Angular 2 runtime detection

We use Selenium WebDriver to automate our interface-based tests. One of our tasks is to detect when the page really loaded, and Angular 1 was a problem in this regard. We ended up executing this piece of code to determine if Angular 1 was executed:

if(typeof window.angular !== \"undefined\") { var injector = window.angular.element(\"*[ng-app]\").eq(0).injector(); if(injector) { var $rootScope = injector.get(\"$rootScope\"); var $http = injector.get(\"$http\"); if($rootScope.$$phase === \"$apply\" || $rootScope.$$phase === \"$digest\" || $http.pendingRequests.length !== 0) { return false; } } } 

The application we are testing has recently switched to using Angular 2. The code snippet above does not wait for Angular 2 to finish. Any suggestions?

+5
angular selenium webdriver
source share
5 answers

In the case of Angular 2, you need to wait for the stability of the "testabilities" of all Angular 2 applications:

 functions.waitForAllAngular2 = function(callback) { try { var testabilities = window.getAllAngularTestabilities(); var count = testabilities.length; var decrement = function() { count--; if (count === 0) { callback(); } }; testabilities.forEach(function(testability) { testability.whenStable(decrement); }); } catch (err) { callback(err.message); } }; 

Adapted from the Protractor source code . Protractor is a wrapper around javacript selenium bindings from WebDriverJS; designed to test AngularJS applications (not only, but also the most suitable).

+9
source share

I fixed this by writing an action class in which I waited for Angular to do the actions (click, fill, check, etc.) using Paul Hammants ngWebDriver :

 import com.paulhammant.ngwebdriver.NgWebDriver; public class ActionsWithWaits { private NgWebDriver ngdriver; private JavascriptExecutor js; public ActionsWithWaits(){ WebDriver driver = getDriver(); js = (JavascriptExecutor) driver; driver.manage().timeouts().setScriptTimeout(9, TimeUnit.SECONDS); ngdriver = new NgWebDriver(js); } public void waitForAngular(){ ngdriver.waitForAngularRequestsToFinish(); } public void waitAndClick(WebElementFacade button){ waitForAngular(); button.click(); } public void waitAndFillIn(String text, WebElementFacade field){ waitForAngular(); field.type(text); } etc.. 

Now you can simply use these actions instead of the standard actions of selenium, and you do not need to worry about things (=

+1
source share

Using @alecxe's answer, I ended up using the following javascript single liner to check if all Angular Testability are stable

 window.getAllAngularTestabilities().findIndex(x=>!x.isStable()) === -1 
+1
source share

I would select an event from ngAfterViewInit() in the root component

 @Component({ selector: 'my-app', ... }) export class AppComponent { constructor(private renderer:Renderer, private elementRef:ElementRef){} ngAfterViewInit() { this.renderer.invokeElementMethod(this.elementRef.nativeElement, 'dispatchEvent', [new CustomEvent('angular2-loaded', { bubbles: true })]); } } 

and then listen to this event using WebDriver.

0
source share

Based on alexce's answer, this is the code we use to wait for angular in our selenium tests:

 public static void waitForPageLoaded(WebDriver webDriver) { ExpectedCondition<Boolean> expectation = new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driver) { return ((JavascriptExecutor) driver).executeAsyncScript( "var callback = arguments[arguments.length - 1];" + "if (document.readyState !== 'complete') {" + " callback('document not ready');" + "} else {" + " try {" + " var testabilities = window.getAllAngularTestabilities();" + " var count = testabilities.length;" + " var decrement = function() {" + " count--;" + " if (count === 0) {" + " callback('complete');" + " }" + " };" + " testabilities.forEach(function(testability) {" + " testability.whenStable(decrement);" + " });" + " } catch (err) {" + " callback(err.message);" + " }" + "}" ).toString().equals("complete"); } }; try { WebDriverWait wait = new WebDriverWait(webDriver, waitSeconds); wait.until(expectation); } catch (Throwable error) { new Exception("Timeout waiting for Page Load Request to complete."); } } 
0
source share

All Articles