diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-10-18 22:25:38 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-10-24 11:24:03 +0100 |
commit | 566c6dca28ea436de791db933f52eba9eef822fb (patch) | |
tree | 8137e0b2710331a71ac9d6028554100782675ba7 /bitbake/lib | |
parent | 57bdcaf4177320cfc0f00ea49ffc166cbdc44d89 (diff) | |
download | poky-566c6dca28ea436de791db933f52eba9eef822fb.tar.gz |
bitbake: toaster/tests/functiona/project_page: Switch to using library create_project function
Switch this test module to use the common project creation code which contains
race fixes. That code requires the database access wrapper be dropped and
we no longer have ordering constraints.
There are two tests that do require database access. Move these to a separate class
and allow database access there. Use ordering constraints to allow them to run
after the main code. They depend on the project creation from the other class which
isn't ideal but good enough for now.
(Bitbake rev: e441bfe98ac41d48692ffbaeec90a9c780337fa4)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib')
-rw-r--r-- | bitbake/lib/toaster/tests/functional/test_project_page.py | 118 |
1 files changed, 42 insertions, 76 deletions
diff --git a/bitbake/lib/toaster/tests/functional/test_project_page.py b/bitbake/lib/toaster/tests/functional/test_project_page.py index 5d10513d9d..40ef5f486a 100644 --- a/bitbake/lib/toaster/tests/functional/test_project_page.py +++ b/bitbake/lib/toaster/tests/functional/test_project_page.py | |||
@@ -7,7 +7,6 @@ | |||
7 | # | 7 | # |
8 | 8 | ||
9 | import os | 9 | import os |
10 | import random | ||
11 | import string | 10 | import string |
12 | from unittest import skip | 11 | from unittest import skip |
13 | import pytest | 12 | import pytest |
@@ -22,58 +21,17 @@ from selenium.webdriver.common.by import By | |||
22 | 21 | ||
23 | from .utils import get_projectId_from_url, wait_until_build, wait_until_build_cancelled | 22 | from .utils import get_projectId_from_url, wait_until_build, wait_until_build_cancelled |
24 | 23 | ||
25 | 24 | class TestProjectPageBase(SeleniumFunctionalTestCase): | |
26 | @pytest.mark.django_db | ||
27 | @pytest.mark.order("last") | ||
28 | class TestProjectPage(SeleniumFunctionalTestCase): | ||
29 | project_id = None | 25 | project_id = None |
30 | PROJECT_NAME = 'TestProjectPage' | 26 | PROJECT_NAME = 'TestProjectPage' |
31 | 27 | ||
32 | def _create_project(self, project_name): | ||
33 | """ Create/Test new project using: | ||
34 | - Project Name: Any string | ||
35 | - Release: Any string | ||
36 | - Merge Toaster settings: True or False | ||
37 | """ | ||
38 | self.get(reverse('newproject')) | ||
39 | self.wait_until_visible('#new-project-name') | ||
40 | self.find("#new-project-name").send_keys(project_name) | ||
41 | select = Select(self.find("#projectversion")) | ||
42 | select.select_by_value('3') | ||
43 | |||
44 | # check merge toaster settings | ||
45 | checkbox = self.find('.checkbox-mergeattr') | ||
46 | if not checkbox.is_selected(): | ||
47 | checkbox.click() | ||
48 | |||
49 | if self.PROJECT_NAME != 'TestProjectPage': | ||
50 | # Reset project name if it's not the default one | ||
51 | self.PROJECT_NAME = 'TestProjectPage' | ||
52 | |||
53 | self.find("#create-project-button").click() | ||
54 | |||
55 | try: | ||
56 | self.wait_until_visible('#hint-error-project-name') | ||
57 | url = reverse('project', args=(TestProjectPage.project_id, )) | ||
58 | self.get(url) | ||
59 | self.wait_until_visible('#config-nav', poll=3) | ||
60 | except TimeoutException: | ||
61 | self.wait_until_visible('#config-nav', poll=3) | ||
62 | |||
63 | def _random_string(self, length): | ||
64 | return ''.join( | ||
65 | random.choice(string.ascii_letters) for _ in range(length) | ||
66 | ) | ||
67 | |||
68 | def _navigate_to_project_page(self): | 28 | def _navigate_to_project_page(self): |
69 | # Navigate to project page | 29 | # Navigate to project page |
70 | if TestProjectPage.project_id is None: | 30 | if TestProjectPageBase.project_id is None: |
71 | self._create_project(project_name=self._random_string(10)) | 31 | TestProjectPageBase.project_id = self.create_new_project(self.PROJECT_NAME, '3', None, True) |
72 | current_url = self.driver.current_url | 32 | |
73 | TestProjectPage.project_id = get_projectId_from_url(current_url) | 33 | url = reverse('project', args=(TestProjectPageBase.project_id,)) |
74 | else: | 34 | self.get(url) |
75 | url = reverse('project', args=(TestProjectPage.project_id,)) | ||
76 | self.get(url) | ||
77 | self.wait_until_visible('#config-nav') | 35 | self.wait_until_visible('#config-nav') |
78 | 36 | ||
79 | def _get_create_builds(self, **kwargs): | 37 | def _get_create_builds(self, **kwargs): |
@@ -81,14 +39,14 @@ class TestProjectPage(SeleniumFunctionalTestCase): | |||
81 | # parameters for builds to associate with the projects | 39 | # parameters for builds to associate with the projects |
82 | now = timezone.now() | 40 | now = timezone.now() |
83 | self.project1_build_success = { | 41 | self.project1_build_success = { |
84 | 'project': Project.objects.get(id=TestProjectPage.project_id), | 42 | 'project': Project.objects.get(id=TestProjectPageBase.project_id), |
85 | 'started_on': now, | 43 | 'started_on': now, |
86 | 'completed_on': now, | 44 | 'completed_on': now, |
87 | 'outcome': Build.SUCCEEDED | 45 | 'outcome': Build.SUCCEEDED |
88 | } | 46 | } |
89 | 47 | ||
90 | self.project1_build_failure = { | 48 | self.project1_build_failure = { |
91 | 'project': Project.objects.get(id=TestProjectPage.project_id), | 49 | 'project': Project.objects.get(id=TestProjectPageBase.project_id), |
92 | 'started_on': now, | 50 | 'started_on': now, |
93 | 'completed_on': now, | 51 | 'completed_on': now, |
94 | 'outcome': Build.FAILED | 52 | 'outcome': Build.FAILED |
@@ -222,6 +180,8 @@ class TestProjectPage(SeleniumFunctionalTestCase): | |||
222 | rows = self.find_all(f'#{table_selector} tbody tr') | 180 | rows = self.find_all(f'#{table_selector} tbody tr') |
223 | self.assertTrue(len(rows) > 0) | 181 | self.assertTrue(len(rows) > 0) |
224 | 182 | ||
183 | class TestProjectPage(TestProjectPageBase): | ||
184 | |||
225 | def test_create_project(self): | 185 | def test_create_project(self): |
226 | """ Create/Test new project using: | 186 | """ Create/Test new project using: |
227 | - Project Name: Any string | 187 | - Project Name: Any string |
@@ -230,26 +190,6 @@ class TestProjectPage(SeleniumFunctionalTestCase): | |||
230 | """ | 190 | """ |
231 | self._create_project(project_name=self.PROJECT_NAME) | 191 | self._create_project(project_name=self.PROJECT_NAME) |
232 | 192 | ||
233 | def test_image_recipe_editColumn(self): | ||
234 | """ Test the edit column feature in image recipe table on project page """ | ||
235 | self._get_create_builds(success=10, failure=10) | ||
236 | |||
237 | url = reverse('projectimagerecipes', args=(TestProjectPage.project_id,)) | ||
238 | self.get(url) | ||
239 | self.wait_until_present('#imagerecipestable tbody tr') | ||
240 | |||
241 | column_list = [ | ||
242 | 'get_description_or_summary', 'layer_version__get_vcs_reference', | ||
243 | 'layer_version__layer__name', 'license', 'recipe-file', 'section', | ||
244 | 'version' | ||
245 | ] | ||
246 | |||
247 | # Check that we can hide the edit column | ||
248 | self._mixin_test_table_edit_column( | ||
249 | 'imagerecipestable', | ||
250 | 'edit-columns-button', | ||
251 | [f'checkbox-{column}' for column in column_list] | ||
252 | ) | ||
253 | 193 | ||
254 | def test_page_header_on_project_page(self): | 194 | def test_page_header_on_project_page(self): |
255 | """ Check page header in project page: | 195 | """ Check page header in project page: |
@@ -379,7 +319,7 @@ class TestProjectPage(SeleniumFunctionalTestCase): | |||
379 | self.assertEqual(config_tab.get_attribute('class'), 'active') | 319 | self.assertEqual(config_tab.get_attribute('class'), 'active') |
380 | self.assertIn('Configuration', str(config_tab.text)) | 320 | self.assertIn('Configuration', str(config_tab.text)) |
381 | self.assertIn( | 321 | self.assertIn( |
382 | f"/toastergui/project/{TestProjectPage.project_id}", str(self.driver.current_url) | 322 | f"/toastergui/project/{TestProjectPageBase.project_id}", str(self.driver.current_url) |
383 | ) | 323 | ) |
384 | 324 | ||
385 | def get_tabs(): | 325 | def get_tabs(): |
@@ -402,7 +342,7 @@ class TestProjectPage(SeleniumFunctionalTestCase): | |||
402 | check_tab_link( | 342 | check_tab_link( |
403 | 1, | 343 | 1, |
404 | 'Builds', | 344 | 'Builds', |
405 | f"/toastergui/project/{TestProjectPage.project_id}/builds" | 345 | f"/toastergui/project/{TestProjectPageBase.project_id}/builds" |
406 | ) | 346 | ) |
407 | 347 | ||
408 | # check "Import layers" tab | 348 | # check "Import layers" tab |
@@ -411,7 +351,7 @@ class TestProjectPage(SeleniumFunctionalTestCase): | |||
411 | check_tab_link( | 351 | check_tab_link( |
412 | 2, | 352 | 2, |
413 | 'Import layer', | 353 | 'Import layer', |
414 | f"/toastergui/project/{TestProjectPage.project_id}/importlayer" | 354 | f"/toastergui/project/{TestProjectPageBase.project_id}/importlayer" |
415 | ) | 355 | ) |
416 | 356 | ||
417 | # check "New custom image" tab | 357 | # check "New custom image" tab |
@@ -420,7 +360,7 @@ class TestProjectPage(SeleniumFunctionalTestCase): | |||
420 | check_tab_link( | 360 | check_tab_link( |
421 | 3, | 361 | 3, |
422 | 'New custom image', | 362 | 'New custom image', |
423 | f"/toastergui/project/{TestProjectPage.project_id}/newcustomimage" | 363 | f"/toastergui/project/{TestProjectPageBase.project_id}/newcustomimage" |
424 | ) | 364 | ) |
425 | 365 | ||
426 | # check search box can be use to build recipes | 366 | # check search box can be use to build recipes |
@@ -766,6 +706,10 @@ class TestProjectPage(SeleniumFunctionalTestCase): | |||
766 | # Check layer description | 706 | # Check layer description |
767 | self.assertIn("Description", section.text) | 707 | self.assertIn("Description", section.text) |
768 | 708 | ||
709 | @pytest.mark.django_db | ||
710 | @pytest.mark.order("last") | ||
711 | class TestProjectPageRecipes(TestProjectPageBase): | ||
712 | |||
769 | def test_single_recipe_page(self): | 713 | def test_single_recipe_page(self): |
770 | """ Test recipe page | 714 | """ Test recipe page |
771 | - Check if title is displayed | 715 | - Check if title is displayed |
@@ -777,9 +721,9 @@ class TestProjectPage(SeleniumFunctionalTestCase): | |||
777 | # Use a recipe which is likely to exist in the layer index but not enabled | 721 | # Use a recipe which is likely to exist in the layer index but not enabled |
778 | # in poky out the box - xen-image-minimal from meta-virtualization | 722 | # in poky out the box - xen-image-minimal from meta-virtualization |
779 | self._navigate_to_project_page() | 723 | self._navigate_to_project_page() |
780 | prj = Project.objects.get(pk=TestProjectPage.project_id) | 724 | prj = Project.objects.get(pk=TestProjectPageBase.project_id) |
781 | recipe_id = prj.get_all_compatible_recipes().get(name="xen-image-minimal").pk | 725 | recipe_id = prj.get_all_compatible_recipes().get(name="xen-image-minimal").pk |
782 | url = reverse("recipedetails", args=(TestProjectPage.project_id, recipe_id)) | 726 | url = reverse("recipedetails", args=(TestProjectPageBase.project_id, recipe_id)) |
783 | self.get(url) | 727 | self.get(url) |
784 | self.wait_until_visible('.page-header') | 728 | self.wait_until_visible('.page-header') |
785 | # check title is displayed | 729 | # check title is displayed |
@@ -802,3 +746,25 @@ class TestProjectPage(SeleniumFunctionalTestCase): | |||
802 | self.assertIn("Approx. packages included", section.text) | 746 | self.assertIn("Approx. packages included", section.text) |
803 | self.assertIn("Approx. package size", section.text) | 747 | self.assertIn("Approx. package size", section.text) |
804 | self.assertIn("Recipe file", section.text) | 748 | self.assertIn("Recipe file", section.text) |
749 | |||
750 | def test_image_recipe_editColumn(self): | ||
751 | """ Test the edit column feature in image recipe table on project page """ | ||
752 | self._get_create_builds(success=10, failure=10) | ||
753 | |||
754 | url = reverse('projectimagerecipes', args=(TestProjectPageBase.project_id,)) | ||
755 | self.get(url) | ||
756 | self.wait_until_present('#imagerecipestable tbody tr') | ||
757 | |||
758 | column_list = [ | ||
759 | 'get_description_or_summary', 'layer_version__get_vcs_reference', | ||
760 | 'layer_version__layer__name', 'license', 'recipe-file', 'section', | ||
761 | 'version' | ||
762 | ] | ||
763 | |||
764 | # Check that we can hide the edit column | ||
765 | self._mixin_test_table_edit_column( | ||
766 | 'imagerecipestable', | ||
767 | 'edit-columns-button', | ||
768 | [f'checkbox-{column}' for column in column_list] | ||
769 | ) | ||
770 | |||