@@ -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
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. Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> --- .../tests/functional/test_project_page.py | 93 ++++++++----------- 1 file changed, 40 insertions(+), 53 deletions(-)