1

I'm doing automated tests(Selenium Java) in a web application that is based on Angular 14.2.12. I check if Angular is loaded using the following code(I paste the whole thing together with jQuery and JS).

public class JSWaiter {

    private static WebDriver jsWaitDriver;
    private static WebDriverWait jsWait;
    private static JavascriptExecutor jsExec;

    //Get the driver from relevant test
    public static void setDriver(ChromeDriver driver) {
        jsWaitDriver = driver;
        jsWait = new WebDriverWait(jsWaitDriver, Duration.ofSeconds(120));
        jsExec = (JavascriptExecutor) jsWaitDriver;
    }

    //Wait for JQuery Load
    public static void waitForJQueryLoad() {
        //Wait for jQuery to load
        ExpectedCondition jQueryLoad = driver -> ((Long) ((JavascriptExecutor) jsWaitDriver)
                .executeScript("return jQuery.active") == 0);

        //Get JQuery is Ready
        boolean jqueryReady = (Boolean) jsExec.executeScript("return jQuery.active==0");

        //Wait JQuery until it is Ready!
        if (!jqueryReady) {
            //Wait for jQuery to load
            jsWait.until(jQueryLoad);
        }
    }

    //Wait for Angular Load
    public static void waitForAngularLoad() {
        String angularReadynessScript = "return window.getAllAngularTestabilities().findIndex(x=>!x.isStable()) === -1";
        angularLoads(angularReadynessScript );
    }

    private static void angularLoads(String angularReadynessScript) {
        try {
            ExpectedCondition angularLoad = driver -> {
                assert driver != null;
                return Boolean.valueOf(((JavascriptExecutor) driver)
                        .executeScript(angularReadynessScript ).toString());
            };

            boolean angularReady = Boolean.parseBoolean(jsExec.executeScript(angularReadynessScript ).toString());

            if (!angularReady) {
                jsWait.until(angularLoad);
            }
        } catch (Exception e) {
            System.out.println("Error occurred: " + e.getMessage());
            e.printStackTrace();
        }
    }

    //Wait Until JS Ready
    public static void waitUntilJSReady() {
        WebDriverWait wait = new WebDriverWait(jsWaitDriver, Duration.ofSeconds(120));
        JavascriptExecutor jsExec = (JavascriptExecutor) jsWaitDriver;

        //Wait for Javascript to load
        ExpectedCondition jsLoad = driver -> ((JavascriptExecutor) jsWaitDriver)
                .executeScript("return document.readyState").toString().equals("complete");

        //Get JS is Ready
        boolean jsReady = jsExec.executeScript("return document.readyState").toString().equals("complete");

        //Wait Javascript until it is Ready!
        if (!jsReady) {
            //Wait for Javascript to load
            wait.until(jsLoad);
        }
    }

    //Wait Until JQuery and JS Ready
    public static void waitUntilJQueryReady() {
        JavascriptExecutor jsExec = (JavascriptExecutor) jsWaitDriver;

        //First check that JQuery is defined on the page. If it is, then wait AJAX
        Boolean jQueryDefined = (Boolean) jsExec.executeScript("return typeof jQuery != 'undefined'");
        if (jQueryDefined) {
            //Pre Wait for stability (Optional)
            sleep(20);

            //Wait JQuery Load
            waitForJQueryLoad();

            //Wait JS Load
            waitUntilJSReady();

            //Post Wait for stability (Optional)
            sleep(20);
        } else {
            System.out.println("jQuery is not defined on this site!");
        }
    }

    //Wait Until Angular and JS Ready
        public static void waitUntilAngularReady() {
        try {
            Object angularCheckVersion = jsExec.executeScript(
                    "return getAllAngularRootElements()[0].attributes['ng-version']");
            if (angularCheckVersion != null) {
                Boolean angularPageLoaded = (Boolean) jsExec.executeScript(
                        "return window.getAllAngularTestabilities().findIndex(x=>!x.isStable()) === -1");
                if (!angularPageLoaded) {
                    sleep(20);
                    waitForJQueryLoad();
                    waitForAngularLoad();
                    sleep(20);
                }
            }
        } catch (Exception e) {
            System.out.println("Error occurred: " + e.getMessage());
            e.printStackTrace();
        }
    }

    //Wait Until JQuery Angular and JS is ready
    public static void waitJQueryAngular() {
        waitUntilJQueryReady();
        waitUntilAngularReady();
    }

    public static void sleep(long milis) {
        try {
            Thread.sleep(milis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
} 

When I check the readiness of Angular with the command:

window.getAllAngularTestabilities().findIndex(x=>!x.isStable()) === -1
everything seems ok, but there is a problem of the type that I am running automated tests, where part of the test cases is based on this popup(assertion) that pops up(is a dynamic element) in app-alerts as a component.

enter image description here

When this popup pops up the above command instead of returning true returns false in the console by which it does not detect this popup and my tests fail.

I have spent two days searching information on this topic and unfortunately found nothing. I would be very grateful for any help.

2 Answers 2

1

I solved this problem by using the command: window.getAllAngularTestabilities().findIndex(x=>!x.isStable()) === -1 as a recursion to wait until Angular fully loads - this is my solution to this issue. I simply skip the popup topic in testing and check the expected result.

0

waitForAngular is a method in Protractor that waits for Angular to finish any pending asynchronous tasks before proceeding with further test execution. If Angular is not ready, it can lead to issues like elements not being visible or clickable, resulting in test failures.

In your case, it seems like you are facing an Angular readiness issue in the app-alerts component while using Selenium. There could be several reasons for this issue, such as long-running asynchronous tasks or network latency.

To troubleshoot this issue, you can try the following steps:

Increase the timeout value for waitForAngular method to allow more time for Angular to become ready. Check if there are any long-running asynchronous tasks in the app-alerts component that might be causing the issue. You can use the browser developer tools to inspect the network requests and console logs to identify any pending tasks. Check for any network latency issues that might be causing delays in the Angular rendering. You can try running the tests on a faster network connection or a local environment to see if the issue persists. Ensure that your Selenium environment is properly configured with the correct version of the browser and Angular framework. If the issue persists even after trying these steps, you might need to dive deeper into the code and debugging to identify the root cause of the issue.

1
  • Thank you for your reply. I would like to point out my mistake regarding waitForAngular, I actually mixed up the terms and removed from the name of this issue due to the fact that I do not use this extension. As for what I did after your answer: tried doing delays in Selenium in various ways, updated everything I could in the project, there are no pending requests or other things in the console. Unfortunately, I still don't know how I would improve it so that it works.
    – Serwa
    Commented Mar 16, 2023 at 9:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.