-
-
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. | |
* | |
* 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){}); | |
}; |
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) { ... })
Great. Solved my issue where an input filed did not load and caused NoSuchElement error (http://stackoverflow.com/questions/31108455/protractor-sendkeys-returns-nosuchelementerror).
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.
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
Really nice solution.
Solved my problem which i m facing in protractor test with AngularJS + RequireJS setup.
Thank you so much...
Nice man. Helped me a lot.
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!
This is great!
Also, looks like angular/protractor#1102 is resolved after this PR angular/protractor#1633.
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 ?
this saved my day! thank you very much.