blob: ee1f5c4bb8bf8d01cf6b42ad3654c53f5f609e90 [file] [log] [blame]
Patrick Williamsac13d5f2023-11-24 18:59:46 -06001#! /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
Patrick Williams169d7bc2024-01-05 11:33:25 -06009import string
10import random
Patrick Williamsac13d5f2023-11-24 18:59:46 -060011import pytest
Patrick Williamsac13d5f2023-11-24 18:59:46 -060012from django.urls import reverse
13from selenium.webdriver import Keys
14from selenium.webdriver.support.select import Select
Patrick Williams169d7bc2024-01-05 11:33:25 -060015from selenium.common.exceptions import NoSuchElementException, TimeoutException
16from orm.models import Project
Patrick Williamsac13d5f2023-11-24 18:59:46 -060017from tests.functional.functional_helpers import SeleniumFunctionalTestCase
18from selenium.webdriver.common.by import By
19
Patrick Williams169d7bc2024-01-05 11:33:25 -060020from .utils import get_projectId_from_url, wait_until_build, wait_until_build_cancelled
21
Patrick Williamsac13d5f2023-11-24 18:59:46 -060022
23@pytest.mark.django_db
Patrick Williams169d7bc2024-01-05 11:33:25 -060024@pytest.mark.order("last")
Patrick Williamsac13d5f2023-11-24 18:59:46 -060025class TestProjectConfigTab(SeleniumFunctionalTestCase):
Patrick Williams169d7bc2024-01-05 11:33:25 -060026 PROJECT_NAME = 'TestProjectConfigTab'
27 project_id = None
Patrick Williamsac13d5f2023-11-24 18:59:46 -060028
Patrick Williams169d7bc2024-01-05 11:33:25 -060029 def _create_project(self, project_name, **kwargs):
Patrick Williamsac13d5f2023-11-24 18:59:46 -060030 """ Create/Test new project using:
31 - Project Name: Any string
32 - Release: Any string
33 - Merge Toaster settings: True or False
34 """
Patrick Williams169d7bc2024-01-05 11:33:25 -060035 release = kwargs.get('release', '3')
Patrick Williamsac13d5f2023-11-24 18:59:46 -060036 self.get(reverse('newproject'))
Patrick Williams169d7bc2024-01-05 11:33:25 -060037 self.wait_until_visible('#new-project-name')
38 self.find("#new-project-name").send_keys(project_name)
39 select = Select(self.find("#projectversion"))
Patrick Williamsac13d5f2023-11-24 18:59:46 -060040 select.select_by_value(release)
41
42 # check merge toaster settings
43 checkbox = self.find('.checkbox-mergeattr')
Patrick Williams169d7bc2024-01-05 11:33:25 -060044 if not checkbox.is_selected():
45 checkbox.click()
46
47 if self.PROJECT_NAME != 'TestProjectConfigTab':
48 # Reset project name if it's not the default one
49 self.PROJECT_NAME = 'TestProjectConfigTab'
50
51 self.find("#create-project-button").click()
52
53 try:
54 self.wait_until_visible('#hint-error-project-name', poll=3)
55 url = reverse('project', args=(TestProjectConfigTab.project_id, ))
56 self.get(url)
57 self.wait_until_visible('#config-nav', poll=3)
58 except TimeoutException:
59 self.wait_until_visible('#config-nav', poll=3)
60
61 def _random_string(self, length):
62 return ''.join(
63 random.choice(string.ascii_letters) for _ in range(length)
64 )
65
66 def _navigate_to_project_page(self):
67 # Navigate to project page
68 if TestProjectConfigTab.project_id is None:
69 self._create_project(project_name=self._random_string(10))
70 current_url = self.driver.current_url
71 TestProjectConfigTab.project_id = get_projectId_from_url(
72 current_url)
Patrick Williamsac13d5f2023-11-24 18:59:46 -060073 else:
Patrick Williams169d7bc2024-01-05 11:33:25 -060074 url = reverse('project', args=(TestProjectConfigTab.project_id,))
75 self.get(url)
76 self.wait_until_visible('#config-nav')
Patrick Williamsac13d5f2023-11-24 18:59:46 -060077
78 def _create_builds(self):
79 # check search box can be use to build recipes
80 search_box = self.find('#build-input')
Patrick Williams169d7bc2024-01-05 11:33:25 -060081 search_box.send_keys('foo')
Patrick Williamsac13d5f2023-11-24 18:59:46 -060082 self.find('#build-button').click()
Patrick Williams169d7bc2024-01-05 11:33:25 -060083 self.wait_until_present('#latest-builds')
Patrick Williamsac13d5f2023-11-24 18:59:46 -060084 # loop until reach the parsing state
Patrick Williams169d7bc2024-01-05 11:33:25 -060085 wait_until_build(self, 'queued cloning starting parsing failed')
Patrick Williamsac13d5f2023-11-24 18:59:46 -060086 lastest_builds = self.driver.find_elements(
87 By.XPATH,
88 '//div[@id="latest-builds"]/div',
89 )
90 last_build = lastest_builds[0]
91 self.assertTrue(
Patrick Williams169d7bc2024-01-05 11:33:25 -060092 'foo' in str(last_build.text)
Patrick Williamsac13d5f2023-11-24 18:59:46 -060093 )
Patrick Williams169d7bc2024-01-05 11:33:25 -060094 last_build = lastest_builds[0]
95 try:
96 cancel_button = last_build.find_element(
97 By.XPATH,
98 '//span[@class="cancel-build-btn pull-right alert-link"]',
99 )
100 cancel_button.click()
101 except NoSuchElementException:
102 # Skip if the build is already cancelled
103 pass
104 wait_until_build_cancelled(self)
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600105
106 def _get_tabs(self):
107 # tabs links list
108 return self.driver.find_elements(
109 By.XPATH,
110 '//div[@id="project-topbar"]//li'
111 )
112
113 def _get_config_nav_item(self, index):
114 config_nav = self.find('#config-nav')
115 return config_nav.find_elements(By.TAG_NAME, 'li')[index]
116
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600117 def test_project_config_nav(self):
118 """ Test project config tab navigation:
119 - Check if the menu is displayed and contains the right elements:
120 - Configuration
121 - COMPATIBLE METADATA
122 - Custom images
123 - Image recipes
124 - Software recipes
125 - Machines
126 - Layers
127 - Distro
128 - EXTRA CONFIGURATION
129 - Bitbake variables
130 - Actions
131 - Delete project
132 """
Patrick Williams169d7bc2024-01-05 11:33:25 -0600133 self._navigate_to_project_page()
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600134
135 def _get_config_nav_item(index):
136 config_nav = self.find('#config-nav')
137 return config_nav.find_elements(By.TAG_NAME, 'li')[index]
138
139 def check_config_nav_item(index, item_name, url):
140 item = _get_config_nav_item(index)
141 self.assertTrue(item_name in item.text)
142 self.assertTrue(item.get_attribute('class') == 'active')
143 self.assertTrue(url in self.driver.current_url)
144
145 # check if the menu contains the right elements
146 # COMPATIBLE METADATA
147 compatible_metadata = _get_config_nav_item(1)
148 self.assertTrue(
149 "compatible metadata" in compatible_metadata.text.lower()
150 )
151 # EXTRA CONFIGURATION
152 extra_configuration = _get_config_nav_item(8)
153 self.assertTrue(
154 "extra configuration" in extra_configuration.text.lower()
155 )
156 # Actions
157 actions = _get_config_nav_item(10)
158 self.assertTrue("actions" in str(actions.text).lower())
159
160 conf_nav_list = [
Patrick Williams169d7bc2024-01-05 11:33:25 -0600161 # config
162 [0, 'Configuration',
163 f"/toastergui/project/{TestProjectConfigTab.project_id}"],
164 # custom images
165 [2, 'Custom images',
166 f"/toastergui/project/{TestProjectConfigTab.project_id}/customimages"],
167 # image recipes
168 [3, 'Image recipes',
169 f"/toastergui/project/{TestProjectConfigTab.project_id}/images"],
170 # software recipes
171 [4, 'Software recipes',
172 f"/toastergui/project/{TestProjectConfigTab.project_id}/softwarerecipes"],
173 # machines
174 [5, 'Machines',
175 f"/toastergui/project/{TestProjectConfigTab.project_id}/machines"],
176 # layers
177 [6, 'Layers',
178 f"/toastergui/project/{TestProjectConfigTab.project_id}/layers"],
179 # distro
180 [7, 'Distros',
181 f"/toastergui/project/{TestProjectConfigTab.project_id}/distros"],
182 # [9, 'BitBake variables', f"/toastergui/project/{TestProjectConfigTab.project_id}/configuration"], # bitbake variables
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600183 ]
184 for index, item_name, url in conf_nav_list:
185 item = _get_config_nav_item(index)
186 if item.get_attribute('class') != 'active':
187 item.click()
188 check_config_nav_item(index, item_name, url)
189
Patrick Williams169d7bc2024-01-05 11:33:25 -0600190 def test_image_recipe_editColumn(self):
191 """ Test the edit column feature in image recipe table on project page """
192 def test_edit_column(check_box_id):
193 # Check that we can hide/show table column
194 check_box = self.find(f'#{check_box_id}')
195 th_class = str(check_box_id).replace('checkbox-', '')
196 if check_box.is_selected():
197 # check if column is visible in table
198 self.assertTrue(
199 self.find(
200 f'#imagerecipestable thead th.{th_class}'
201 ).is_displayed(),
202 f"The {th_class} column is checked in EditColumn dropdown, but it's not visible in table"
203 )
204 check_box.click()
205 # check if column is hidden in table
206 self.assertFalse(
207 self.find(
208 f'#imagerecipestable thead th.{th_class}'
209 ).is_displayed(),
210 f"The {th_class} column is unchecked in EditColumn dropdown, but it's visible in table"
211 )
212 else:
213 # check if column is hidden in table
214 self.assertFalse(
215 self.find(
216 f'#imagerecipestable thead th.{th_class}'
217 ).is_displayed(),
218 f"The {th_class} column is unchecked in EditColumn dropdown, but it's visible in table"
219 )
220 check_box.click()
221 # check if column is visible in table
222 self.assertTrue(
223 self.find(
224 f'#imagerecipestable thead th.{th_class}'
225 ).is_displayed(),
226 f"The {th_class} column is checked in EditColumn dropdown, but it's not visible in table"
227 )
228
229 self._navigate_to_project_page()
230 # navigate to project image recipe page
231 recipe_image_page_link = self._get_config_nav_item(3)
232 recipe_image_page_link.click()
233 self.wait_until_present('#imagerecipestable tbody tr')
234
235 # Check edit column
236 edit_column = self.find('#edit-columns-button')
237 self.assertTrue(edit_column.is_displayed())
238 edit_column.click()
239 # Check dropdown is visible
240 self.wait_until_visible('ul.dropdown-menu.editcol')
241
242 # Check that we can hide the edit column
243 test_edit_column('checkbox-get_description_or_summary')
244 test_edit_column('checkbox-layer_version__get_vcs_reference')
245 test_edit_column('checkbox-layer_version__layer__name')
246 test_edit_column('checkbox-license')
247 test_edit_column('checkbox-recipe-file')
248 test_edit_column('checkbox-section')
249 test_edit_column('checkbox-version')
250
251 def test_image_recipe_show_rows(self):
252 """ Test the show rows feature in image recipe table on project page """
253 def test_show_rows(row_to_show, show_row_link):
254 # Check that we can show rows == row_to_show
255 show_row_link.select_by_value(str(row_to_show))
256 self.wait_until_visible('#imagerecipestable tbody tr')
257 self.assertTrue(
258 len(self.find_all('#imagerecipestable tbody tr')) == row_to_show
259 )
260
261 self._navigate_to_project_page()
262 # navigate to project image recipe page
263 recipe_image_page_link = self._get_config_nav_item(3)
264 recipe_image_page_link.click()
265 self.wait_until_present('#imagerecipestable tbody tr')
266
267 show_rows = self.driver.find_elements(
268 By.XPATH,
269 '//select[@class="form-control pagesize-imagerecipestable"]'
270 )
271 # Check show rows
272 for show_row_link in show_rows:
273 show_row_link = Select(show_row_link)
274 test_show_rows(10, show_row_link)
275 test_show_rows(25, show_row_link)
276 test_show_rows(50, show_row_link)
277 test_show_rows(100, show_row_link)
278 test_show_rows(150, show_row_link)
279
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600280 def test_project_config_tab_right_section(self):
281 """ Test project config tab right section contains five blocks:
282 - Machine:
283 - check 'Machine' is displayed
284 - check can change Machine
285 - Distro:
286 - check 'Distro' is displayed
287 - check can change Distro
288 - Most built recipes:
289 - check 'Most built recipes' is displayed
290 - check can select a recipe and build it
291 - Project release:
292 - check 'Project release' is displayed
293 - check project has right release displayed
294 - Layers:
295 - check can add a layer if exists
296 - check at least three layers are displayed
297 - openembedded-core
298 - meta-poky
299 - meta-yocto-bsp
300 """
Patrick Williams169d7bc2024-01-05 11:33:25 -0600301 # Create a new project for this test
302 project_name = self._random_string(10)
303 self._create_project(project_name=project_name)
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600304 # check if the menu is displayed
305 self.wait_until_visible('#project-page')
306 block_l = self.driver.find_element(
307 By.XPATH, '//*[@id="project-page"]/div[2]')
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600308 project_release = self.driver.find_element(
309 By.XPATH, '//*[@id="project-page"]/div[1]/div[4]')
310 layers = block_l.find_element(By.ID, 'layer-container')
311
Patrick Williams169d7bc2024-01-05 11:33:25 -0600312 def check_machine_distro(self, item_name, new_item_name, block_id):
313 block = self.find(f'#{block_id}')
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600314 title = block.find_element(By.TAG_NAME, 'h3')
315 self.assertTrue(item_name.capitalize() in title.text)
Patrick Williams169d7bc2024-01-05 11:33:25 -0600316 edit_btn = self.find(f'#change-{item_name}-toggle')
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600317 edit_btn.click()
Patrick Williams169d7bc2024-01-05 11:33:25 -0600318 self.wait_until_visible(f'#{item_name}-change-input')
319 name_input = self.find(f'#{item_name}-change-input')
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600320 name_input.clear()
321 name_input.send_keys(new_item_name)
Patrick Williams169d7bc2024-01-05 11:33:25 -0600322 change_btn = self.find(f'#{item_name}-change-btn')
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600323 change_btn.click()
Patrick Williams169d7bc2024-01-05 11:33:25 -0600324 self.wait_until_visible(f'#project-{item_name}-name')
325 project_name = self.find(f'#project-{item_name}-name')
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600326 self.assertTrue(new_item_name in project_name.text)
327 # check change notificaiton is displayed
328 change_notification = self.find('#change-notification')
329 self.assertTrue(
330 f'You have changed the {item_name} to: {new_item_name}' in change_notification.text
331 )
332
333 # Machine
Patrick Williams169d7bc2024-01-05 11:33:25 -0600334 check_machine_distro(self, 'machine', 'qemux86-64', 'machine-section')
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600335 # Distro
Patrick Williams169d7bc2024-01-05 11:33:25 -0600336 check_machine_distro(self, 'distro', 'poky-altcfg', 'distro-section')
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600337
338 # Project release
339 title = project_release.find_element(By.TAG_NAME, 'h3')
340 self.assertTrue("Project release" in title.text)
341 self.assertTrue(
342 "Yocto Project master" in self.find('#project-release-title').text
343 )
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600344 # Layers
345 title = layers.find_element(By.TAG_NAME, 'h3')
346 self.assertTrue("Layers" in title.text)
347 # check at least three layers are displayed
348 # openembedded-core
349 # meta-poky
350 # meta-yocto-bsp
351 layers_list = layers.find_element(By.ID, 'layers-in-project-list')
352 layers_list_items = layers_list.find_elements(By.TAG_NAME, 'li')
Patrick Williams169d7bc2024-01-05 11:33:25 -0600353 # remove all layers except the first three layers
354 for i in range(3, len(layers_list_items)):
355 layers_list_items[i].find_element(By.TAG_NAME, 'span').click()
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600356 # check can add a layer if exists
357 add_layer_input = layers.find_element(By.ID, 'layer-add-input')
358 add_layer_input.send_keys('meta-oe')
359 self.wait_until_visible('#layer-container > form > div > span > div')
360 dropdown_item = self.driver.find_element(
361 By.XPATH,
362 '//*[@id="layer-container"]/form/div/span/div'
363 )
364 dropdown_item.click()
365 add_layer_btn = layers.find_element(By.ID, 'add-layer-btn')
366 add_layer_btn.click()
Patrick Williams169d7bc2024-01-05 11:33:25 -0600367 self.wait_until_visible('#layers-in-project-list')
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600368 # check layer is added
369 layers_list_items = layers_list.find_elements(By.TAG_NAME, 'li')
370 self.assertTrue(len(layers_list_items) == 4)
371
Patrick Williams169d7bc2024-01-05 11:33:25 -0600372 def test_most_build_recipes(self):
373 """ Test most build recipes block contains"""
374 def rebuild_from_most_build_recipes(recipe_list_items):
375 checkbox = recipe_list_items[0].find_element(By.TAG_NAME, 'input')
376 checkbox.click()
377 build_btn = self.find('#freq-build-btn')
378 build_btn.click()
379 self.wait_until_visible('#latest-builds')
380 wait_until_build(self, 'queued cloning starting parsing failed')
381 lastest_builds = self.driver.find_elements(
382 By.XPATH,
383 '//div[@id="latest-builds"]/div'
384 )
385 self.assertTrue(len(lastest_builds) >= 2)
386 last_build = lastest_builds[0]
387 try:
388 cancel_button = last_build.find_element(
389 By.XPATH,
390 '//span[@class="cancel-build-btn pull-right alert-link"]',
391 )
392 cancel_button.click()
393 except NoSuchElementException:
394 # Skip if the build is already cancelled
395 pass
396 wait_until_build_cancelled(self)
397 # Create a new project for remaining asserts
398 project_name = self._random_string(10)
399 self._create_project(project_name=project_name, release='2')
400 current_url = self.driver.current_url
401 TestProjectConfigTab.project_id = get_projectId_from_url(current_url)
402 url = current_url.split('?')[0]
403
404 # Create a new builds
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600405 self._create_builds()
406
Patrick Williams169d7bc2024-01-05 11:33:25 -0600407 # back to project page
408 self.driver.get(url)
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600409
Patrick Williams169d7bc2024-01-05 11:33:25 -0600410 self.wait_until_visible('#project-page', poll=3)
411
412 # Most built recipes
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600413 most_built_recipes = self.driver.find_element(
414 By.XPATH, '//*[@id="project-page"]/div[1]/div[3]')
Patrick Williams169d7bc2024-01-05 11:33:25 -0600415 title = most_built_recipes.find_element(By.TAG_NAME, 'h3')
416 self.assertTrue("Most built recipes" in title.text)
417 # check can select a recipe and build it
418 self.wait_until_visible('#freq-build-list', poll=3)
419 recipe_list = self.find('#freq-build-list')
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600420 recipe_list_items = recipe_list.find_elements(By.TAG_NAME, 'li')
421 self.assertTrue(
422 len(recipe_list_items) > 0,
Patrick Williams169d7bc2024-01-05 11:33:25 -0600423 msg="Any recipes found in the most built recipes list",
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600424 )
Patrick Williams169d7bc2024-01-05 11:33:25 -0600425 rebuild_from_most_build_recipes(recipe_list_items)
426 TestProjectConfigTab.project_id = None # reset project id
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600427
428 def test_project_page_tab_importlayer(self):
429 """ Test project page tab import layer """
Patrick Williams169d7bc2024-01-05 11:33:25 -0600430 self._navigate_to_project_page()
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600431 # navigate to "Import layers" tab
432 import_layers_tab = self._get_tabs()[2]
433 import_layers_tab.find_element(By.TAG_NAME, 'a').click()
434 self.wait_until_visible('#layer-git-repo-url')
435
436 # Check git repo radio button
437 git_repo_radio = self.find('#git-repo-radio')
438 git_repo_radio.click()
439
440 # Set git repo url
441 input_repo_url = self.find('#layer-git-repo-url')
442 input_repo_url.send_keys('git://git.yoctoproject.org/meta-fake')
443 # Blur the input to trigger the validation
444 input_repo_url.send_keys(Keys.TAB)
445
446 # Check name is set
447 input_layer_name = self.find('#import-layer-name')
448 self.assertTrue(input_layer_name.get_attribute('value') == 'meta-fake')
449
450 # Set branch
451 input_branch = self.find('#layer-git-ref')
452 input_branch.send_keys('master')
453
454 # Import layer
455 self.find('#import-and-add-btn').click()
456
457 # Check layer is added
458 self.wait_until_visible('#layer-container')
459 block_l = self.driver.find_element(
460 By.XPATH, '//*[@id="project-page"]/div[2]')
461 layers = block_l.find_element(By.ID, 'layer-container')
462 layers_list = layers.find_element(By.ID, 'layers-in-project-list')
463 layers_list_items = layers_list.find_elements(By.TAG_NAME, 'li')
464 self.assertTrue(
465 'meta-fake' in str(layers_list_items[-1].text)
466 )
467
468 def test_project_page_custom_image_no_image(self):
469 """ Test project page tab "New custom image" when no custom image """
Patrick Williams169d7bc2024-01-05 11:33:25 -0600470 project_name = self._random_string(10)
471 self._create_project(project_name=project_name)
472 current_url = self.driver.current_url
473 TestProjectConfigTab.project_id = get_projectId_from_url(current_url)
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600474 # navigate to "Custom image" tab
475 custom_image_section = self._get_config_nav_item(2)
476 custom_image_section.click()
477 self.wait_until_visible('#empty-state-customimagestable')
478
479 # Check message when no custom image
480 self.assertTrue(
481 "You have not created any custom images yet." in str(
482 self.find('#empty-state-customimagestable').text
483 )
484 )
485 div_empty_msg = self.find('#empty-state-customimagestable')
486 link_create_custom_image = div_empty_msg.find_element(
487 By.TAG_NAME, 'a')
Patrick Williams169d7bc2024-01-05 11:33:25 -0600488 self.assertTrue(TestProjectConfigTab.project_id is not None)
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600489 self.assertTrue(
Patrick Williams169d7bc2024-01-05 11:33:25 -0600490 f"/toastergui/project/{TestProjectConfigTab.project_id}/newcustomimage" in str(
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600491 link_create_custom_image.get_attribute('href')
492 )
493 )
494 self.assertTrue(
495 "Create your first custom image" in str(
496 link_create_custom_image.text
497 )
498 )
Patrick Williams169d7bc2024-01-05 11:33:25 -0600499 TestProjectConfigTab.project_id = None # reset project id
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600500
501 def test_project_page_image_recipe(self):
502 """ Test project page section images
503 - Check image recipes are displayed
504 - Check search input
505 - Check image recipe build button works
506 - Check image recipe table features(show/hide column, pagination)
507 """
Patrick Williams169d7bc2024-01-05 11:33:25 -0600508 self._navigate_to_project_page()
Patrick Williamsac13d5f2023-11-24 18:59:46 -0600509 # navigate to "Images section"
510 images_section = self._get_config_nav_item(3)
511 images_section.click()
512 self.wait_until_visible('#imagerecipestable')
513 rows = self.find_all('#imagerecipestable tbody tr')
514 self.assertTrue(len(rows) > 0)
515
516 # Test search input
517 self.wait_until_visible('#search-input-imagerecipestable')
518 recipe_input = self.find('#search-input-imagerecipestable')
519 recipe_input.send_keys('core-image-minimal')
520 self.find('#search-submit-imagerecipestable').click()
521 self.wait_until_visible('#imagerecipestable tbody tr')
522 rows = self.find_all('#imagerecipestable tbody tr')
523 self.assertTrue(len(rows) > 0)