Hi all, during the last two weeks I was dealing with the best solution to wait for both JQuery, Angular and JavaScript (JS) in my Selenium (Java) test codes and finally, I found a significantly stable solution without silly sleep() statements to share with you.
In this period, I searched maybe more than 20 articles and sites to find best and unique solutions and in this article, I combined all solutions in only one method. This is “WaitJQueryAngular()“. When you need to wait for an asynchronous wait, you can use the below methods as your project type.
Then, my solution upgraded by Colm Murphy and he added Angular 5 synchronization method as well. Thanks to him. I updated code snippet on 18 Feb 2019.
I know that you wonder to know what it does? First, it waits JQuery is Ready? and then waits Angular is Ready? and if JQuery or Angular is ready? Then it checks JS is ready? If all of them are ready then the code will continue to run the next statements. Also, I added a control point that checks JQuery and Angular are defined or not. It is important that if the any of them is not defined in the page, code skips asynchronous wait statements. If this control does not exist, we will get a JS error.
You can just add below methods in your code and use “WaitJQueryAngular()” for an asynchronous wait in your test automation codes.
- Add below JSWaiter utility class into your project.
- Then, send WebDriver object to JSWaiter Class in a convenient place in your project by adding this line: “JSWaiter.setDriver(driver);”
- Finally, you can use any of the methods below in your test code:
- JSWaiter.waitJQueryAngular(); –> Both waits JQuery, Angular, JS
- waitUntilAngularReady(); –> It only waits Angular and JS
- waitUntilJQueryReady(); –> It only waits JQuery and JS
- waitUntilAngular5Ready(); –> Waits for Angular 5 projects
Note: I added waitUntilJSReady(); call both in waitUntilJQueryReady() and waitUntilAngularReady() methods. In this way, if your test site only comprises of Angular or JQuery, you can just use the relevant method to wait asynchronous operations.
Note: You should combine this asynchronous wait solution with the synchronous explicit wait statements to get highest stability in your tests. If you face with a problem, please let me know.
Github Link of a Sample Project: https://github.com/swtestacademy/JSWaiter (It is not updated. Below code snippet is the latest version. You should update JSWaiter class when u clone this project.)
JQuery, Angular, and JavaScript Waiter
public class JSWaiter { private static WebDriver jsWaitDriver; private static WebDriverWait jsWait; private static JavascriptExecutor jsExec; //Get the driver public static void setDriver (WebDriver driver) { jsWaitDriver = driver; jsWait = new WebDriverWait(jsWaitDriver, 10); jsExec = (JavascriptExecutor) jsWaitDriver; } private void ajaxComplete() { jsExec.executeScript("var callback = arguments[arguments.length - 1];" + "var xhr = new XMLHttpRequest();" + "xhr.open('GET', '/Ajax_call', true);" + "xhr.onreadystatechange = function() {" + " if (xhr.readyState == 4) {" + " callback(xhr.responseText);" + " }" + "};" + "xhr.send();"); } private void waitForJQueryLoad() { try { ExpectedCondition<Boolean> jQueryLoad = driver -> ((Long) ((JavascriptExecutor) this.driver) .executeScript("return jQuery.active") == 0); boolean jqueryReady = (Boolean) jsExec.executeScript("return jQuery.active==0"); if (!jqueryReady) { jsWait.until(jQueryLoad); } } catch (WebDriverException ignored) { } } private void waitForAngularLoad() { String angularReadyScript = "return angular.element(document).injector().get('$http').pendingRequests.length === 0"; angularLoads(angularReadyScript); } private void waitUntilJSReady() { try { ExpectedCondition<Boolean> jsLoad = driver -> ((JavascriptExecutor) this.driver) .executeScript("return document.readyState").toString().equals("complete"); boolean jsReady = jsExec.executeScript("return document.readyState").toString().equals("complete"); if (!jsReady) { jsWait.until(jsLoad); } } catch (WebDriverException ignored) { } } private void waitUntilJQueryReady() { Boolean jQueryDefined = (Boolean) jsExec.executeScript("return typeof jQuery != 'undefined'"); if (jQueryDefined) { poll(20); waitForJQueryLoad(); poll(20); } } public void waitUntilAngularReady() { try { Boolean angularUnDefined = (Boolean) jsExec.executeScript("return window.angular === undefined"); if (!angularUnDefined) { Boolean angularInjectorUnDefined = (Boolean) jsExec.executeScript("return angular.element(document).injector() === undefined"); if (!angularInjectorUnDefined) { poll(20); waitForAngularLoad(); poll(20); } } } catch (WebDriverException ignored) { } } public void waitUntilAngular5Ready() { 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) { poll(20); waitForAngular5Load(); poll(20); } } } catch (WebDriverException ignored) { } } private void waitForAngular5Load() { String angularReadyScript = "return window.getAllAngularTestabilities().findIndex(x=>!x.isStable()) === -1"; angularLoads(angularReadyScript); } private void angularLoads(String angularReadyScript) { try { ExpectedCondition<Boolean> angularLoad = driver -> Boolean.valueOf(((JavascriptExecutor) driver) .executeScript(angularReadyScript).toString()); boolean angularReady = Boolean.valueOf(jsExec.executeScript(angularReadyScript).toString()); if (!angularReady) { jsWait.until(angularLoad); } } catch (WebDriverException ignored) { } } public void waitAllRequest() { waitUntilJSReady(); ajaxComplete(); waitUntilJQueryReady(); waitUntilAngularReady(); waitUntilAngular5Ready(); } /** * Method to make sure a specific element has loaded on the page * * @param by * @param expected */ public void waitForElementAreComplete(By by, int expected) { ExpectedCondition<Boolean> angularLoad = driver -> { int loadingElements = this.driver.findElements(by).size(); return loadingElements >= expected; }; jsWait.until(angularLoad); } /** * Waits for the elements animation to be completed * @param css */ public void waitForAnimationToComplete(String css) { ExpectedCondition<Boolean> angularLoad = driver -> { int loadingElements = this.driver.findElements(By.cssSelector(css)).size(); return loadingElements == 0; }; jsWait.until(angularLoad); } private void poll(long milis) { try { Thread.sleep(milis); } catch (InterruptedException e) { e.printStackTrace(); } } }
Notes:
– For java.net.SocketTimeoutException you can add below line before get() method. It will also wait for Page Load.
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
Thanks.
-Onur

Onur Baskirt is a Software Engineering Leader with international experience in world-class companies. Now, he is a Software Engineering Lead at Emirates Airlines in Dubai.
HI Onur Baskirt,
this class works with Selenium v2.53.1 but its throwing an error with Selenium 3.4.0
Can you please help as my framework depends heavily on this class to wait for angular api calls
Thanks…
What kind of error message did you get? I need an URL and error message and scenario to check your problem.
I rerun the test and did not face with any errors. Here is the sample code: https://github.com/swtestacademy/JSWaiter
Hi Onur Baskirt,
how to run project?
Download the code from https://github.com/swtestacademy/JSWaiter and open with IntelliJ and run the project. That’s all.
Thanks you!
Best solution ever. Many thanks.
Also do you have a tutorial to setup an automation framework in real projects (with real world examples)
preferably Page object Model ?
Again Many Thanks.
Ray
Hi Ray,
You are welcome. :) I am planning to write a comprehensive real life test automation framework book. If it is finished, I will let you know.
As far as I understand this example for AngularJS. What about Angular 2 ? Can you give example?
I did not have any experience on Angular 2 automation. But it is better to google it. There should be a solution on the web.
Would u try Angular 5 wait for Angular 2? Maybe it will cover that also.
Will this work on Angular 1.5? Since I’m getting message in console “Angular injector is not defined on this site!”.
Note: I’ve used method “waitJQueryAngular()”
Really great solution!!!
It Works perfectly for me
Thank you a lot!!!
I am happy that it works! :) You are welcome.
this doesn’t support angular 2 and plus.
Thank you for your feedback. If I have time, I will find a solution for Angular2 and above soon. By the way, did you ever try Procractor or nightwatch.js? They maybe better solutions for angular2 and above.
Hi Mukesh, I found a small library of WebDriver locators and more for AngularJS (v1.x) and Angular (v2.x +), for Java. They have taken JavaScript from Angular’s Protractor project. While ngWebDriver perfectly compliments the Java version of WebDriver, it has to pass JavaScript up to the browser to interoperate with Angular, and the Protractor project has done the hard work (including testing) to make that solid. You can use ngWebDriver today with the regular Java Selenium2/WebDriver libraries. Like Protractor, ngWebDriver works with Angular versions greater than 1.0.6/1.1.4, and is compatible with Angular 2 applications. Note that for Angular 2 apps, the binding and model locators are not supported. they recommend using by.css.
new NgWebDriver(driver).waitForAngularRequestsToFinish();
Do this if WebDriver can possibly run ahead of Angular’s ability finish it’s MVC stuff in your application.
Library link: https://github.com/paul-hammant/ngWebDriver
Would you try the latest version, please? We added angular 5 wait strategy.
Hi Onur. I would like to convert this code into Python, I have some problems. For example with angularLoad and angularReady, you basically execute the same script. Can I use only one angularReady and check if it is ready. Because in python there is no such cast ExpectedCondition like in Java.
it would be really great if you by any chance have an example in Python. Thank you
Hi Ragnar, I am not an expert on Python. I hope I will be in the future. It is a very strong and promising language in IT sector. However, I know an expert on Python, he is Sergey Pirogov (http://automation-remarks.com/author/). I will try to reach him for help.
Hi Ragnar, If you have the solution for the jswaiter in python, It would be great if you can share the python solution.
Hi,For Mobile Automation, which type of wait you would recommend to use? I’m currently working on mobile automation and using “wait.until.elementvisibility…”
Thanks!
I suggest you use explicit waits and you are doing in a right way.
Hi, I am using angular materiel menus(md-menu), there i have implemented your JSWaiter , still I am getting some TimeoutExceptions randomly.
Hi, this code is written for Angular 1.X, For angular 2.X and more you can use protractor or you can modify my code. Synchronization always a challenge.
You should really update the blog post to indicate this is out of date with modern Angular.
We updated our code for angular 5 as well. Thanks for your comment.
Trying the Angular ready detector on a site that runs Angular 1.0.5, it fails.
https://goodfil.ms
I should clarify just testing the JavaScript snippets in the browser console.
It worked well on our projects. If I find a solution for angular 2.x and above I will update the article. Thank you.
Hello JJ, we updated the code. Fyi. Thank you for your comments.
Hi, under which license is this code available? I couldn’t find anything on github.
There is no license of this code. I wrote this and it is my property and I give it to the all world’s usage for free. :) By the way, if you face some problems, you may also use Awaitility tool. It looks promising and stable. https://github.com/awaitility/awaitility
Thank you for your fast reply. So I am free to use a modified version of this code in my own application.
I had a similiar approach but it was as extensive and robust as yours. So far I haven’t had any problems but I keep your suggestion in mind.
Thanks again.
Hello, I am using method waitForAngularLoad() fro above code. It is throwing error – ‘ unknown error: angular is not defined’.
My application is build with AngularJS5.
Can anyone help please..
This code is worked for former versions of Angular. For the latest versions, it is better to use Protractor. I don’t have any experience on Angular 5.X automation.
We updated the for Angular 5 too. Fyi.
Many Thanks!
Welcome. :)
Hello Sir,
We are working on Angular 1.3 project. I am trying to automate using selenium webdriver and Java and new to this. Problem here is that we are caching everything. So in DOM it always resides.we are hiding using ng-hide etc. Core developers who did have left organization there and no one will be changing it.The main problem is that , till we get response (REST api service calls are called ) all elements are displayed. Once a response is received (status 200- if we try to see in network tab of the chrome browser) based on the outcome the elements are hidden or displayed.
For example as soon as I enter a product code-> GET method with request url is sent. It takes time to get the response. Till that time all other elements like location/etc are displayed. So I can’t wait for the elements to be displayed nor I can force to sleep using thread.sleep as I don’t know how long will it take to get response and will slow down the script.I can’t even use implicit wait because the data entered may be invalid which i will come to know after getting response. If services returns message as invalid product then all the elements like location/code etc will be hidden and a pop up message is displayed.
So I am kind of stuck and I stumbled on your site . I would like to know more about the code
boolean angularReady = Boolean.valueOf(jsExec.executeScript(angularReadyScript).toString());
Does it check and wait for pending request response? What I need is that till I get response(200) my script should be paused. Once I get the response based on the test data my DOM will change and thereafter it will be easy for me to manipulate by checking on the visibility of the elements
Kindly help me on this matter
Thanks in advance.
Did you try invisibility of element? You wrote that when a response comes elements becomes hidden, right? ” If services returns message as invalid product then all the elements like location/code etc will be hidden and a pop up message is displayed.” If you use invisibilityofelement expected condition, maybe it will work for you?
First use invisibilityofelement for “the elements like location/code etc hidden”
Then use visibilityofelement for the popup “a pop up message is displayed.”
Please check here: https://stackoverflow.com/questions/29082862/how-to-wait-until-an-element-no-longer-exists-in-selenium
And please check my webdriver wait article in the site. Selenium 9: Webdriver Wait article.
Thank you.
Also, check here: https://sqa.stackexchange.com/questions/29379/how-to-wait-for-an-api-request-to-return-a-response
Try given solutions.
Hi Onur,
This solution here looks really helpful for my current project. the only problem is that i am a C# , .Net person not able to convert the code to C# completly. Do you think you can help me here??
Regards,Joe
Thank you Joe,
There are some nice solutions were proposed in this link: https://stackoverflow.com/questions/25062969/testing-angularjs-with-selenium
That page contains C# codes for angular wait solutions. Hope it helps. :)
Also, there is a C# code snippet here: https://gist.github.com/npbenjohnson/2ca45e54bd656337caa3
This solution here looks really helpful for my current project. the only problem is that i am a python , .Net person not able to convert the code to python completly. Do you think you can help me here??
I am not using Phyton in my daily development routine. But if you can not do the conversion, pls write here.
hiee
hiee sir ,
while calling the methods of JSWaiter getting the below exceptions:
exception—>java.lang.NullPointerException
FAILED: Ticket
java.lang.NullPointerException
at FunctionalData.JSWaiter.waitUntilAngularReady(JSWaiter.java:131)
at FunctionalData.JSWaiter.waitJQueryAngular(JSWaiter.java:157)
You should debug it sir. You are using an unassigned (null) ojbect.
Hey!:)
This is really helpful and working as expected for Java, Can you please convert and make repo for Selenium c# ? This is many of user looking for. As this is well-structured for Java, we need same for c#. I have referred SO link which you have provided, But can’t go through it.
Here you can find some examples for C# https://stackoverflow.com/questions/25062969/testing-angularjs-with-selenium
Thanks. This is a really good stack overflow answer for C#.
Welcome. :)
b
c
Hi Onur, If we want to understand method defined in JSWaiter class, where to read basics to understand how it is implemented.
Hope you understand my question
Please check here: https://github.com/swtestacademy/JSWaiter
all details in here but change the JSWaiter code with the code which is updated on the site.
Thanks for the great wait class. I needed to make a couple adjustments to make it work.
I needed to change all the places that said: this.driver to be jsWaitDriver. IntelliJ didn’t think this.driver existed.
Also I couldn’t call the methods that were not static. So I changed all the methods to static.
I noticed both of these things were fixed in initial release on Github.
The angular5 method is awesome. I do this to wait for all types of elements.
JSWaiter.waitAllRequest();
Welcome Michael. I am happy that you adjusted and used it in your project.
Selam Onur,
Bizim projemiz VS Code üzerinde Node JS ile oluşturulmuş framework, bir uyguşlamada Ajaxın dolmasını beklemek için waitforJqueryLoad kodunu NodeJS e covert edemedim nasıl bir kod hazırlamalıyım yardımcı olursan çok sevinirim.
Teşekkürler.
Selam Tayfun,
Ben nodeJS de cok iyi degilim ama Ege Aksoz belki yardimci olabilir. Ona sorabilirsiniz linkedin uzerinden.
Saygilar.
Hi Onur,
Could you please update this code to the latest API? It’s a bit out-of-date.
Thank you!
Hi,
I will do it whenever I will have time.
Thanks.