summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/tests/functional/test_project_config.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/toaster/tests/functional/test_project_config.py')
-rw-r--r--bitbake/lib/toaster/tests/functional/test_project_config.py341
1 files changed, 341 insertions, 0 deletions
diff --git a/bitbake/lib/toaster/tests/functional/test_project_config.py b/bitbake/lib/toaster/tests/functional/test_project_config.py
new file mode 100644
index 0000000000..dbee36aa4e
--- /dev/null
+++ b/bitbake/lib/toaster/tests/functional/test_project_config.py
@@ -0,0 +1,341 @@
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
9import string
10import random
11import pytest
12from django.urls import reverse
13from selenium.webdriver import Keys
14from selenium.webdriver.support.select import Select
15from selenium.common.exceptions import TimeoutException
16from tests.functional.functional_helpers import SeleniumFunctionalTestCase
17from selenium.webdriver.common.by import By
18
19from .utils import get_projectId_from_url
20
21
22@pytest.mark.django_db
23@pytest.mark.order("last")
24class TestProjectConfig(SeleniumFunctionalTestCase):
25 project_id = None
26 PROJECT_NAME = 'TestProjectConfig'
27 INVALID_PATH_START_TEXT = 'The directory path should either start with a /'
28 INVALID_PATH_CHAR_TEXT = 'The directory path cannot include spaces or ' \
29 'any of these characters'
30
31 def _create_project(self, project_name):
32 """ Create/Test new project using:
33 - Project Name: Any string
34 - Release: Any string
35 - Merge Toaster settings: True or False
36 """
37 self.get(reverse('newproject'))
38 self.wait_until_visible('#new-project-name', poll=2)
39 self.find("#new-project-name").send_keys(project_name)
40 select = Select(self.find("#projectversion"))
41 select.select_by_value('3')
42
43 # check merge toaster settings
44 checkbox = self.find('.checkbox-mergeattr')
45 if not checkbox.is_selected():
46 checkbox.click()
47
48 if self.PROJECT_NAME != 'TestProjectConfig':
49 # Reset project name if it's not the default one
50 self.PROJECT_NAME = 'TestProjectConfig'
51
52 self.find("#create-project-button").click()
53
54 try:
55 self.wait_until_visible('#hint-error-project-name', poll=2)
56 url = reverse('project', args=(TestProjectConfig.project_id, ))
57 self.get(url)
58 self.wait_until_visible('#config-nav', poll=3)
59 except TimeoutException:
60 self.wait_until_visible('#config-nav', poll=3)
61
62 def _random_string(self, length):
63 return ''.join(
64 random.choice(string.ascii_letters) for _ in range(length)
65 )
66
67 def _get_config_nav_item(self, index):
68 config_nav = self.find('#config-nav')
69 return config_nav.find_elements(By.TAG_NAME, 'li')[index]
70
71 def _navigate_bbv_page(self):
72 """ Navigate to project BitBake variables page """
73 # check if the menu is displayed
74 if TestProjectConfig.project_id is None:
75 self._create_project(project_name=self._random_string(10))
76 current_url = self.driver.current_url
77 TestProjectConfig.project_id = get_projectId_from_url(current_url)
78 else:
79 url = reverse('projectconf', args=(TestProjectConfig.project_id,))
80 self.get(url)
81 self.wait_until_visible('#config-nav', poll=3)
82 bbv_page_link = self._get_config_nav_item(9)
83 bbv_page_link.click()
84 self.wait_until_visible('#config-nav', poll=3)
85
86 def test_no_underscore_iamgefs_type(self):
87 """
88 Should not accept IMAGEFS_TYPE with an underscore
89 """
90 self._navigate_bbv_page()
91 imagefs_type = "foo_bar"
92
93 self.wait_until_visible('#change-image_fstypes-icon', poll=2)
94
95 self.click('#change-image_fstypes-icon')
96
97 self.enter_text('#new-imagefs_types', imagefs_type)
98
99 element = self.wait_until_visible('#hintError-image-fs_type', poll=2)
100
101 self.assertTrue(("A valid image type cannot include underscores" in element.text),
102 "Did not find underscore error message")
103
104 def test_checkbox_verification(self):
105 """
106 Should automatically check the checkbox if user enters value
107 text box, if value is there in the checkbox.
108 """
109 self._navigate_bbv_page()
110
111 imagefs_type = "btrfs"
112
113 self.wait_until_visible('#change-image_fstypes-icon', poll=2)
114
115 self.click('#change-image_fstypes-icon')
116
117 self.enter_text('#new-imagefs_types', imagefs_type)
118
119 checkboxes = self.driver.find_elements(By.XPATH, "//input[@class='fs-checkbox-fstypes']")
120
121 for checkbox in checkboxes:
122 if checkbox.get_attribute("value") == "btrfs":
123 self.assertEqual(checkbox.is_selected(), True)
124
125 def test_textbox_with_checkbox_verification(self):
126 """
127 Should automatically add or remove value in textbox, if user checks
128 or unchecks checkboxes.
129 """
130 self._navigate_bbv_page()
131
132 self.wait_until_visible('#change-image_fstypes-icon', poll=2)
133
134 self.click('#change-image_fstypes-icon')
135
136 checkboxes_selector = '.fs-checkbox-fstypes'
137
138 self.wait_until_visible(checkboxes_selector, poll=2)
139 checkboxes = self.find_all(checkboxes_selector)
140
141 for checkbox in checkboxes:
142 if checkbox.get_attribute("value") == "cpio":
143 checkbox.click()
144 element = self.driver.find_element(By.ID, 'new-imagefs_types')
145
146 self.wait_until_visible('#new-imagefs_types', poll=2)
147
148 self.assertTrue(("cpio" in element.get_attribute('value'),
149 "Imagefs not added into the textbox"))
150 checkbox.click()
151 self.assertTrue(("cpio" not in element.text),
152 "Image still present in the textbox")
153
154 def test_set_download_dir(self):
155 """
156 Validate the allowed and disallowed types in the directory field for
157 DL_DIR
158 """
159 self._navigate_bbv_page()
160
161 # activate the input to edit download dir
162 try:
163 change_dl_dir_btn = self.wait_until_visible('#change-dl_dir-icon', poll=2)
164 except TimeoutException:
165 # If download dir is not displayed, test is skipped
166 change_dl_dir_btn = None
167
168 if change_dl_dir_btn:
169 change_dl_dir_btn = self.wait_until_visible('#change-dl_dir-icon', poll=2)
170 change_dl_dir_btn.click()
171
172 # downloads dir path doesn't start with / or ${...}
173 input_field = self.wait_until_visible('#new-dl_dir', poll=2)
174 input_field.clear()
175 self.enter_text('#new-dl_dir', 'home/foo')
176 element = self.wait_until_visible('#hintError-initialChar-dl_dir', poll=2)
177
178 msg = 'downloads directory path starts with invalid character but ' \
179 'treated as valid'
180 self.assertTrue((self.INVALID_PATH_START_TEXT in element.text), msg)
181
182 # downloads dir path has a space
183 self.driver.find_element(By.ID, 'new-dl_dir').clear()
184 self.enter_text('#new-dl_dir', '/foo/bar a')
185
186 element = self.wait_until_visible('#hintError-dl_dir', poll=2)
187 msg = 'downloads directory path characters invalid but treated as valid'
188 self.assertTrue((self.INVALID_PATH_CHAR_TEXT in element.text), msg)
189
190 # downloads dir path starts with ${...} but has a space
191 self.driver.find_element(By.ID,'new-dl_dir').clear()
192 self.enter_text('#new-dl_dir', '${TOPDIR}/down foo')
193
194 element = self.wait_until_visible('#hintError-dl_dir', poll=2)
195 msg = 'downloads directory path characters invalid but treated as valid'
196 self.assertTrue((self.INVALID_PATH_CHAR_TEXT in element.text), msg)
197
198 # downloads dir path starts with /
199 self.driver.find_element(By.ID,'new-dl_dir').clear()
200 self.enter_text('#new-dl_dir', '/bar/foo')
201
202 hidden_element = self.driver.find_element(By.ID,'hintError-dl_dir')
203 self.assertEqual(hidden_element.is_displayed(), False,
204 'downloads directory path valid but treated as invalid')
205
206 # downloads dir path starts with ${...}
207 self.driver.find_element(By.ID,'new-dl_dir').clear()
208 self.enter_text('#new-dl_dir', '${TOPDIR}/down')
209
210 hidden_element = self.driver.find_element(By.ID,'hintError-dl_dir')
211 self.assertEqual(hidden_element.is_displayed(), False,
212 'downloads directory path valid but treated as invalid')
213
214 def test_set_sstate_dir(self):
215 """
216 Validate the allowed and disallowed types in the directory field for
217 SSTATE_DIR
218 """
219 self._navigate_bbv_page()
220
221 try:
222 btn_chg_sstate_dir = self.wait_until_visible(
223 '#change-sstate_dir-icon',
224 poll=2
225 )
226 self.click('#change-sstate_dir-icon')
227 except TimeoutException:
228 # If sstate_dir is not displayed, test is skipped
229 btn_chg_sstate_dir = None
230
231 if btn_chg_sstate_dir: # Skip continuation if sstate_dir is not displayed
232 # path doesn't start with / or ${...}
233 input_field = self.wait_until_visible('#new-sstate_dir', poll=2)
234 input_field.clear()
235 self.enter_text('#new-sstate_dir', 'home/foo')
236 element = self.wait_until_visible('#hintError-initialChar-sstate_dir', poll=2)
237
238 msg = 'sstate directory path starts with invalid character but ' \
239 'treated as valid'
240 self.assertTrue((self.INVALID_PATH_START_TEXT in element.text), msg)
241
242 # path has a space
243 self.driver.find_element(By.ID, 'new-sstate_dir').clear()
244 self.enter_text('#new-sstate_dir', '/foo/bar a')
245
246 element = self.wait_until_visible('#hintError-sstate_dir', poll=2)
247 msg = 'sstate directory path characters invalid but treated as valid'
248 self.assertTrue((self.INVALID_PATH_CHAR_TEXT in element.text), msg)
249
250 # path starts with ${...} but has a space
251 self.driver.find_element(By.ID,'new-sstate_dir').clear()
252 self.enter_text('#new-sstate_dir', '${TOPDIR}/down foo')
253
254 element = self.wait_until_visible('#hintError-sstate_dir', poll=2)
255 msg = 'sstate directory path characters invalid but treated as valid'
256 self.assertTrue((self.INVALID_PATH_CHAR_TEXT in element.text), msg)
257
258 # path starts with /
259 self.driver.find_element(By.ID,'new-sstate_dir').clear()
260 self.enter_text('#new-sstate_dir', '/bar/foo')
261
262 hidden_element = self.driver.find_element(By.ID, 'hintError-sstate_dir')
263 self.assertEqual(hidden_element.is_displayed(), False,
264 'sstate directory path valid but treated as invalid')
265
266 # paths starts with ${...}
267 self.driver.find_element(By.ID, 'new-sstate_dir').clear()
268 self.enter_text('#new-sstate_dir', '${TOPDIR}/down')
269
270 hidden_element = self.driver.find_element(By.ID, 'hintError-sstate_dir')
271 self.assertEqual(hidden_element.is_displayed(), False,
272 'sstate directory path valid but treated as invalid')
273
274 def _change_bbv_value(self, **kwargs):
275 var_name, field, btn_id, input_id, value, save_btn, *_ = kwargs.values()
276 """ Change bitbake variable value """
277 self._navigate_bbv_page()
278 self.wait_until_visible(f'#{btn_id}', poll=2)
279 if kwargs.get('new_variable'):
280 self.find(f"#{btn_id}").clear()
281 self.enter_text(f"#{btn_id}", f"{var_name}")
282 else:
283 self.click(f'#{btn_id}')
284 self.wait_until_visible(f'#{input_id}', poll=2)
285
286 if kwargs.get('is_select'):
287 select = Select(self.find(f'#{input_id}'))
288 select.select_by_visible_text(value)
289 else:
290 self.find(f"#{input_id}").clear()
291 self.enter_text(f'#{input_id}', f'{value}')
292 self.click(f'#{save_btn}')
293 value_displayed = str(self.wait_until_visible(f'#{field}').text).lower()
294 msg = f'{var_name} variable not changed'
295 self.assertTrue(str(value).lower() in value_displayed, msg)
296
297 def test_change_distro_var(self):
298 """ Test changing distro variable """
299 self._change_bbv_value(
300 var_name='DISTRO',
301 field='distro',
302 btn_id='change-distro-icon',
303 input_id='new-distro',
304 value='poky-changed',
305 save_btn="apply-change-distro",
306 )
307
308 def test_set_image_install_append_var(self):
309 """ Test setting IMAGE_INSTALL:append variable """
310 self._change_bbv_value(
311 var_name='IMAGE_INSTALL:append',
312 field='image_install',
313 btn_id='change-image_install-icon',
314 input_id='new-image_install',
315 value='bash, apt, busybox',
316 save_btn="apply-change-image_install",
317 )
318
319 def test_set_package_classes_var(self):
320 """ Test setting PACKAGE_CLASSES variable """
321 self._change_bbv_value(
322 var_name='PACKAGE_CLASSES',
323 field='package_classes',
324 btn_id='change-package_classes-icon',
325 input_id='package_classes-select',
326 value='package_deb',
327 save_btn="apply-change-package_classes",
328 is_select=True,
329 )
330
331 def test_create_new_bbv(self):
332 """ Test creating new bitbake variable """
333 self._change_bbv_value(
334 var_name='New_Custom_Variable',
335 field='configvar-list',
336 btn_id='variable',
337 input_id='value',
338 value='new variable value',
339 save_btn="add-configvar-button",
340 new_variable=True
341 )