Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Actively wait for an element present and displayed up to specTimeoutMs ignoring useless webdriver errors like StaleElementError.
/**
* Actively wait for an element present and displayed up to specTimeoutMs
* ignoring useless webdriver errors like StaleElementError.
*
* Usage:
* Add `require('./waitReady.js');` in your onPrepare block or file.
*
* @example
* expect($('.some-html-class').waitReady()).toBeTruthy();
*/
"use strict";
// Config
var specTimeoutMs = 10000; // 10 seconds
/**
* Current workaround until https://github.com/angular/protractor/issues/1102
* @type {Function}
*/
var ElementFinder = $('').constructor;
ElementFinder.prototype.waitReady = function(opt_optStr) {
var self = this;
var driverWaitIterations = 0;
var lastWebdriverError;
function _throwError() {
throw new Error("Expected '" + self.locator().toString() +
"' to be present and visible. " +
"After " + driverWaitIterations + " driverWaitIterations. " +
"Last webdriver error: " + lastWebdriverError);
};
function _isPresentError(err) {
lastWebdriverError = (err != null) ? err.toString() : err;
return false;
};
return browser.driver.wait(function() {
driverWaitIterations++;
if (opt_optStr === 'withRefresh') {
// Refresh page after more than some retries
if (driverWaitIterations > 7) {
_refreshPage();
}
}
return self.isPresent().then(function(present) {
if (present) {
return self.isDisplayed().then(function(visible) {
lastWebdriverError = 'visible:' + visible;
return visible;
}, _isPresentError);
} else {
lastWebdriverError = 'present:' + present;
return false;
}
}, _isPresentError);
}, specTimeoutMs).then(function(waitResult) {
if (!waitResult) { _throwError() };
return waitResult;
}, function(err) {
_isPresentError(err);
_throwError();
return false;
});
};
// Helpers
function _refreshPage() {
// Swallow useless refresh page webdriver errors
browser.navigate().refresh().then(function(){}, function(e){});
};
@olegwn

This comment has been minimized.

Copy link

olegwn commented Jan 26, 2015

this saved my day! thank you very much.

@ghost

This comment has been minimized.

Copy link

ghost commented May 21, 2015

Very nice solution!

If needed, you can remove a lot of lines of code from spec files using waitReady.js by rewriting...

return waitResult;

with...

return self;

This way, you can do...

element.waitReady().then(function (elm) { ... })

@prabinmetals

This comment has been minimized.

Copy link

prabinmetals commented Jun 29, 2015

Great. Solved my issue where an input filed did not load and caused NoSuchElement error (http://stackoverflow.com/questions/31108455/protractor-sendkeys-returns-nosuchelementerror).

@michalpelc

This comment has been minimized.

Copy link

michalpelc commented Oct 20, 2015

Is that solution really work for you ?
Have tried to use it to click on stale elements but sometimes exceptions occurs anyway.

have written is function like that:

function clickWait(element) {
    (element).waitReady().then(function () {
        return element.click();
    });
};

and invoking it like this :

    clickWait(usersPage.element);

where usersPage is my page object.

@matbruc

This comment has been minimized.

Copy link

matbruc commented Jan 7, 2016

Hi, thanks for share this solution. I have a problem while trying to use it.

The error says:
ReferenceError: $ is not defined
for the line 20.

Can you help me with this?
Thanks in advance

@jaguwalapratik

This comment has been minimized.

Copy link

jaguwalapratik commented Apr 28, 2016

Really nice solution.

Solved my problem which i m facing in protractor test with AngularJS + RequireJS setup.

Thank you so much...

@dgasi

This comment has been minimized.

Copy link

dgasi commented May 12, 2016

Nice man. Helped me a lot.

@ToreyStapleton

This comment has been minimized.

Copy link

ToreyStapleton commented Jun 6, 2016

This is awesome -- been using Protractor for awhile and have always relied on Expected Conditions to wait for things. For some reason today I was having an unusually hard time with one of my EC's throwing a stale element error, and I found this code after some googling. Works flawlessly for that same element I was having trouble with earlier. Thanks again!

@jrharshath

This comment has been minimized.

Copy link

jrharshath commented Jul 25, 2016

This is great!

Also, looks like angular/protractor#1102 is resolved after this PR angular/protractor#1633.

@miriamstub

This comment has been minimized.

Copy link

miriamstub commented Nov 10, 2016

This looks awesome, exactly what i looked for, but i have a problem - element(by.id('login_field')) is a protractor function which can not be used on non angular pages. $('#login_field') is giving undefined. How to waitReady for a element on non angular Page ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.