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

nederev commented Jan 26, 2015

Copy link
Copy Markdown

this saved my day! thank you very much.

ghost commented May 21, 2015

Copy link
Copy Markdown

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

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

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

matbruc commented Jan 7, 2016

Copy link
Copy Markdown

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

Really nice solution.

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

Thank you so much...

@dgasi

dgasi commented May 12, 2016

Copy link
Copy Markdown

Nice man. Helped me a lot.

@ToreyStapleton

ToreyStapleton commented Jun 6, 2016

Copy link
Copy Markdown

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

jrharshath commented Jul 25, 2016

Copy link
Copy Markdown

This is great!

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

@miriamstub

Copy link
Copy Markdown

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