diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-10-22 13:38:50 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-10-24 11:24:03 +0100 |
commit | 1f2b8a27ead94d48148111c00f11056e328c03eb (patch) | |
tree | 7945eedb876593d2bad736f00eaea7501e5d4972 | |
parent | 7fef43d98a20cc8267adad55c46fb96f6bb026d7 (diff) | |
download | poky-1f2b8a27ead94d48148111c00f11056e328c03eb.tar.gz |
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>
-rw-r--r-- | bitbake/lib/toaster/tests/functional/test_project_page.py | 93 |
1 files changed, 40 insertions, 53 deletions
diff --git a/bitbake/lib/toaster/tests/functional/test_project_page.py b/bitbake/lib/toaster/tests/functional/test_project_page.py index f34ccf5e8e..c6dad0eb5d 100644 --- a/bitbake/lib/toaster/tests/functional/test_project_page.py +++ b/bitbake/lib/toaster/tests/functional/test_project_page.py | |||
@@ -92,7 +92,8 @@ class TestProjectPageBase(SeleniumFunctionalTestCase): | |||
92 | list_check_box_id: list | 92 | list_check_box_id: list |
93 | ): | 93 | ): |
94 | # Check edit column | 94 | # Check edit column |
95 | edit_column = self.find(f'#{edit_btn_id}') | 95 | finder = lambda driver: self.find(f'#{edit_btn_id}') |
96 | edit_column = self.wait_until_element_clickable(finder) | ||
96 | self.assertTrue(edit_column.is_displayed()) | 97 | self.assertTrue(edit_column.is_displayed()) |
97 | edit_column.click() | 98 | edit_column.click() |
98 | # Check dropdown is visible | 99 | # Check dropdown is visible |
@@ -280,7 +281,8 @@ class TestProjectPage(TestProjectPageBase): | |||
280 | 281 | ||
281 | # click on "Edit" icon button | 282 | # click on "Edit" icon button |
282 | self.wait_until_visible('#project-name-container') | 283 | self.wait_until_visible('#project-name-container') |
283 | edit_button = self.find('#project-change-form-toggle') | 284 | finder = lambda driver: self.find('#project-change-form-toggle') |
285 | edit_button = self.wait_until_element_clickable(finder) | ||
284 | edit_button.click() | 286 | edit_button.click() |
285 | project_name_input = self.find('#project-name-change-input') | 287 | project_name_input = self.find('#project-name-change-input') |
286 | self.assertTrue(project_name_input.is_displayed()) | 288 | self.assertTrue(project_name_input.is_displayed()) |
@@ -391,12 +393,8 @@ class TestProjectPage(TestProjectPageBase): | |||
391 | table_selector='softwarerecipestable' | 393 | table_selector='softwarerecipestable' |
392 | ) | 394 | ) |
393 | # check "build recipe" button works | 395 | # check "build recipe" button works |
394 | rows = self.find_all('#softwarerecipestable tbody tr') | 396 | finder = lambda driver: self.find_all('#softwarerecipestable tbody tr')[0].find_element(By.XPATH, '//td[@class="add-del-layers"]/a') |
395 | image_to_build = rows[0] | 397 | build_btn = self.wait_until_element_clickable(finder) |
396 | build_btn = image_to_build.find_element( | ||
397 | By.XPATH, | ||
398 | '//td[@class="add-del-layers"]//a[1]' | ||
399 | ) | ||
400 | build_btn.click() | 398 | build_btn.click() |
401 | build_state = wait_until_build(self, 'queued cloning starting parsing failed') | 399 | build_state = wait_until_build(self, 'queued cloning starting parsing failed') |
402 | lastest_builds = self.driver.find_elements( | 400 | lastest_builds = self.driver.find_elements( |
@@ -404,11 +402,10 @@ class TestProjectPage(TestProjectPageBase): | |||
404 | '//div[@id="latest-builds"]/div' | 402 | '//div[@id="latest-builds"]/div' |
405 | ) | 403 | ) |
406 | self.assertTrue(len(lastest_builds) > 0) | 404 | self.assertTrue(len(lastest_builds) > 0) |
407 | last_build = lastest_builds[0] | 405 | # Find the latest builds, the last build and then the cancel button |
408 | cancel_button = last_build.find_element( | 406 | |
409 | By.XPATH, | 407 | 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"]') |
410 | '//span[@class="cancel-build-btn pull-right alert-link"]', | 408 | cancel_button = self.wait_until_element_clickable(finder) |
411 | ) | ||
412 | cancel_button.click() | 409 | cancel_button.click() |
413 | if 'starting' not in build_state: # change build state when cancelled in starting state | 410 | if 'starting' not in build_state: # change build state when cancelled in starting state |
414 | wait_until_build_cancelled(self) | 411 | wait_until_build_cancelled(self) |
@@ -455,14 +452,10 @@ class TestProjectPage(TestProjectPageBase): | |||
455 | table_selector='machinestable' | 452 | table_selector='machinestable' |
456 | ) | 453 | ) |
457 | # check "Select machine" button works | 454 | # check "Select machine" button works |
458 | rows = self.find_all('#machinestable tbody tr') | 455 | finder = lambda driver: self.find_all('#machinestable tbody tr')[0].find_element(By.XPATH, '//td[@class="add-del-layers"]') |
459 | machine_to_select = rows[0] | 456 | select_btn = self.wait_until_element_clickable(finder) |
460 | select_btn = machine_to_select.find_element( | 457 | select_btn.click() |
461 | By.XPATH, | 458 | self.wait_until_visible('#project-machine-name') |
462 | '//td[@class="add-del-layers"]//a[1]' | ||
463 | ) | ||
464 | select_btn.send_keys(Keys.RETURN) | ||
465 | self.wait_until_visible('#config-nav') | ||
466 | project_machine_name = self.find('#project-machine-name') | 459 | project_machine_name = self.find('#project-machine-name') |
467 | self.assertIn( | 460 | self.assertIn( |
468 | 'qemux86-64', project_machine_name.text | 461 | 'qemux86-64', project_machine_name.text |
@@ -478,9 +471,9 @@ class TestProjectPage(TestProjectPageBase): | |||
478 | ) | 471 | ) |
479 | 472 | ||
480 | self.wait_until_visible('#machinestable tbody tr') | 473 | self.wait_until_visible('#machinestable tbody tr') |
481 | rows = self.find_all('#machinestable tbody tr') | 474 | # Locate a machine to add button |
482 | machine_to_add = rows[0] | 475 | finder = lambda driver: self.find_all('#machinestable tbody tr')[0].find_element(By.XPATH, '//td[@class="add-del-layers"]') |
483 | add_btn = machine_to_add.find_element(By.XPATH, '//td[@class="add-del-layers"]') | 476 | add_btn = self.wait_until_element_clickable(finder) |
484 | add_btn.click() | 477 | add_btn.click() |
485 | self.wait_until_visible('#change-notification') | 478 | self.wait_until_visible('#change-notification') |
486 | change_notification = self.find('#change-notification') | 479 | change_notification = self.find('#change-notification') |
@@ -488,7 +481,8 @@ class TestProjectPage(TestProjectPageBase): | |||
488 | f'You have added 1 layer to your project', str(change_notification.text) | 481 | f'You have added 1 layer to your project', str(change_notification.text) |
489 | ) | 482 | ) |
490 | 483 | ||
491 | hide_button = self.find('#hide-alert') | 484 | finder = lambda driver: self.find('#hide-alert') |
485 | hide_button = self.wait_until_element_clickable(finder) | ||
492 | hide_button.click() | 486 | hide_button.click() |
493 | self.wait_until_not_visible('#change-notification') | 487 | self.wait_until_not_visible('#change-notification') |
494 | 488 | ||
@@ -533,21 +527,15 @@ class TestProjectPage(TestProjectPageBase): | |||
533 | ) | 527 | ) |
534 | # check "Add layer" button works | 528 | # check "Add layer" button works |
535 | self.wait_until_visible('#layerstable tbody tr') | 529 | self.wait_until_visible('#layerstable tbody tr') |
536 | rows = self.find_all('#layerstable tbody tr') | 530 | finder = lambda driver: self.find_all('#layerstable tbody tr')[0].find_element(By.XPATH, '//td[@class="add-del-layers"]/a[@data-directive="add"]') |
537 | layer_to_add = rows[0] | 531 | add_btn = self.wait_until_element_clickable(finder) |
538 | add_btn = layer_to_add.find_element( | ||
539 | By.XPATH, | ||
540 | '//td[@class="add-del-layers"]' | ||
541 | ) | ||
542 | add_btn.click() | 532 | add_btn.click() |
543 | # check modal is displayed | 533 | # check modal is displayed |
544 | self.wait_until_visible('#dependencies-modal') | 534 | self.wait_until_visible('#dependencies-modal') |
545 | list_dependencies = self.find_all('#dependencies-list li') | 535 | list_dependencies = self.find_all('#dependencies-list li') |
546 | # click on add-layers button | 536 | # click on add-layers button |
547 | add_layers_btn = self.driver.find_element( | 537 | finder = lambda driver: self.driver.find_element(By.XPATH, '//form[@id="dependencies-modal-form"]//button[@class="btn btn-primary"]') |
548 | By.XPATH, | 538 | add_layers_btn = self.wait_until_element_clickable(finder) |
549 | '//form[@id="dependencies-modal-form"]//button[@class="btn btn-primary"]' | ||
550 | ) | ||
551 | add_layers_btn.click() | 539 | add_layers_btn.click() |
552 | self.wait_until_visible('#change-notification') | 540 | self.wait_until_visible('#change-notification') |
553 | change_notification = self.find('#change-notification') | 541 | change_notification = self.find('#change-notification') |
@@ -555,18 +543,15 @@ class TestProjectPage(TestProjectPageBase): | |||
555 | f'You have added {len(list_dependencies)+1} layers to your project: {input_text} and its dependencies', str(change_notification.text) | 543 | f'You have added {len(list_dependencies)+1} layers to your project: {input_text} and its dependencies', str(change_notification.text) |
556 | ) | 544 | ) |
557 | 545 | ||
558 | hide_button = self.find('#hide-alert') | 546 | finder = lambda driver: self.find('#hide-alert') |
547 | hide_button = self.wait_until_element_clickable(finder) | ||
559 | hide_button.click() | 548 | hide_button.click() |
560 | self.wait_until_not_visible('#change-notification') | 549 | self.wait_until_not_visible('#change-notification') |
561 | 550 | ||
562 | # check "Remove layer" button works | 551 | # check "Remove layer" button works |
563 | self.wait_until_visible('#layerstable tbody tr') | 552 | self.wait_until_visible('#layerstable tbody tr') |
564 | rows = self.find_all('#layerstable tbody tr') | 553 | finder = lambda driver: self.find_all('#layerstable tbody tr')[0].find_element(By.XPATH, '//td[@class="add-del-layers"]/a[@data-directive="remove"]') |
565 | layer_to_remove = rows[0] | 554 | remove_btn = self.wait_until_element_clickable(finder) |
566 | remove_btn = layer_to_remove.find_element( | ||
567 | By.XPATH, | ||
568 | '//td[@class="add-del-layers"]' | ||
569 | ) | ||
570 | remove_btn.click() | 555 | remove_btn.click() |
571 | self.wait_until_visible('#change-notification') | 556 | self.wait_until_visible('#change-notification') |
572 | change_notification = self.find('#change-notification') | 557 | change_notification = self.find('#change-notification') |
@@ -574,7 +559,8 @@ class TestProjectPage(TestProjectPageBase): | |||
574 | f'You have removed 1 layer from your project: {input_text}', str(change_notification.text) | 559 | f'You have removed 1 layer from your project: {input_text}', str(change_notification.text) |
575 | ) | 560 | ) |
576 | 561 | ||
577 | hide_button = self.find('#hide-alert') | 562 | finder = lambda driver: self.find('#hide-alert') |
563 | hide_button = self.wait_until_element_clickable(finder) | ||
578 | hide_button.click() | 564 | hide_button.click() |
579 | self.wait_until_not_visible('#change-notification') | 565 | self.wait_until_not_visible('#change-notification') |
580 | 566 | ||
@@ -618,12 +604,9 @@ class TestProjectPage(TestProjectPageBase): | |||
618 | table_selector='distrostable' | 604 | table_selector='distrostable' |
619 | ) | 605 | ) |
620 | # check "Add distro" button works | 606 | # check "Add distro" button works |
621 | rows = self.find_all('#distrostable tbody tr') | 607 | self.wait_until_visible(".add-del-layers") |
622 | distro_to_add = rows[0] | 608 | finder = lambda driver: self.find_all('#distrostable tbody tr')[0].find_element(By.XPATH, '//td[@class="add-del-layers"]') |
623 | add_btn = distro_to_add.find_element( | 609 | add_btn = self.wait_until_element_clickable(finder) |
624 | By.XPATH, | ||
625 | '//td[@class="add-del-layers"]//a[1]' | ||
626 | ) | ||
627 | add_btn.click() | 610 | add_btn.click() |
628 | self.wait_until_visible('#change-notification') | 611 | self.wait_until_visible('#change-notification') |
629 | change_notification = self.find('#change-notification') | 612 | change_notification = self.find('#change-notification') |
@@ -668,25 +651,29 @@ class TestProjectPage(TestProjectPageBase): | |||
668 | self.assertTrue(self.find('.page-header h1').is_displayed()) | 651 | self.assertTrue(self.find('.page-header h1').is_displayed()) |
669 | 652 | ||
670 | # check remove layer button works | 653 | # check remove layer button works |
671 | remove_layer_btn = self.find('#add-remove-layer-btn') | 654 | finder = lambda driver: self.find('#add-remove-layer-btn') |
655 | remove_layer_btn = self.wait_until_element_clickable(finder) | ||
672 | remove_layer_btn.click() | 656 | remove_layer_btn.click() |
673 | self.wait_until_visible('#change-notification') | 657 | self.wait_until_visible('#change-notification') |
674 | change_notification = self.find('#change-notification') | 658 | change_notification = self.find('#change-notification') |
675 | self.assertIn( | 659 | self.assertIn( |
676 | f'You have removed 1 layer from your project', str(change_notification.text) | 660 | f'You have removed 1 layer from your project', str(change_notification.text) |
677 | ) | 661 | ) |
678 | hide_button = self.find('#hide-alert') | 662 | finder = lambda driver: self.find('#hide-alert') |
663 | hide_button = self.wait_until_element_clickable(finder) | ||
679 | hide_button.click() | 664 | hide_button.click() |
680 | # check add layer button works | 665 | # check add layer button works |
681 | self.wait_until_not_visible('#change-notification') | 666 | self.wait_until_not_visible('#change-notification') |
682 | add_layer_btn = self.find('#add-remove-layer-btn') | 667 | finder = lambda driver: self.find('#add-remove-layer-btn') |
668 | add_layer_btn = self.wait_until_element_clickable(finder) | ||
683 | add_layer_btn.click() | 669 | add_layer_btn.click() |
684 | self.wait_until_visible('#change-notification') | 670 | self.wait_until_visible('#change-notification') |
685 | change_notification = self.find('#change-notification') | 671 | change_notification = self.find('#change-notification') |
686 | self.assertIn( | 672 | self.assertIn( |
687 | f'You have added 1 layer to your project', str(change_notification.text) | 673 | f'You have added 1 layer to your project', str(change_notification.text) |
688 | ) | 674 | ) |
689 | hide_button = self.find('#hide-alert') | 675 | finder = lambda driver: self.find('#hide-alert') |
676 | hide_button = self.wait_until_element_clickable(finder) | ||
690 | hide_button.click() | 677 | hide_button.click() |
691 | self.wait_until_not_visible('#change-notification') | 678 | self.wait_until_not_visible('#change-notification') |
692 | # check tabs(layers, recipes, machines) are displayed | 679 | # check tabs(layers, recipes, machines) are displayed |