diff options
Diffstat (limited to 'import-layers/yocto-poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py')
-rw-r--r-- | import-layers/yocto-poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py | 178 |
1 files changed, 137 insertions, 41 deletions
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py b/import-layers/yocto-poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py index 5e0874947..f8ccb5452 100644 --- a/import-layers/yocto-poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py +++ b/import-layers/yocto-poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py @@ -22,10 +22,10 @@ from django.core.urlresolvers import reverse from django.utils import timezone -from selenium_helpers import SeleniumTestCase +from tests.browser.selenium_helpers import SeleniumTestCase 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): """ Tests for the build dashboard /build/X """ @@ -42,11 +42,27 @@ class TestBuildDashboardPage(SeleniumTestCase): self.build1 = Build.objects.create(project=project, started_on=now, - completed_on=now) + completed_on=now, + outcome=Build.SUCCEEDED) self.build2 = Build.objects.create(project=project, started_on=now, - completed_on=now) + completed_on=now, + outcome=Build.SUCCEEDED) + + self.build3 = Build.objects.create(project=project, + started_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 msg1 = 'an exception was thrown' @@ -64,6 +80,22 @@ class TestBuildDashboardPage(SeleniumTestCase): 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 # custom image buttons layer = Layer.objects.create(name='alayer') @@ -71,6 +103,11 @@ class TestBuildDashboardPage(SeleniumTestCase): layer=layer, build=self.build1 ) + # non-image recipes related to a build, for testing the new custom + # image button + layer_version2 = Layer_Version.objects.create(layer=layer, + build=self.build3) + # image recipes self.image_recipe1 = Recipe.objects.create( name='recipeA', @@ -140,38 +177,47 @@ class TestBuildDashboardPage(SeleniumTestCase): dashboard for the Build object build """ self._get_build_dashboard(build) - return self.find_all('#errors div.alert-error') + return self.find_all('#errors div.alert-danger') - def _check_for_log_message(self, build, log_message): - """ - Check whether the LogMessage instance <log_message> is - represented as an HTML error in the dashboard page for the Build object - build + def _check_for_log_message(self, message_elements, log_message): """ - errors = self._get_build_dashboard_errors(build) - self.assertEqual(len(errors), 2) + 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_id = str(log_message.id) + expected_pk = str(log_message.pk) found = False - for error in errors: - error_text = error.find_element_by_tag_name('pre').text - text_matches = (error_text == expected_text) + for element in message_elements: + log_message_text = element.find_element_by_tag_name('pre').text.strip() + text_matches = (log_message_text == expected_text) - error_id = error.get_attribute('data-error') - id_matches = (error_id == expected_id) + 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, 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) + 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 + represented as an HTML error in the dashboard page for the Build object + build + """ + errors = self._get_build_dashboard_errors(build) + self._check_for_log_message(errors, log_message) def _check_labels_in_modal(self, modal, expected): """ @@ -179,37 +225,29 @@ class TestBuildDashboardPage(SeleniumTestCase): the WebElement modal match the list of text values in expected """ # labels containing the radio buttons we're testing for - labels = modal.find_elements_by_tag_name('label') - - # because the label content has the structure - # label text - # <input...> - # we have to regex on its innerHTML, as we can't just retrieve the - # "label text" on its own via the Selenium API - labels_text = sorted(map( - lambda label: label.get_attribute('innerHTML'), labels - )) - - expected = sorted(expected) + labels = modal.find_elements_by_css_selector(".radio") + labels_text = [lab.text for lab in labels] self.assertEqual(len(labels_text), len(expected)) - for idx, label_text in enumerate(labels_text): - self.assertRegexpMatches(label_text, expected[idx]) + for expected_text in expected: + self.assertTrue(expected_text in labels_text, + "Could not find %s in %s" % (expected_text, + labels_text)) def test_exceptions_show_as_errors(self): """ LogMessages with level EXCEPTION should display in the errors 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): """ LogMessages with level CRITICAL should display in the errors 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): """ @@ -217,7 +255,13 @@ class TestBuildDashboardPage(SeleniumTestCase): the user choose one of them to edit """ self._get_build_dashboard(self.build1) + + # click the "edit custom image" button, which populates the modal + selector = '[data-role="edit-custom-image-trigger"]' + self.click(selector) + modal = self.driver.find_element_by_id('edit-custom-image-modal') + self.wait_until_visible("#edit-custom-image-modal") # recipes we expect to see in the edit custom image modal expected_recipes = [ @@ -235,10 +279,11 @@ class TestBuildDashboardPage(SeleniumTestCase): self._get_build_dashboard(self.build1) # click the "new custom image" button, which populates the modal - selector = '[data-role="new-custom-image-trigger"] button' + selector = '[data-role="new-custom-image-trigger"]' self.click(selector) modal = self.driver.find_element_by_id('new-custom-image-modal') + self.wait_until_visible("#new-custom-image-modal") # recipes we expect to see in the new custom image modal expected_recipes = [ @@ -249,3 +294,54 @@ class TestBuildDashboardPage(SeleniumTestCase): ] self._check_labels_in_modal(modal, expected_recipes) + + def test_new_custom_image_button_no_image(self): + """ + Check that a build which builds non-image recipes doesn't show + the new custom image button on the dashboard. + """ + self._get_build_dashboard(self.build3) + selector = '[data-role="new-custom-image-trigger"]' + self.assertFalse(self.element_exists(selector), + 'new custom image button should not show for builds which ' \ + '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) |