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

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 />

Leave a Comment