Skip to content

Instantly share code, notes, and snippets.

@elgalu
Last active February 2, 2021 07:14
Show Gist options
  • Select an option

  • Save elgalu/2939aad2b2e31418c1bb to your computer and use it in GitHub Desktop.

Select an option

Save elgalu/2939aad2b2e31418c1bb to your computer and use it in GitHub Desktop.
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){});
};
@nederev
Copy link

nederev commented Jan 26, 2015

this saved my day! thank you very much.

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
Copy link

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
Copy link

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
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
Copy link

Really nice solution.

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

Thank you so much...

@dgasi
Copy link

dgasi commented May 12, 2016

Nice man. Helped me a lot.

@ToreyStapleton
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
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
Copy link

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