AngularJS revolutionized front-end development with features like two-way data binding and dynamic single-page applications (SPAs). However, its asynchronous nature created challenges for traditional automation tools such as Selenium.
To address this, the Angular team introduced Protractor, a NodeJS-based automation framework tailored for Angular apps. But with Protractor having reached its end-of-life, testers now need alternatives. One such option is ngWebDriver, which offers Protractor-like capabilities while supporting Selenium with Java-making it a reliable solution for continuing AngularJS test automation.
Testing AngularJS Applications using Selenium
Selenium is the most popular test automation tool, it provides a lot of flexibility such as support for various programming languages, platform independence, open source, etc. As a test automation tool, it is capable of simulating the user interaction on the browser. However, when it comes to Angular applications it faces the challenges listed below.
- Dynamic content rendering and validating can be challenging using Selenium.
- Asynchronous operations are difficult to handle.
- Angular comes with specific hooks and DOM structure it may be challenging to handle them.
Read More: Angular vs AngularJS
The above factors make not only challenging to automate but also cause flaky tests. To address the above issue you might need to use the custom hooks and custom harness tools, or you can add the already available plugins for Selenium.
ngWebDriver is one such plugin that supports angular test automation.
Challenges in Testing AngularJS with Selenium
Though Selenium is the most popular tool and flexible to customize, It has its challenges when it comes to test automation of Angular applications.
- Flakiness: Angular dynamically renders components after the load() event is triggered. Selenium might try to interact before even those components are triggered. This may cause flakiness of tests.
- Manual Waits: Testers often need to add manual waits to handle Angular’s behavior, which leads to unreliable and flaky tests.
- Angular rendering mechanism: Selenium has no inbuilt capability to understand the angular mechanism such as digest cycle, pending HTTP requests, or rendering queue.
- DOM Structure: The DOM structure that Angular renders may be complex and different from the traditional web application, which may be difficult to handle using Selenium
Read More:How to avoid Flaky Tests?
Introducing ngWebDriver: Bringing Protractor-Like Sync to Selenium
Protractor was launched to support the Angular application. It solved many challenges that existed in the Angular application automation, such as Angular events waiting, rendering cycles, dynamic data rendering, Angular-specific locators, etc. However Protractor has now been deprecated and users are left with only a few options.
ngWebDriver acts as a Java-based bridge, providing similar functionality on top of Selenium.
The ngWebDriver was created by Paul Hammant and it is made as open for all using git repository https://github.com/paul-hammant/ngWebDriver. The ngWebDriver provides similar functionality to Protractor when it is integrated with the Selenium web driver. It can wait for the Angular application to fully load, it supports angular-specific locators, etc.
Key Features of ngWebDriver
Here are the key features of ngWebDriver:
- ngWebDriver can be easily integrated with Selenium Java with maven dependency or manually downloading the Jar.
- It works with Firefox, Chrome, and all the other Selenium WebDriver browsers.
- Automatic Synchronization with AngularJS lifecycle just like Protractor did.
- Handles Angular requests waiting without any extra JavaScript code
- Fully compatible with BrowserStack Automate for cloud-based test automation.
- Supports Page Object Model / Page FactoryDesign patterns.
Setting Up Selenium for AngularJS
Setting up an ngWebDriver is easy. ngWebDriver is available as a maven dependency. You can start by adding the maven dependency.
Step 1. Add ngWebDriver Dependency
Add the below maven dependency to your project
com.paulhammant
ngwebdriver
1.2
Step 2. Setup Webdriver with ngWebDriver
import org.openqa.selenium.chrome.ChromeDriver;import com.paulhammant.ngwebdriver.NgWebDriver;public class AngularNgDriverSetup {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
NgWebDriver ngDriver = new NgWebDriver(driver);
driver.get(“https://juliemr.github.io/protractor-demo/”);
ngWebDriver.waitForAngularRequestsToFinish();
// Continue with your test steps
}
}
In the above code, Use the ChromeDriver to create a driver object. Next, to create a new ngWebDriver object you are passing the Selenium Chrome Driver object. After that, you navigate to the webpage and wait for the Angular application to completely load using the ngWebDriver.waitForAngularRequestsToFinish() function.
Automating AngularJS Applications using Selenium: Example
Consider test case
- Navigate to https://juliemr.github.io/protractor-demo/ website (it’s an Angular application)
- Enter first number as 5
- Enter the second number as 10
- Click on the Go button
- Verify the output is 15
Selenium ngWebDriver example for the above scenario
package com.javaselenium.demo.SelDemo;
import java.util.logging.Level;
import java.util.logging.Logger;import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import com.paulhammant.ngwebdriver.ByAngular;
import com.paulhammant.ngwebdriver.NgWebDriver;import junit.framework.Assert;
public class DemoSelenium {
ChromeDriver driver = new ChromeDriver();
NgWebDriver ngWebDriver = new NgWebDriver(driver);
@Test
public void Test() throws InterruptedException {driver.get(“https://juliemr.github.io/protractor-demo/”);
ngWebDriver.waitForAngularRequestsToFinish();int num1 = 5;
int num2 = 10;
driver.findElement(ByAngular.model(“first”)).sendKeys(String.valueOf(num1));
driver.findElement(ByAngular.model(“second”)).sendKeys(String.valueOf(num2));
driver.findElement(By.id(“gobutton”)).click();
Thread.sleep(10000);
int sum = Integer.parseInt(driver.findElement(By.cssSelector(“h2[class=’ng-binding’]”)).getText());
System.out.println(“Sum Example: “+num1+”+”+num2+” = “+sum);
Assert.assertEquals(num1+num2, sum);
driver.close();
}}
Code Explanation:
In the above code,
- You are creating the Webdriver instance called driver
- ngWebDriver instance is created by calling the newNgWebDriver(driver)
- using driver.get() you are navigating to the desired website
- ngWebDriver.waitForAngularRequestsToFinish() is used to ensure the angular webpage is loaded completely
- using driver.findElement and ByAngular.model you are fetching angular specific locators and using send keys you are typing the values of variable num1 and num2
- Then, the Go button is clicked to fetch the results.
- The results are fetched and validated using the JUnit Assertions.
Output:
Read More:Top 6 Alternatives to Protractor
Best Practices for AngularJS Test Automation with Selenium
As mentioned earlier the Angular application test automation may produce flaky results if it is not handled properly. Following general guidelines helps to produce the most reliable test.
Here are some of the key best practices to follow during the Automation Testing of AngularJS using Selenium:
1. Use Angular-aware locators when possible
While Selenium does not natively support Angular-specific locators, you can use plugins like ngWebDriver to achieve this.
Example:
ByAngular.model(“first”)
2. Call Angular waits before DOM interactions.
One of the major challenges with traditional automation frameworks is that they are not aware of Angular’s rendering logic. Using ngWebDriver you should be able to ensure if angular loading is completed or not.
This helps to ensure that the web component or web page is fully loaded before performing any actions, without this test may fail.
Example:
ngWebDriver.waitForAngularRequestsToFinish();
3. Combine ExpectedConditions with JavascriptExecutor for complex UI flows
The Angular application can be complex if it contains large dynamic data, complex UI flows, or animations in such scenarios combine the Expected conditions with Javascript Executor, which helps to ensure the visibility or presence of the locator before performing an action on it.
Example:
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(“dashboard”)));
ngDriver.waitForAngularRequestsToFinish();
4. Structure using Page Object Model for maintainability
The page object model makes the code more readable and easily maintainable. Consider you are using a text field locator in 20 different places, in the future if the text field locator changes, you might have to update 20 different places.
Using the Page Object Model makes this easy, as you only need to update the locator in one place
Example Structure
CalculatorPage.java
public class CalculatorPage { private WebDriver driver;
private NgWebDriver ngWebDriver;
private By firstInput = ByAngular.model(“first”);
public CalculatorPage(WebDriver driver, NgWebDriver ngWebDriver) {
this.driver = driver;
this.ngWebDriver = ngWebDriver;
}
public void enterFirstNumber(String num) {
driver.findElement(firstInput).sendKeys(num);
}
}
CalculatorTest.java
public class CalculatorTest {
@Test
public void testAddition() {
WebDriver driver = new ChromeDriver();
NgWebDriver ngDriver = new NgWebDriver(driver);
try {
driver.get(“https://juliemr.github.io/protractor-demo/”);
ngDriver.waitForAngularRequestsToFinish();
CalculatorPage calc = new CalculatorPage(driver, ngDriver);
calc.enterFirstNumber(“3”);
} finally {
driver.quit();
}
}
Testing AngularJS Apps on Real Browsers with BrowserStack Automate
Web application architecture has become complex with modern frameworks like Angular, React, and other backend technologies. As it gets more complex, there is more chance that the application can break.
It is important to test your application across various platforms and devices to ensure the application’s behavior and performance.
BrowserStack Automate provides a diverse environment to execute your Angular test automation suite. It has many features that can help to execute your test cases.
- Concurrent Test Execution: It allows to run multiple tests in parallel which reduces the total testing time. This also helps in providing instant feedback.
- Diverse Environment: It provides a diverse environment to execute the tests across multiple browsers and platforms, with no need to worry about maintaining the on-premise infrastructure.
- CI/CD pipeline: You can also integrate BrowserStack tests with the CI/CD pipeline to streamline the testing process.
- Debugging: It provides many debugging capabilities including videos, logs, etc.
- Test on Real Devices and browsers in the cloud for precise and real-world outcomes.
Conclusion
Testing Angular applications is complex and it requires customization in your framework. Traditional test automation frameworks like Selenium cannot handle the angular application natively. Protractor was built to support the Angular application. However, it has now been deprecated.
As Protractor is deprecated, teams working with AngularJS (version 1.x) can use the ngWebDriver plugin to extend Selenium for handling Angular-specific waits.
As the modern web application follows complex architecture it is important to test the application on various breakpoints to ensure application runs smoothly. This includes different operating systems, different browsers, devices, etc.
Having an on-premise infrastructure for such a test environment can be difficult and more cost-consuming. BrowserStack Automate does this by providing a cloud-based execution environment and supporting all major test automation frameworks.
Frequently Asked Questions
1. Why choose Selenium + ngWebDriver over Protractor?
Since the protractor is deprecated it is no longer an option for performing an Angular application test automation. Selenium + ngWebDriver provides an option to automate the Angular application without impacting the existing code.
The ngWebdriver is a plugin that can easily added to the existing framework to support Angular test automation.
2. Can BrowserStack Automate handle Angular waits automatically?
BrowserStack Automate supports integration with many test automation frameworks. It extensively supports the Selenium tool. Since the ngWebDriver is part of the Selenium framework the Angular application waits and other Angular features are taken care of by the framework. BrowserStack provides the execution environment.
3. How to integrate AngularJS Selenium tests in CI/CD pipelines?
Angular Selenium tests can be integrated with CI/CD pipelines using popular tools like Jenkins, Github Actions, CircleCI, etc. BrowserStack also supports real-user environments with CI/CD integration. Refer to the Selenium CI/CD Integration page for more details.