diff mbox series

[4/5] tests/selenium_helpers_base: Add wait_until_element_clickable

Message ID 20260901225555.2254932-4-richard.purdie@linuxfoundation.org
State New
Headers show
Series [1/5] toaster: Rename wait_until_element_clickable -> wait_under_finder_clickable | expand

Commit Message

Richard Purdie Sept. 1, 2026, 10:55 p.m. UTC
Add a version of the wait function that works on a specific element but
can also scroll to make the element clickable. To do this we need
to add an optional scroll function to the core wait function, but this
may be useful in other functions here eventually.

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
---
 .../tests/browser/selenium_helpers_base.py    | 20 +++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/lib/toaster/tests/browser/selenium_helpers_base.py b/lib/toaster/tests/browser/selenium_helpers_base.py
index ca27b3b9877..ce108e2fccc 100644
--- a/lib/toaster/tests/browser/selenium_helpers_base.py
+++ b/lib/toaster/tests/browser/selenium_helpers_base.py
@@ -27,7 +27,9 @@  from selenium.webdriver.common.by import By
 from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
 from selenium.common.exceptions import NoSuchElementException, \
         StaleElementReferenceException, TimeoutException, \
-        SessionNotCreatedException, WebDriverException
+        SessionNotCreatedException, WebDriverException, \
+        ElementNotInteractableException
+from selenium.webdriver.common.action_chains import ActionChains
 
 def create_selenium_driver(cls,browser='chrome'):
     # set default browser string based on env (if available)
@@ -98,7 +100,7 @@  class Wait(WebDriverWait):
         self._POLL_FREQUENCY = poll
         super(Wait, self).__init__(driver, self._TIMEOUT, self._POLL_FREQUENCY)
 
-    def until(self, method, message=''):
+    def until(self, method, message='', scroll=None):
         """
         Calls the method provided with the driver as an argument until the
         return value is not False.
@@ -107,9 +109,14 @@  class Wait(WebDriverWait):
         end_time = time.time() + self._timeout
         while True:
             try:
+                if scroll:
+                    scroll(self._driver)
                 value = method(self._driver)
                 if value:
                     return value
+
+            except ElementNotInteractableException:
+                pass
             except NoSuchElementException:
                 pass
             except StaleElementReferenceException:
@@ -255,6 +262,15 @@  class SeleniumTestCaseBase(unittest.TestCase):
         Wait(self.driver, timeout=timeout).until(is_clickable, msg)
         return finder(self.driver)
 
+    def wait_until_element_clickable(self, element, timeout=Wait._TIMEOUT):
+        """ Wait until element is clickable """
+        WebDriverWait(self.driver, timeout=timeout).until(lambda driver: self.driver.execute_script("return jQuery.active == 0"))
+        is_clickable = lambda driver: (element.is_displayed() and element.is_enabled())
+        scroll = lambda driver: ActionChains(driver).move_to_element(element).perform()
+        msg = 'A matching element never became be clickable'
+        Wait(self.driver, timeout=timeout).until(is_clickable, msg, scroll=scroll)
+        return
+
     def wait_until_focused(self, selector):
         """ Wait until element matching CSS selector has focus """
         is_focused = \