21

I am using the selenium-webdriverjs. I want to wait for a certain element to be displayed for which I have created an explicit wait as follows and it works just fine,

var displayed = false;
driver.wait(function(){
    driver.findElement(locator).isDisplayed().then(function(value){
        displayed = value;
    });
    return displayed;
}, timeout);

Is this the best I can do or is there a better way to do this? The reason I ask is that the first time ever the wait callback is called (in my case) it will always return false. Only subsequently when the isDisplayed promise is executed will the value of displayed change.

2 Answers 2

28

Your code is mixing a synchronous return with asynchronous callbacks, the following code should do the right thing:

return driver.wait(function() {
    return driver.findElement(locator).isDisplayed();
}, timeout);

The inner function will return a promise that driver.wait will wait for and will take its value (true/false) as the waiting condition.

Sign up to request clarification or add additional context in comments.

6 Comments

Hello guys, this solution gave me Error: This Deferred has already been resolved. Did this work for you?
instead, driver.isElementPresent(locator); worked for me, for those of you who could not use this solution :)
The "timeout" appears to be in milliseconds, by the way. I know it usually is, in JavaScript, but this is a binding so I wasn't too sure. Docs didn't bother to specify. Thanks for the answer. Haeljeong87s tip worked for me.
@coudy (and all): You mentioned that Moiz Raza was "mixing a synchronous return with asynchronous callbacks". I'm having the same problem - I don't know which are which! Is there a way to know which callbacks/functions are synchronous and which are asynchronous? I'm finding this all terribly confusing...
@rinogo Generally, an operation that takes time or involves external actors (browser, filesystem) will be async, and the function will take a callback. Some "by default" async functions have sync counterparts with "Sync" appended to the function name.
|
5

To avoid much of the confusion involved in the asynchronous flavors of webdriver and js, you could give webdriver-sync a try: https://npmjs.org/package/webdriver-sync

It's been my experience that the async versions of the webdriver API become difficult to read after too many nested callbacks.

This of course assumes that you don't have requirements to remain asynchronous.

Disclaimer: I am the creator of this piece of software (webdriver-sync)

3 Comments

You should try Webdriver Js (code.google.com/p/selenium/wiki/WebDriverJs) which is the "official" javascript version of webdriver provided by Selenium folks. Additionally, it's not difficult to read as webdriver js provides a "promises manager" that let you write/execute your code in a sync way by using "Control Flows" (code.google.com/p/selenium/wiki/WebDriverJs#Control_Flows). By using this, your code will be even more readable!
@cSn, I really love that the Webdriver JS team has made the effort to look as synchronous as possible; however, as was mentioned here, it is often confusing to know what is synchronous and what is not. Even with a promise based approach, you still end up with scenarios where you fall into nested callbacks (like doing something after you've retrieved an element's text).
Here is a gist that shows a version of the solution written in a purely synchronous way using webdriver-sync.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.