14

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.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
cSn
  • 2,796
  • 3
  • 23
  • 29

3 Answers3

13

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.

Louis
  • 146,715
  • 28
  • 274
  • 320
  • Cool that you check the behavior on python's API! If that the case then, problem solved! :D – cSn Nov 01 '14 at 01:55
  • THIS is the explanation I've been looking for for a month! I used `.isEnabled()` and ran 100 tests and they all passed, whereas before it was at a 90% pass rate. I hope others find this answer. Thank you so much @Louis – Jason Sep 21 '17 at 23:15
  • 6 years are passed but you still saved my arse :D with this: a) That the element is visible. b) That it is enabled. Basically, i was getting mad because I thought the issue was in the promises, but that's not. Issue is on object visibility/enabled. I solved in JS using this: `const stuff = await driver.findElement(By.xpath('path-to-your-element')); await driver.wait(until.elementIsVisible(stuff), 3000); await driver.wait(until.elementIsEnabled(stuff), 3000); await stuff.click();` – Don Diego Dec 29 '20 at 17:33
3

If you don't care about clicking the object once it's available ** then you can do something like this:

function clickWhenClickable(locator, timeout){
  driver.wait(function(){
    return driver.findElement(locator).then(function(element){
      return element.click().then(function(){
        return true;
      }, function(err){
        return false;
      })
    }, function(err){
      return false;
    });
  }, timeout, 'Timeout waiting for ' + locator.value);    ;
}

** if you just want to check if the element is clickable without having to click it then this snippet is not for you. In that case, I would say webdriver js does not provides the means to do that. (or at least I haven't find it yet, insights welcomed :) )

jmreicha
  • 3,155
  • 7
  • 32
  • 39
cSn
  • 2,796
  • 3
  • 23
  • 29
0

UNTIL seems to be the closest thing in webdriver js for this:

Check: https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/until.html

There are already defined waiting conditions there. I don't know which one should be considered clickeable.

cSn
  • 2,796
  • 3
  • 23
  • 29