I have a Selenium test suite that is running Selenium integration tests against a number of web applications, some that are written in Angular 2+, and some that are written in AngularJS.
We use a custom ExpectedCondition
with WebDriverWait
that we use to make test cases wait until AngularJS apps have finished loading, in order to avoid waiting an arbitrary amount of time:
private static ExpectedCondition<Boolean> angularIsFinished() {
return new ExpectedCondition<Boolean>() {
public Boolean apply(final WebDriver driver) {
Object result = null;
while(result == null || result.toString().equals("undefined")) {
result = ((JavascriptExecutor)driver).executeScript("return typeof angular;");
try {
Thread.sleep(200L);
} catch (final InterruptedException ex) {
logger.error("Error while trying to sleep", ex);
}
}
final String script = " var el = document.querySelector(\"body\");\n" +
" var callback = arguments[arguments.length - 1];\n" +
" angular.element(el).injector().get('$browser').notifyWhenNoOutstandingRequests(callback);";
((JavascriptExecutor)driver).executeAsyncScript(script);
return true;
}
public String toString() {
return "Wait for AngularJS";
}
};
}
However, return typeof angular;
will always return undefined
for an Angular 2+ app. Is there a similar way to AngularJS's notifyWhenNoOutstandingRequests that you can use to determine when an Angular 2+ app has finished loading?
This question mentions using NgZone
as a possible solution, but how would you get a handle on that via a script executed via JavascriptExecutor
?