cSn cSn - 22 days ago 11
Javascript Question

How do I wait for an element to be clickable in WebDriverJS?

Does anybody know how to wait for a WebElement to be clickable in WebDriverJS?
I already know how to wait for the element to be "visible", but I would need it to be "clickable".. Something similar to expectable conditions in Python binding.
I haven't been able to find something similar in Webdriver Js API.

Answer

There does not seem to be a condition equivalent to Python's selenium.webdriver.support.expected_conditions.element_to_be_clickable. However, looking at the source for that condition, I see that it does two checks:

  1. That the element is visible.

  2. That it is enabled.

So you could wait for both conditions to become true. The following code illustrates how that could be done. It first make an element invisible and disables it, sets some timeouts to make it visible and enable it, and then wait for the two conditions to happen.

var webdriver = require('selenium-webdriver');

var driver = new webdriver.Builder().
   withCapabilities(webdriver.Capabilities.chrome()).
   build();

driver.get('http://www.google.com');

// This script allows testing the wait. We make the element invisible
// and disable it and then set timeouts to make it visible and enabled.
driver.executeScript("\
var q = document.getElementsByName('q')[0];\
q.style.display = 'none';\
q.disabled = true;\
setTimeout(function () {\
    q.style.display = '';\
}, 2000);\
setTimeout(function () {\
    q.disabled = false;\
}, 3000);\
");
driver.findElement(webdriver.By.name('q')).then(function (element) {
    driver.wait(function () {
        return element.isDisplayed().then(function (displayed) {
            if (!displayed)
                return false;

            return element.isEnabled();
        });
    });
    element.sendKeys('webdriver');
});
driver.findElement(webdriver.By.name('btnG')).click();
driver.wait(function() {
 return driver.getTitle().then(function(title) {
   return title === 'webdriver - Google Search';
 });
}, 1000);

driver.quit();

The code may look a bit strange due to the fact that we're working with promises. Not that promises are inherently strange but they take some time getting accustomed to when one is used to work with Python.