How can I get Selenium Web Driver to wait for an element to be accessible, not just present?

后端 未结 4 1210
不思量自难忘°
不思量自难忘° 2020-11-29 23:06

I am writing tests for a web application. Some commands pull up dialog boxes that have controls that are visible, but not available for a few moments. (They are greyed out,

相关标签:
4条回答
  • 2020-11-29 23:55

    There are already some great answers posted up here, but I thought I would add my solution. Explicit wait etc. are great functions for use in testing with selenium. However explicit wait merely performs the function of a Thread.Sleep() that you can only set one time. The function below is what I used to "Shave off" a few minutes. It waits until the element is "accessible."

        //ALTERNATIVE FOR THREAD.SLEEP
    public static class Wait
    {  
        //public static void wait(this IWebDriver driver, List<IWebElement> IWebElementLIst)
        public static void wait(this IWebDriver driver, By bylocator)
        {
            bool elementPresent = IsPresent.isPresent(driver, bylocator);
            while (elementPresent != true)
            {
                Thread.Sleep(1000);
    
                elementPresent = IsPresent.isPresent(driver, bylocator); 
    
            }
    
        }
    
    }
    

    It is in C#, but to adapt it would not be that difficult. Hope this helps.

    0 讨论(0)
  • 2020-11-29 23:59
        print time.time()
        try:
            print "about to look for element"
            def find(driver):
                e = driver.find_element_by_id("createFolderCreateBtn")
                if (e.get_attribute("disabled")=='true'):
                    return False
                return e
            element = WebDriverWait(driver, 10).until(find)
            print "still looking?"
        finally: print 'yowp'
        print "ok, left the loop"
        print time.time()
    

    Here is what we ended up with. (Thanks to lukeis and RossPatterson.) Note that we had to find all the items by id and then filter by "disabled". I would have preferred a single search pattern, but what can you do?

    0 讨论(0)
  • 2020-11-30 00:01

    I assume the events timeline goes like this:

    1. there are no needed elements on page.
    2. needed element appears, but is disabled:
      <input type="button" id="createFolderCreateBtn" disabled="disabled" />
    3. needed element becomes enabled:
      <input type="button" id="createFolderCreateBtn" />

    Currently you are searching for element by id, and you find one on step 2, which is earlier than you need. What you need to do, is to search it by xpath:

    //input[@id="createFolderCreateBtn" and not(@disabled)]
    

    Here's the difference:

    from lxml import etree
    
    
    html = """
    <input type="button" id="createFolderCreateBtn" disabled="disabled" />
    <input type="button" id="createFolderCreateBtn" />
    """
    
    tree = etree.fromstring(html, parser=etree.HTMLParser())
    
    tree.xpath('//input[@id="createFolderCreateBtn"]')
    # returns both elements:
    # [<Element input at 102a73680>, <Element input at 102a73578>]
    
    
    tree.xpath('//input[@id="createFolderCreateBtn" and not(@disabled)]')
    # returns single element:
    # [<Element input at 102a73578>]
    

    To wrap it up, here's your fixed code:

    try:
        print "about to look for element"
        element_xpath = '//input[@id="createFolderCreateBtn" and not(@disabled)]'
        element = WebDriverWait(driver, 10).until(
                lambda driver : driver.find_element_by_xpath(element_xpath)
        )
        print "still looking?"
    finally: 
        print 'yowp'
    

    UPDATE:
    Repasting the same with the actual webdriver.
    Here's the example.html page code:

    <input type="button" id="createFolderCreateBtn" disabled="disabled" />
    <input type="button" id="createFolderCreateBtn" />
    

    Here's the ipython session:

    In [1]: from selenium.webdriver import Firefox
    
    In [2]: browser = Firefox()
    
    In [3]: browser.get('file:///tmp/example.html')
    
    In [4]: browser.find_elements_by_xpath('//input[@id="createFolderCreateBtn"]')
    Out[4]: 
    [<selenium.webdriver.remote.webelement.WebElement at 0x103f75110>,
     <selenium.webdriver.remote.webelement.WebElement at 0x103f75150>]
    
    In [5]: browser.find_elements_by_xpath('//input[@id="createFolderCreateBtn" and not(@disabled)]')
    Out[5]: 
    [<selenium.webdriver.remote.webelement.WebElement at 0x103f75290>]
    

    UPDATE 2:

    It works with this as well:

    <input type="button" id="createFolderCreateBtn" disabled />
    
    0 讨论(0)
  • 2020-11-30 00:05

    I think something along these lines should work as well:

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions
    
    browser = webdriver.Firefox()
    wait = WebDriverWait(browser, 30)
    wait.until(expected_conditions.presence_of_element_located((By.XPATH, "//*[@id='createFolderCreateBrn' and not(@disabled)]")))
    
    0 讨论(0)
提交回复
热议问题