1

I am automating one angular based application with Selenium WebDriver(Java).

In my AUT(Application Under Test) after selecting any option from dropdown it loads the data into the page. Now this loading is ajax based, basically it calls a webservice and return the data but in page loading spinner or message is not showing in this interval. Previously I use this following javascript within explicit wait.

notDisplay = Boolean.valueOf(((JavascriptExecutor) input)
  .executeScript("return angular.element(document).injector()
  .get('$http').pendingRequests.length === 0")
  .toString());

But now it is not working. Not working means it always return true so it is not waiting to wait for loading.

This application is using angular so I try to implement angular based wait strategy, but I previously also try with the jQuery or JS wait strategy but it is also not working. For jQuery I use the following JavaScriptExecutor

boolean jqueryReady = (Boolean) ((JavascriptExecutor)driver)
  .executeScript("return jQuery.active==0")

Can anyone please help me on this. I also attach the DOM structure for better understanding of the application

<head>
<meta charset="utf-8">
<title>XISOT | Energy Software</title>
<base href="/">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="assets/css/font-include.css" rel="stylesheet">
<link href="assets/css/datepicker-theme.css" rel="stylesheet">
<link href="assets/css/component.css" rel="stylesheet">
<link href="assets/css/custom.css" rel="stylesheet">
<script async="" src="https://www.google-analytics.com/analytics.js">
<script async="" src="https://www.google-analytics.com/analytics.js">
<script async="" src="https://www.google-analytics.com/analytics.js">
<script async="" src="https://www.google-analytics.com/analytics.js">
<script async="" src="https://www.google-analytics.com/analytics.js">
<script async="" src="https://www.google-analytics.com/analytics.js">
<script src="https://use.fontawesome.com/webfontloader/1.6.24/webfontloader.js">
<script async="" src="https://www.googletagmanager.com/gtm.js?id=GTM-MH7JJN7">
<script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.js">
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.js">
<script src="https://use.fontawesome.com/7fbaaf4e79.js">
<script src="https://cdnjs.cloudflare.com/ajax/libs/accounting.js/0.4.1/accounting.min.js">
<link rel="stylesheet" media="screen" href="https://cdnjs.cloudflare.com/ajax/libs/handsontable/0.30.0/handsontable.full.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/handsontable/0.30.0/handsontable.full.js">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.3/Chart.bundle.min.js">
<script src="https://www.google.com/jsapi">
<script>
<link rel="stylesheet" href="https://use.fontawesome.com/7fbaaf4e79.css" media="all">
<script src="https://www.google.com/uds/?file=visualization&v=1.0&packages=corechart" type="text/javascript">
<link href="https://www.google.com/uds/api/visualization/1.0/40ff64b1d9d6b3213524485974f36cc0/ui+en.css" type="text/css" rel="stylesheet">
<script src="https://www.google.com/uds/api/visualization/1.0/40ff64b1d9d6b3213524485974f36cc0/format+en,default+en,ui+en,corechart+en.I.js" type="text/javascript">
<script src="https://www.gstatic.com/charts/loader.js">
<link href="styles.77279c25a29673778a1c.bundle.css" rel="stylesheet">
<style>
<script type="text/javascript" charset="utf-8" async="" src="0.9bd994105eb2d54dba78.chunk.js">
<script type="text/javascript" charset="utf-8" async="" src="10.328d3d60aa813c93c06a.chunk.js">
<script type="text/javascript" charset="utf-8" async="" src="1.af512bfedea06d5a0cbc.chunk.js">
<style>
<style>
<style>
<style>
</head>
<body class="" style="padding-right: 0px;">
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-MH7JJN7" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<******-cli-app ng-version="4.0.1">
<script type="text/javascript" src="inline.a72ddd58b7d594fb4f3e.bundle.js">
<script type="text/javascript" src="polyfills.c88a23e25eb2f45b7bb7.bundle.js">
<script type="text/javascript" src="scripts.fd3b917905e45b8ba8f8.bundle.js">
<script type="text/javascript" src="vendor.ebddd23038be460d8b8d.bundle.js">
<script type="text/javascript" src="main.f9ced3beb42f51486f9b.bundle.js">
<script id="" type="text/javascript">
<script id="" type="text/javascript">
<script id="" type="text/javascript">
<script id="" type="text/javascript">
<script id="" type="text/javascript">
<script id="" type="text/javascript">
</body>
saba
  • 539
  • 1
  • 14
  • 30
  • Please read why [a screenshot of code is a bad idea](https://meta.stackoverflow.com/questions/303812/discourage-screenshots-of-code-and-or-errors). Paste the code and properly format it instead. – JeffC Aug 05 '17 at 20:52
  • Also,"not working" is vague. Please indicate how it's not working and paste any error messages, etc. that are relevant. – JeffC Aug 05 '17 at 20:53
  • You might want to combine the [solution check page load with javascript](https://stackoverflow.com/questions/33348600/selenium-wait-for-ajax-content-to-load-universal-approach) and the [solution check if page load via an specific element after page loaded](https://stackoverflow.com/questions/6201425/wait-for-an-ajax-call-to-complete-with-selenium-2-web-driver). Or you can use [solution check if ajax spinner loading icon is available](http://automationrhapsody.com/efficient-waiting-for-ajax-call-data-loading-with-selenium-webdriver/) – TuyenNTA Aug 06 '17 at 00:12
  • @Jeffs Thanks for your advice I modify my question as per your suggestion. – saba Aug 06 '17 at 06:58
  • @Tuyen Nguyen I already mentioned that I tried with wait for jQuery and js wait but it is always return true so means it shows page is loaded, for spinner and loader part I already mentioned that it is not showing in my page as per design. – saba Aug 06 '17 at 07:04
  • I used to have the same problem with you and I solve the problem with the first link I mention above. When I am using the selenium on IE Webdriver it won't work but it works well on chrome. The only solution that I can find is using a explicit wait (Thread.sleep). – TuyenNTA Aug 06 '17 at 22:07

2 Answers2

0

If your application is using angular 5 or above, use below java script.

String angularwait = "return window.getAllAngularTestabilities().findIndex(x=>!x.isStable()) === -1"

notDisplay = Boolean.valueOf(((JavascriptExecutor) input).executeScript(angularwait).toString());
0

Angular does a lot in the background apart from your check. You can have the below code snippet in a separate class and call the method (waitUntilAngularReady) in your desired class. Also, you must send a WebDriver object to this Class (setDriver method) in a comfortable place in your project. This is working fine for me for Angular version 7.2.0.

public class WaiterForAngular{
 private WebDriver driver;
    private WebDriverWait jsWait;
    private JavascriptExecutor jsExec;
 
    //Get the driver 
    public void setDriver (WebDriver driver) {
        jsWait = new WebDriverWait(driver, 10);
        jsExec = (JavascriptExecutor) driver;
}

        public void waitUntilAngularReady() {
        try {
        Object angular5Check = jsExec.executeScript(
        "return getAllAngularRootElements()[0].attributes['ng-version']");
        if (angular5Check != null) {
        Boolean angularPageLoaded = (Boolean) jsExec.executeScript(
        "return window.getAllAngularTestabilities().findIndex(x=>!x.isStable()) === -1");
        if (!angularPageLoaded) {
        sleep(10);
        waitForAngular5Load();
        sleep(10);
        }
        }
        } catch (Exception e) {
        }
        }
    
        private void waitForAngular5Load() {
                String angularReadynessScript = "return window.getAllAngularTestabilities().findIndex(x=>!x.isStable()) === -1";
                angularLoads(angularReadynessScript );
            }
    
private void angularLoads(String angularReadynessScript ) {
        try {
            ExpectedCondition<Boolean> angularLoad = driver -> Boolean.valueOf(((JavascriptExecutor) driver)
                .executeScript(angularReadynessScript ).toString());
 
            boolean angularReady = Boolean.valueOf(jsExec.executeScript(angularReadynessScript ).toString());
 
            if (!angularReady) {
                jsWait.until(angularLoad);
            }
        } catch (Exception e) {
        }
    }


        private void sleep(long milliseconds){
        try{
        Thread.sleep(milliseconds);
        }
        catch(Exception e){
        }
}
Arun
  • 35
  • 8