bitbake: toaster/tests/functional/project_page: Use wait_until_element_clickable before click calls

Switch the clickable() calls to use the new element_clickable() function
which accepts a finder labmda function. This means if the element doesn't
yet exist, the code can rebuild the query and try again once a small
amount of time has elapsed.

There were a ton of timing related races around these element interactions
and this seemed to be the most robust way to address the issues.

The change also makes some of the elements slightly more specific so
the code can work effectively.

(Bitbake rev: 38643aadbb5a960004b886cf7709beaf2fc96652)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Richard Purdie
2024-10-22 13:38:50 +01:00
parent 7fef43d98a
commit 1f2b8a27ea

View File

@@ -92,7 +92,8 @@ class TestProjectPageBase(SeleniumFunctionalTestCase):
list_check_box_id: list
):
# Check edit column
edit_column = self.find(f'#{edit_btn_id}')
finder = lambda driver: self.find(f'#{edit_btn_id}')
edit_column = self.wait_until_element_clickable(finder)
self.assertTrue(edit_column.is_displayed())
edit_column.click()
# Check dropdown is visible
@@ -280,7 +281,8 @@ class TestProjectPage(TestProjectPageBase):
# click on "Edit" icon button
self.wait_until_visible('#project-name-container')
edit_button = self.find('#project-change-form-toggle')
finder = lambda driver: self.find('#project-change-form-toggle')
edit_button = self.wait_until_element_clickable(finder)
edit_button.click()
project_name_input = self.find('#project-name-change-input')
self.assertTrue(project_name_input.is_displayed())
@@ -391,12 +393,8 @@ class TestProjectPage(TestProjectPageBase):
table_selector='softwarerecipestable'
)
# check "build recipe" button works
rows = self.find_all('#softwarerecipestable tbody tr')
image_to_build = rows[0]
build_btn = image_to_build.find_element(
By.XPATH,
'//td[@class="add-del-layers"]//a[1]'
)
finder = lambda driver: self.find_all('#softwarerecipestable tbody tr')[0].find_element(By.XPATH, '//td[@class="add-del-layers"]/a')
build_btn = self.wait_until_element_clickable(finder)
build_btn.click()
build_state = wait_until_build(self, 'queued cloning starting parsing failed')
lastest_builds = self.driver.find_elements(
@@ -404,11 +402,10 @@ class TestProjectPage(TestProjectPageBase):
'//div[@id="latest-builds"]/div'
)
self.assertTrue(len(lastest_builds) > 0)
last_build = lastest_builds[0]
cancel_button = last_build.find_element(
By.XPATH,
'//span[@class="cancel-build-btn pull-right alert-link"]',
)
# Find the latest builds, the last build and then the cancel button
finder = lambda driver: driver.find_elements(By.XPATH, '//div[@id="latest-builds"]/div')[0].find_element(By.XPATH, '//span[@class="cancel-build-btn pull-right alert-link"]')
cancel_button = self.wait_until_element_clickable(finder)
cancel_button.click()
if 'starting' not in build_state: # change build state when cancelled in starting state
wait_until_build_cancelled(self)
@@ -455,14 +452,10 @@ class TestProjectPage(TestProjectPageBase):
table_selector='machinestable'
)
# check "Select machine" button works
rows = self.find_all('#machinestable tbody tr')
machine_to_select = rows[0]
select_btn = machine_to_select.find_element(
By.XPATH,
'//td[@class="add-del-layers"]//a[1]'
)
select_btn.send_keys(Keys.RETURN)
self.wait_until_visible('#config-nav')
finder = lambda driver: self.find_all('#machinestable tbody tr')[0].find_element(By.XPATH, '//td[@class="add-del-layers"]')
select_btn = self.wait_until_element_clickable(finder)
select_btn.click()
self.wait_until_visible('#project-machine-name')
project_machine_name = self.find('#project-machine-name')
self.assertIn(
'qemux86-64', project_machine_name.text
@@ -478,9 +471,9 @@ class TestProjectPage(TestProjectPageBase):
)
self.wait_until_visible('#machinestable tbody tr')
rows = self.find_all('#machinestable tbody tr')
machine_to_add = rows[0]
add_btn = machine_to_add.find_element(By.XPATH, '//td[@class="add-del-layers"]')
# Locate a machine to add button
finder = lambda driver: self.find_all('#machinestable tbody tr')[0].find_element(By.XPATH, '//td[@class="add-del-layers"]')
add_btn = self.wait_until_element_clickable(finder)
add_btn.click()
self.wait_until_visible('#change-notification')
change_notification = self.find('#change-notification')
@@ -488,7 +481,8 @@ class TestProjectPage(TestProjectPageBase):
f'You have added 1 layer to your project', str(change_notification.text)
)
hide_button = self.find('#hide-alert')
finder = lambda driver: self.find('#hide-alert')
hide_button = self.wait_until_element_clickable(finder)
hide_button.click()
self.wait_until_not_visible('#change-notification')
@@ -533,21 +527,15 @@ class TestProjectPage(TestProjectPageBase):
)
# check "Add layer" button works
self.wait_until_visible('#layerstable tbody tr')
rows = self.find_all('#layerstable tbody tr')
layer_to_add = rows[0]
add_btn = layer_to_add.find_element(
By.XPATH,
'//td[@class="add-del-layers"]'
)
finder = lambda driver: self.find_all('#layerstable tbody tr')[0].find_element(By.XPATH, '//td[@class="add-del-layers"]/a[@data-directive="add"]')
add_btn = self.wait_until_element_clickable(finder)
add_btn.click()
# check modal is displayed
self.wait_until_visible('#dependencies-modal')
list_dependencies = self.find_all('#dependencies-list li')
# click on add-layers button
add_layers_btn = self.driver.find_element(
By.XPATH,
'//form[@id="dependencies-modal-form"]//button[@class="btn btn-primary"]'
)
finder = lambda driver: self.driver.find_element(By.XPATH, '//form[@id="dependencies-modal-form"]//button[@class="btn btn-primary"]')
add_layers_btn = self.wait_until_element_clickable(finder)
add_layers_btn.click()
self.wait_until_visible('#change-notification')
change_notification = self.find('#change-notification')
@@ -555,18 +543,15 @@ class TestProjectPage(TestProjectPageBase):
f'You have added {len(list_dependencies)+1} layers to your project: {input_text} and its dependencies', str(change_notification.text)
)
hide_button = self.find('#hide-alert')
finder = lambda driver: self.find('#hide-alert')
hide_button = self.wait_until_element_clickable(finder)
hide_button.click()
self.wait_until_not_visible('#change-notification')
# check "Remove layer" button works
self.wait_until_visible('#layerstable tbody tr')
rows = self.find_all('#layerstable tbody tr')
layer_to_remove = rows[0]
remove_btn = layer_to_remove.find_element(
By.XPATH,
'//td[@class="add-del-layers"]'
)
finder = lambda driver: self.find_all('#layerstable tbody tr')[0].find_element(By.XPATH, '//td[@class="add-del-layers"]/a[@data-directive="remove"]')
remove_btn = self.wait_until_element_clickable(finder)
remove_btn.click()
self.wait_until_visible('#change-notification')
change_notification = self.find('#change-notification')
@@ -574,7 +559,8 @@ class TestProjectPage(TestProjectPageBase):
f'You have removed 1 layer from your project: {input_text}', str(change_notification.text)
)
hide_button = self.find('#hide-alert')
finder = lambda driver: self.find('#hide-alert')
hide_button = self.wait_until_element_clickable(finder)
hide_button.click()
self.wait_until_not_visible('#change-notification')
@@ -618,12 +604,9 @@ class TestProjectPage(TestProjectPageBase):
table_selector='distrostable'
)
# check "Add distro" button works
rows = self.find_all('#distrostable tbody tr')
distro_to_add = rows[0]
add_btn = distro_to_add.find_element(
By.XPATH,
'//td[@class="add-del-layers"]//a[1]'
)
self.wait_until_visible(".add-del-layers")
finder = lambda driver: self.find_all('#distrostable tbody tr')[0].find_element(By.XPATH, '//td[@class="add-del-layers"]')
add_btn = self.wait_until_element_clickable(finder)
add_btn.click()
self.wait_until_visible('#change-notification')
change_notification = self.find('#change-notification')
@@ -668,25 +651,29 @@ class TestProjectPage(TestProjectPageBase):
self.assertTrue(self.find('.page-header h1').is_displayed())
# check remove layer button works
remove_layer_btn = self.find('#add-remove-layer-btn')
finder = lambda driver: self.find('#add-remove-layer-btn')
remove_layer_btn = self.wait_until_element_clickable(finder)
remove_layer_btn.click()
self.wait_until_visible('#change-notification')
change_notification = self.find('#change-notification')
self.assertIn(
f'You have removed 1 layer from your project', str(change_notification.text)
)
hide_button = self.find('#hide-alert')
finder = lambda driver: self.find('#hide-alert')
hide_button = self.wait_until_element_clickable(finder)
hide_button.click()
# check add layer button works
self.wait_until_not_visible('#change-notification')
add_layer_btn = self.find('#add-remove-layer-btn')
finder = lambda driver: self.find('#add-remove-layer-btn')
add_layer_btn = self.wait_until_element_clickable(finder)
add_layer_btn.click()
self.wait_until_visible('#change-notification')
change_notification = self.find('#change-notification')
self.assertIn(
f'You have added 1 layer to your project', str(change_notification.text)
)
hide_button = self.find('#hide-alert')
finder = lambda driver: self.find('#hide-alert')
hide_button = self.wait_until_element_clickable(finder)
hide_button.click()
self.wait_until_not_visible('#change-notification')
# check tabs(layers, recipes, machines) are displayed