mirror of
https://git.yoctoproject.org/poky
synced 2026-09-19 00:49:33 +02:00
bitbake: toaster-tests: add tests for build dashboard menu and summary visibility
Test that the build dashboard only shows a menu and a build summary area if a build has properly "started" (i.e. has at least one Variable object associated with it). [YOCTO #8443] (Bitbake rev: 9e16f76fb254ae967ded6c21251243b2af9b16b6) Signed-off-by: Elliot Smith <elliot.smith@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
committed by
Richard Purdie
parent
504a85822e
commit
36f71db680
@@ -25,7 +25,7 @@ from django.utils import timezone
|
|||||||
from tests.browser.selenium_helpers import SeleniumTestCase
|
from tests.browser.selenium_helpers import SeleniumTestCase
|
||||||
|
|
||||||
from orm.models import Project, Release, BitbakeVersion, Build, LogMessage
|
from orm.models import Project, Release, BitbakeVersion, Build, LogMessage
|
||||||
from orm.models import Layer, Layer_Version, Recipe, CustomImageRecipe
|
from orm.models import Layer, Layer_Version, Recipe, CustomImageRecipe, Variable
|
||||||
|
|
||||||
class TestBuildDashboardPage(SeleniumTestCase):
|
class TestBuildDashboardPage(SeleniumTestCase):
|
||||||
""" Tests for the build dashboard /build/X """
|
""" Tests for the build dashboard /build/X """
|
||||||
@@ -42,15 +42,27 @@ class TestBuildDashboardPage(SeleniumTestCase):
|
|||||||
|
|
||||||
self.build1 = Build.objects.create(project=project,
|
self.build1 = Build.objects.create(project=project,
|
||||||
started_on=now,
|
started_on=now,
|
||||||
completed_on=now)
|
completed_on=now,
|
||||||
|
outcome=Build.SUCCEEDED)
|
||||||
|
|
||||||
self.build2 = Build.objects.create(project=project,
|
self.build2 = Build.objects.create(project=project,
|
||||||
started_on=now,
|
started_on=now,
|
||||||
completed_on=now)
|
completed_on=now,
|
||||||
|
outcome=Build.SUCCEEDED)
|
||||||
|
|
||||||
self.build3 = Build.objects.create(project=project,
|
self.build3 = Build.objects.create(project=project,
|
||||||
started_on=now,
|
started_on=now,
|
||||||
completed_on=now)
|
completed_on=now,
|
||||||
|
outcome=Build.FAILED)
|
||||||
|
|
||||||
|
# add Variable objects to the successful builds, as this is the criterion
|
||||||
|
# used to determine whether the left-hand panel should be displayed
|
||||||
|
Variable.objects.create(build=self.build1,
|
||||||
|
variable_name='Foo',
|
||||||
|
variable_value='Bar')
|
||||||
|
Variable.objects.create(build=self.build2,
|
||||||
|
variable_name='Foo',
|
||||||
|
variable_value='Bar')
|
||||||
|
|
||||||
# exception
|
# exception
|
||||||
msg1 = 'an exception was thrown'
|
msg1 = 'an exception was thrown'
|
||||||
@@ -68,6 +80,22 @@ class TestBuildDashboardPage(SeleniumTestCase):
|
|||||||
message=msg2
|
message=msg2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# error on the failed build
|
||||||
|
msg3 = 'an error occurred'
|
||||||
|
self.error_message = LogMessage.objects.create(
|
||||||
|
build=self.build3,
|
||||||
|
level=LogMessage.ERROR,
|
||||||
|
message=msg3
|
||||||
|
)
|
||||||
|
|
||||||
|
# warning on the failed build
|
||||||
|
msg4 = 'DANGER WILL ROBINSON'
|
||||||
|
self.warning_message = LogMessage.objects.create(
|
||||||
|
build=self.build3,
|
||||||
|
level=LogMessage.WARNING,
|
||||||
|
message=msg4
|
||||||
|
)
|
||||||
|
|
||||||
# recipes related to the build, for testing the edit custom image/new
|
# recipes related to the build, for testing the edit custom image/new
|
||||||
# custom image buttons
|
# custom image buttons
|
||||||
layer = Layer.objects.create(name='alayer')
|
layer = Layer.objects.create(name='alayer')
|
||||||
@@ -151,36 +179,45 @@ class TestBuildDashboardPage(SeleniumTestCase):
|
|||||||
self._get_build_dashboard(build)
|
self._get_build_dashboard(build)
|
||||||
return self.find_all('#errors div.alert-danger')
|
return self.find_all('#errors div.alert-danger')
|
||||||
|
|
||||||
def _check_for_log_message(self, build, log_message):
|
def _check_for_log_message(self, message_elements, log_message):
|
||||||
|
"""
|
||||||
|
Check that the LogMessage <log_message> has a representation in
|
||||||
|
the HTML elements <message_elements>.
|
||||||
|
|
||||||
|
message_elements: WebElements representing the log messages shown
|
||||||
|
in the build dashboard; each should have a <pre> element inside
|
||||||
|
it with a data-log-message-id attribute
|
||||||
|
|
||||||
|
log_message: orm.models.LogMessage instance
|
||||||
|
"""
|
||||||
|
expected_text = log_message.message
|
||||||
|
expected_pk = str(log_message.pk)
|
||||||
|
|
||||||
|
found = False
|
||||||
|
for element in message_elements:
|
||||||
|
log_message_text = element.find_element_by_tag_name('pre').text.strip()
|
||||||
|
text_matches = (log_message_text == expected_text)
|
||||||
|
|
||||||
|
log_message_pk = element.get_attribute('data-log-message-id')
|
||||||
|
id_matches = (log_message_pk == expected_pk)
|
||||||
|
|
||||||
|
if text_matches and id_matches:
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
template_vars = (expected_text, expected_pk)
|
||||||
|
assertion_failed_msg = 'message not found: ' \
|
||||||
|
'expected text "%s" and ID %s' % template_vars
|
||||||
|
self.assertTrue(found, assertion_failed_msg)
|
||||||
|
|
||||||
|
def _check_for_error_message(self, build, log_message):
|
||||||
"""
|
"""
|
||||||
Check whether the LogMessage instance <log_message> is
|
Check whether the LogMessage instance <log_message> is
|
||||||
represented as an HTML error in the dashboard page for the Build object
|
represented as an HTML error in the dashboard page for the Build object
|
||||||
build
|
build
|
||||||
"""
|
"""
|
||||||
errors = self._get_build_dashboard_errors(build)
|
errors = self._get_build_dashboard_errors(build)
|
||||||
self.assertEqual(len(errors), 2)
|
self._check_for_log_message(errors, log_message)
|
||||||
|
|
||||||
expected_text = log_message.message
|
|
||||||
expected_id = str(log_message.id)
|
|
||||||
|
|
||||||
found = False
|
|
||||||
for error in errors:
|
|
||||||
error_text = error.find_element_by_tag_name('pre').text
|
|
||||||
text_matches = (error_text == expected_text)
|
|
||||||
|
|
||||||
error_id = error.get_attribute('data-error')
|
|
||||||
id_matches = (error_id == expected_id)
|
|
||||||
|
|
||||||
if text_matches and id_matches:
|
|
||||||
found = True
|
|
||||||
break
|
|
||||||
|
|
||||||
template_vars = (expected_text, error_text,
|
|
||||||
expected_id, error_id)
|
|
||||||
assertion_error_msg = 'exception not found as error: ' \
|
|
||||||
'expected text "%s" and got "%s"; ' \
|
|
||||||
'expected ID %s and got %s' % template_vars
|
|
||||||
self.assertTrue(found, assertion_error_msg)
|
|
||||||
|
|
||||||
def _check_labels_in_modal(self, modal, expected):
|
def _check_labels_in_modal(self, modal, expected):
|
||||||
"""
|
"""
|
||||||
@@ -203,14 +240,14 @@ class TestBuildDashboardPage(SeleniumTestCase):
|
|||||||
LogMessages with level EXCEPTION should display in the errors
|
LogMessages with level EXCEPTION should display in the errors
|
||||||
section of the page
|
section of the page
|
||||||
"""
|
"""
|
||||||
self._check_for_log_message(self.build1, self.exception_message)
|
self._check_for_error_message(self.build1, self.exception_message)
|
||||||
|
|
||||||
def test_criticals_show_as_errors(self):
|
def test_criticals_show_as_errors(self):
|
||||||
"""
|
"""
|
||||||
LogMessages with level CRITICAL should display in the errors
|
LogMessages with level CRITICAL should display in the errors
|
||||||
section of the page
|
section of the page
|
||||||
"""
|
"""
|
||||||
self._check_for_log_message(self.build1, self.critical_message)
|
self._check_for_error_message(self.build1, self.critical_message)
|
||||||
|
|
||||||
def test_edit_custom_image_button(self):
|
def test_edit_custom_image_button(self):
|
||||||
"""
|
"""
|
||||||
@@ -268,3 +305,43 @@ class TestBuildDashboardPage(SeleniumTestCase):
|
|||||||
self.assertFalse(self.element_exists(selector),
|
self.assertFalse(self.element_exists(selector),
|
||||||
'new custom image button should not show for builds which ' \
|
'new custom image button should not show for builds which ' \
|
||||||
'don\'t have any image recipes')
|
'don\'t have any image recipes')
|
||||||
|
|
||||||
|
def test_left_panel(self):
|
||||||
|
""""
|
||||||
|
Builds which succeed should have a left panel and a build summary
|
||||||
|
"""
|
||||||
|
self._get_build_dashboard(self.build1)
|
||||||
|
|
||||||
|
left_panel = self.find_all('#nav')
|
||||||
|
self.assertEqual(len(left_panel), 1)
|
||||||
|
|
||||||
|
build_summary = self.find_all('[data-role="build-summary-heading"]')
|
||||||
|
self.assertEqual(len(build_summary), 1)
|
||||||
|
|
||||||
|
def test_failed_no_left_panel(self):
|
||||||
|
"""
|
||||||
|
Builds which fail should have no left panel and no build summary
|
||||||
|
"""
|
||||||
|
self._get_build_dashboard(self.build3)
|
||||||
|
|
||||||
|
left_panel = self.find_all('#nav')
|
||||||
|
self.assertEqual(len(left_panel), 0)
|
||||||
|
|
||||||
|
build_summary = self.find_all('[data-role="build-summary-heading"]')
|
||||||
|
self.assertEqual(len(build_summary), 0)
|
||||||
|
|
||||||
|
def test_failed_shows_errors_and_warnings(self):
|
||||||
|
"""
|
||||||
|
Failed builds should still show error and warning messages
|
||||||
|
"""
|
||||||
|
self._get_build_dashboard(self.build3)
|
||||||
|
|
||||||
|
errors = self.find_all('#errors div.alert-danger')
|
||||||
|
self._check_for_log_message(errors, self.error_message)
|
||||||
|
|
||||||
|
# expand the warnings area
|
||||||
|
self.click('#warning-toggle')
|
||||||
|
self.wait_until_visible('#warnings div.alert-warning')
|
||||||
|
|
||||||
|
warnings = self.find_all('#warnings div.alert-warning')
|
||||||
|
self._check_for_log_message(warnings, self.warning_message)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ from tests.browser.selenium_helpers import SeleniumTestCase
|
|||||||
|
|
||||||
from orm.models import Project, Release, BitbakeVersion, Build, Target, Package
|
from orm.models import Project, Release, BitbakeVersion, Build, Target, Package
|
||||||
from orm.models import Target_Image_File, TargetSDKFile, TargetKernelFile
|
from orm.models import Target_Image_File, TargetSDKFile, TargetKernelFile
|
||||||
from orm.models import Target_Installed_Package
|
from orm.models import Target_Installed_Package, Variable
|
||||||
|
|
||||||
class TestBuildDashboardPageArtifacts(SeleniumTestCase):
|
class TestBuildDashboardPageArtifacts(SeleniumTestCase):
|
||||||
""" Tests for artifacts on the build dashboard /build/X """
|
""" Tests for artifacts on the build dashboard /build/X """
|
||||||
@@ -151,6 +151,11 @@ class TestBuildDashboardPageArtifacts(SeleniumTestCase):
|
|||||||
started_on=now, completed_on=timezone.now(),
|
started_on=now, completed_on=timezone.now(),
|
||||||
outcome=Build.SUCCEEDED)
|
outcome=Build.SUCCEEDED)
|
||||||
|
|
||||||
|
# add a variable to the build so that it counts as "started"
|
||||||
|
Variable.objects.create(build=build,
|
||||||
|
variable_name='Christopher',
|
||||||
|
variable_value='Lee')
|
||||||
|
|
||||||
target = Target.objects.create(is_image=True, build=build,
|
target = Target.objects.create(is_image=True, build=build,
|
||||||
task='', target='core-image-minimal',
|
task='', target='core-image-minimal',
|
||||||
license_manifest_path='/home/foo/license.manifest',
|
license_manifest_path='/home/foo/license.manifest',
|
||||||
|
|||||||
Reference in New Issue
Block a user