diff options
author | Alassane Yattara <alassane.yattara@savoirfairelinux.com> | 2023-11-21 14:51:25 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2023-11-23 12:06:06 +0000 |
commit | 363f19e75a19f3e9d08292602e40bfe784972747 (patch) | |
tree | dc970bd0dbd4598f2d1c8436ecbdd77be58c1379 /bitbake/lib | |
parent | fd740a6b6dc37d0a872f4013e2cf34501064f269 (diff) | |
download | poky-363f19e75a19f3e9d08292602e40bfe784972747.tar.gz |
bitbake: toaster/tests: Add UI TestCase - Test project config tab navigation:
- Check if the menu is displayed and contains the right elements:
- Configuration
- COMPATIBLE METADATA
- Custom images
- Image recipes
- Software recipes
- Machines
- Layers
- Distro
- EXTRA CONFIGURATION
- Bitbake variables
- Actions
- Delete project
(Bitbake rev: a12fe481aac82e1feebdb56afb67ba77a8904995)
Signed-off-by: Alassane Yattara <alassane.yattara@savoirfairelinux.com>
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_tab_config.py | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/bitbake/lib/toaster/tests/functional/test_project_page_tab_config.py b/bitbake/lib/toaster/tests/functional/test_project_page_tab_config.py new file mode 100644 index 0000000000..f0c6aacfc8 --- /dev/null +++ b/bitbake/lib/toaster/tests/functional/test_project_page_tab_config.py | |||
@@ -0,0 +1,176 @@ | |||
1 | #! /usr/bin/env python3 # | ||
2 | # BitBake Toaster UI tests implementation | ||
3 | # | ||
4 | # Copyright (C) 2023 Savoir-faire Linux | ||
5 | # | ||
6 | # SPDX-License-Identifier: GPL-2.0-only | ||
7 | # | ||
8 | |||
9 | from time import sleep | ||
10 | import pytest | ||
11 | from django.urls import reverse | ||
12 | from selenium.webdriver.support.select import Select | ||
13 | from selenium.common.exceptions import NoSuchElementException | ||
14 | from tests.functional.functional_helpers import SeleniumFunctionalTestCase | ||
15 | from selenium.webdriver.common.by import By | ||
16 | |||
17 | |||
18 | @pytest.mark.django_db | ||
19 | class TestProjectConfigTab(SeleniumFunctionalTestCase): | ||
20 | |||
21 | def setUp(self): | ||
22 | self.recipe = None | ||
23 | super().setUp() | ||
24 | release = '3' | ||
25 | project_name = 'projectmaster' | ||
26 | self._create_test_new_project( | ||
27 | project_name, | ||
28 | release, | ||
29 | False, | ||
30 | ) | ||
31 | |||
32 | def _create_test_new_project( | ||
33 | self, | ||
34 | project_name, | ||
35 | release, | ||
36 | merge_toaster_settings, | ||
37 | ): | ||
38 | """ Create/Test new project using: | ||
39 | - Project Name: Any string | ||
40 | - Release: Any string | ||
41 | - Merge Toaster settings: True or False | ||
42 | """ | ||
43 | self.get(reverse('newproject')) | ||
44 | self.driver.find_element(By.ID, | ||
45 | "new-project-name").send_keys(project_name) | ||
46 | |||
47 | select = Select(self.find('#projectversion')) | ||
48 | select.select_by_value(release) | ||
49 | |||
50 | # check merge toaster settings | ||
51 | checkbox = self.find('.checkbox-mergeattr') | ||
52 | if merge_toaster_settings: | ||
53 | if not checkbox.is_selected(): | ||
54 | checkbox.click() | ||
55 | else: | ||
56 | if checkbox.is_selected(): | ||
57 | checkbox.click() | ||
58 | |||
59 | self.driver.find_element(By.ID, "create-project-button").click() | ||
60 | |||
61 | @classmethod | ||
62 | def _wait_until_build(cls, state): | ||
63 | while True: | ||
64 | try: | ||
65 | last_build_state = cls.driver.find_element( | ||
66 | By.XPATH, | ||
67 | '//*[@id="latest-builds"]/div[1]//div[@class="build-state"]', | ||
68 | ) | ||
69 | build_state = last_build_state.get_attribute( | ||
70 | 'data-build-state') | ||
71 | state_text = state.lower().split() | ||
72 | if any(x in str(build_state).lower() for x in state_text): | ||
73 | break | ||
74 | except NoSuchElementException: | ||
75 | continue | ||
76 | sleep(1) | ||
77 | |||
78 | def _create_builds(self): | ||
79 | # check search box can be use to build recipes | ||
80 | search_box = self.find('#build-input') | ||
81 | search_box.send_keys('core-image-minimal') | ||
82 | self.find('#build-button').click() | ||
83 | sleep(1) | ||
84 | self.wait_until_visible('#latest-builds') | ||
85 | # loop until reach the parsing state | ||
86 | self._wait_until_build('parsing starting cloning') | ||
87 | lastest_builds = self.driver.find_elements( | ||
88 | By.XPATH, | ||
89 | '//div[@id="latest-builds"]/div', | ||
90 | ) | ||
91 | last_build = lastest_builds[0] | ||
92 | self.assertTrue( | ||
93 | 'core-image-minimal' in str(last_build.text) | ||
94 | ) | ||
95 | cancel_button = last_build.find_element( | ||
96 | By.XPATH, | ||
97 | '//span[@class="cancel-build-btn pull-right alert-link"]', | ||
98 | ) | ||
99 | cancel_button.click() | ||
100 | sleep(1) | ||
101 | self._wait_until_build('cancelled') | ||
102 | |||
103 | def _get_tabs(self): | ||
104 | # tabs links list | ||
105 | return self.driver.find_elements( | ||
106 | By.XPATH, | ||
107 | '//div[@id="project-topbar"]//li' | ||
108 | ) | ||
109 | |||
110 | def _get_config_nav_item(self, index): | ||
111 | config_nav = self.find('#config-nav') | ||
112 | return config_nav.find_elements(By.TAG_NAME, 'li')[index] | ||
113 | |||
114 | def test_project_config_nav(self): | ||
115 | """ Test project config tab navigation: | ||
116 | - Check if the menu is displayed and contains the right elements: | ||
117 | - Configuration | ||
118 | - COMPATIBLE METADATA | ||
119 | - Custom images | ||
120 | - Image recipes | ||
121 | - Software recipes | ||
122 | - Machines | ||
123 | - Layers | ||
124 | - Distro | ||
125 | - EXTRA CONFIGURATION | ||
126 | - Bitbake variables | ||
127 | - Actions | ||
128 | - Delete project | ||
129 | """ | ||
130 | # navigate to the project page | ||
131 | url = reverse("project", args=(1,)) | ||
132 | self.get(url) | ||
133 | |||
134 | # check if the menu is displayed | ||
135 | self.wait_until_visible('#config-nav') | ||
136 | |||
137 | def _get_config_nav_item(index): | ||
138 | config_nav = self.find('#config-nav') | ||
139 | return config_nav.find_elements(By.TAG_NAME, 'li')[index] | ||
140 | |||
141 | def check_config_nav_item(index, item_name, url): | ||
142 | item = _get_config_nav_item(index) | ||
143 | self.assertTrue(item_name in item.text) | ||
144 | self.assertTrue(item.get_attribute('class') == 'active') | ||
145 | self.assertTrue(url in self.driver.current_url) | ||
146 | |||
147 | # check if the menu contains the right elements | ||
148 | # COMPATIBLE METADATA | ||
149 | compatible_metadata = _get_config_nav_item(1) | ||
150 | self.assertTrue( | ||
151 | "compatible metadata" in compatible_metadata.text.lower() | ||
152 | ) | ||
153 | # EXTRA CONFIGURATION | ||
154 | extra_configuration = _get_config_nav_item(8) | ||
155 | self.assertTrue( | ||
156 | "extra configuration" in extra_configuration.text.lower() | ||
157 | ) | ||
158 | # Actions | ||
159 | actions = _get_config_nav_item(10) | ||
160 | self.assertTrue("actions" in str(actions.text).lower()) | ||
161 | |||
162 | conf_nav_list = [ | ||
163 | [0, 'Configuration', f"/toastergui/project/1"], # config | ||
164 | [2, 'Custom images', f"/toastergui/project/1/customimages"], # custom images | ||
165 | [3, 'Image recipes', f"/toastergui/project/1/images"], # image recipes | ||
166 | [4, 'Software recipes', f"/toastergui/project/1/softwarerecipes"], # software recipes | ||
167 | [5, 'Machines', f"/toastergui/project/1/machines"], # machines | ||
168 | [6, 'Layers', f"/toastergui/project/1/layers"], # layers | ||
169 | [7, 'Distro', f"/toastergui/project/1/distro"], # distro | ||
170 | [9, 'BitBake variables', f"/toastergui/project/1/configuration"], # bitbake variables | ||
171 | ] | ||
172 | for index, item_name, url in conf_nav_list: | ||
173 | item = _get_config_nav_item(index) | ||
174 | if item.get_attribute('class') != 'active': | ||
175 | item.click() | ||
176 | check_config_nav_item(index, item_name, url) | ||