Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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, but webdriver still sees them as visible).

How can I tell Selenium to wait for the element to be actually accessible, and not just visible?

    try:         print "about to look for element"         element = WebDriverWait(driver, 10).until(lambda driver : driver.find_element_by_id("createFolderCreateBtn"))         print "still looking?"     finally: print 'yowp' 

Here is the code that I have tried, but it "sees" the button before it is usable and basically charges right past the supposed "wait".

Note that I can stuff a ten second sleep into the code instead of this and the code will work properly, but that is ugly, unreliable, and inefficient. But it does prove that the problem is just that "click" command is racing ahead of the availability of the controls.

like image 574
Skip Huffman Avatar asked Feb 06 '12 14:02

Skip Huffman


People also ask

How do you get Selenium to wait until the element is present?

We can wait until an element is present in Selenium webdriver. This can be done with the help of synchronization concept. We have an explicit wait condition where we can pause or wait for an element before proceeding to the next step. The explicit wait waits for a specific amount of time before throwing an exception.

How wait until elements are visible?

Selenium: Waiting Until the Element Is Visiblevar wait = new WebDriverWait(driver, TimeSpan. FromSeconds(20)); As you can see, we give the WebDriverWait object two parameters: the driver itself and a TimeSpan object that represents the timeout for trying to locate the element.

Is used to tell the web driver to wait for certain conditions?

The Explicit Wait in Selenium is used to tell the Web Driver to wait for certain conditions (Expected Conditions) or maximum time exceeded before throwing “ElementNotVisibleException” exception. It is an intelligent kind of wait, but it can be applied only for specified elements.


1 Answers

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 /> 
like image 59
Misha Akovantsev Avatar answered Oct 16 '22 15:10

Misha Akovantsev