Skip to content

Instantly share code, notes, and snippets.

@elgalu
Last active February 2, 2021 07:14
Show Gist options
  • Save elgalu/2939aad2b2e31418c1bb to your computer and use it in GitHub Desktop.
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){});
};
@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