From eb8dc40360f0cfef56fb6947cc817a547d6d9bc6 Mon Sep 17 00:00:00 2001 From: Dave Cobbley Date: Tue, 14 Aug 2018 10:05:37 -0700 Subject: [Subtree] Removing import-layers directory As part of the move to subtrees, need to bring all the import layers content to the top level. Change-Id: I4a163d10898cbc6e11c27f776f60e1a470049d8f Signed-off-by: Dave Cobbley Signed-off-by: Brad Bishop --- .../tests/browser/test_builddashboard_page.py | 347 +++++++++++++++++++++ 1 file changed, 347 insertions(+) create mode 100644 poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py (limited to 'poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py') diff --git a/poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py b/poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py new file mode 100644 index 000000000..f8ccb5452 --- /dev/null +++ b/poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py @@ -0,0 +1,347 @@ +#! /usr/bin/env python +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# BitBake Toaster Implementation +# +# Copyright (C) 2013-2016 Intel Corporation +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +from django.core.urlresolvers import reverse +from django.utils import timezone + +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, Variable + +class TestBuildDashboardPage(SeleniumTestCase): + """ Tests for the build dashboard /build/X """ + + def setUp(self): + bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/', + branch='master', dirpath="") + release = Release.objects.create(name='release1', + bitbake_version=bbv) + project = Project.objects.create_project(name='test project', + release=release) + + now = timezone.now() + + self.build1 = Build.objects.create(project=project, + started_on=now, + completed_on=now, + outcome=Build.SUCCEEDED) + + self.build2 = Build.objects.create(project=project, + started_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' + self.exception_message = LogMessage.objects.create( + build=self.build1, + level=LogMessage.EXCEPTION, + message=msg1 + ) + + # critical + msg2 = 'a critical error occurred' + self.critical_message = LogMessage.objects.create( + build=self.build1, + level=LogMessage.CRITICAL, + 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') + layer_version = Layer_Version.objects.create( + 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', + layer_version=layer_version, + file_path='/foo/recipeA.bb', + is_image=True + ) + self.image_recipe2 = Recipe.objects.create( + name='recipeB', + layer_version=layer_version, + file_path='/foo/recipeB.bb', + is_image=True + ) + + # custom image recipes for this project + self.custom_image_recipe1 = CustomImageRecipe.objects.create( + name='customRecipeY', + project=project, + layer_version=layer_version, + file_path='/foo/customRecipeY.bb', + base_recipe=self.image_recipe1, + is_image=True + ) + self.custom_image_recipe2 = CustomImageRecipe.objects.create( + name='customRecipeZ', + project=project, + layer_version=layer_version, + file_path='/foo/customRecipeZ.bb', + base_recipe=self.image_recipe2, + is_image=True + ) + + # custom image recipe for a different project (to test filtering + # of image recipes and custom image recipes is correct: this shouldn't + # show up in either query against self.build1) + self.custom_image_recipe3 = CustomImageRecipe.objects.create( + name='customRecipeOmega', + project=Project.objects.create(name='baz', release=release), + layer_version=Layer_Version.objects.create( + layer=layer, build=self.build2 + ), + file_path='/foo/customRecipeOmega.bb', + base_recipe=self.image_recipe2, + is_image=True + ) + + # another non-image recipe (to test filtering of image recipes and + # custom image recipes is correct: this shouldn't show up in either + # for any build) + self.non_image_recipe = Recipe.objects.create( + name='nonImageRecipe', + layer_version=layer_version, + file_path='/foo/nonImageRecipe.bb', + is_image=False + ) + + def _get_build_dashboard(self, build): + """ + Navigate to the build dashboard for build + """ + url = reverse('builddashboard', args=(build.id,)) + self.get(url) + + def _get_build_dashboard_errors(self, build): + """ + Get a list of HTML fragments representing the errors on the + dashboard for the Build object build + """ + self._get_build_dashboard(build) + return self.find_all('#errors div.alert-danger') + + def _check_for_log_message(self, message_elements, log_message): + """ + Check that the LogMessage has a representation in + the HTML elements . + + message_elements: WebElements representing the log messages shown + in the build dashboard; each should have a
 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  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):
+        """
+        Check that the text values of the