Python Selenium: wait until an element is no longer stale?

后端 未结 4 1790
故里飘歌
故里飘歌 2021-01-18 12:19

I have a situation in which I want to wait until an element is no longer STALE i.e. until an elements gets connected to the DOM. Following wait options do not work somehow:<

相关标签:
4条回答
  • 2021-01-18 12:49
    WebDriverWait(browser, waitTime).until(EC.presence_of_element_located(
                    (By.XPATH or By.id or w/e you want, " xpath or id name")))
    
    0 讨论(0)
  • 2021-01-18 13:01

    A stale element is an element reference that you have stored that is no longer valid because the page, part of the page, or maybe just the element was refreshed. A simple example

    element = driver.find_element_by_id("elementID")
    # do something that refreshes the page
    element.click()
    

    Here element.click() will throw a stale element exception because the reference was stored before the refresh but used (clicked) after the refresh. In this case, that reference is no longer valid. Once a reference is stale, it never becomes "unstale"... that reference can never be used again. The only way to fix that is to store the reference again.

    NOTE: Your code sample is not correct for .staleness_of(). It takes a web element reference, not a locator. You need an existing reference to wait for it to go stale. See the docs.

    Now to solve the problem... you need to wait for the refresh to complete and then get a new reference.

    element = driver.find_element_by_id("elementID")
    # do something that refreshes the element
    self.wait.until(EC.staleness_of(element))
    element = self.wait.until(EC.visibility_of_element_located((By.ID, "elementID")))
    # do something with element
    

    Waiting for the element to become stale waits for the element reference to be lost, which means the element has changed/refreshed. Once we know the element has changed, we can now get a new reference to it. In this case, waiting for the element to become visible. We now have a new reference stored in our variable that we can use without stale element exceptions.

    0 讨论(0)
  • 2021-01-18 13:03

    From the documentation:

    Staleness of:

    class staleness_of(object):
        """ Wait until an element is no longer attached to the DOM.
        element is the element to wait for.
        returns False if the element is still attached to the DOM, true otherwise.
        """
        def __init__(self, element):
            self.element = element
    
        def __call__(self, ignored):
            try:
                # Calling any method forces a staleness check
                self.element.is_enabled()
                return False
            except StaleElementReferenceException:
                return True
    

    Element to be clickable:

    class element_to_be_clickable(object):
        """ An Expectation for checking an element is visible and enabled such that
        you can click it."""
        def __init__(self, locator):
            self.locator = locator
    
        def __call__(self, driver):
            element = visibility_of_element_located(self.locator)(driver)
            if element and element.is_enabled():
                return element
            else:
                return False
    

    As you can see, both use the same method is_enabled() in order to perform the check.

    0 讨论(0)
  • 2021-01-18 13:10

    As you want to pick up the text property once the WebElement is no longer stale, you can use the following :

    wait1 = WebDriverWait(driver, 10)
    wait1.until(expected_conditions.text_to_be_present_in_element((By.ID, "elementID"), "expected_text1"))
    

    OR

    wait2 = WebDriverWait(driver, 10)
    wait2.until(expected_conditions.text_to_be_present_in_element_value((By.ID, "elementID"), "expected_text2"))
    
    0 讨论(0)
提交回复
热议问题