Most Viewed Pages

2.8.19

NgWebDriver - Alternative to Protractor for AngularJS

AngularJS is an opensource framework for building web applications using JavaScript. Over the years it has become quite popular and any new web-app built these days has elements of AngularJS.

What this means under the hood is that AngularJS could result in some pretty complex DOM for the web pages, with its own custom tags like ng-app, ng-model, ng-bind, ng-repeat etc.

To help with testing, a new set of purpose-built tools targeting AngularJS have cropped up, and Protractor is one of the leaders in this field, and has gained good traction in the QA community.
Protractor is an end-to-end framework built using the JavaScript bindings of Selenium and its own locator methods to work with the AngularJS tags.

But the number of teams using Java + Selenium far out-number those using JavaScript + Selenium, and as such its difficult for them to incorporate Protractor in their own Java frameworks.
This is specially true for teams that already have a mature framework which supports multiple technologies, not just Web. And as it is usually the case, just UI-based testing is not the only goal of these teams. Hence, it makes little sense for them to use Protractor for testing.
And AngularJS is just one of the many ways we build apps - its just a small feature in the bigger scope of things.
And to test those, what we really need is a library that can be incorporated easily in the existing framework - not a new tool all together.

NgWebDriver is one such java library.

It has many useful methods to work with AngularJS locators, just as in Protractor (in fact it internally leverages Protractor to work with AngularJS).

With NgWebDriver we dont need to depend on Protractor at all because we can just merge this in our existing framework and use it as and when we need to.
This removes the need to change our framework just for AngularJS.

Maven dependency to add NgWebDriver library -

<dependency>
<groupId>com.paulhammant</groupId>
<artifactId>ngwebdriver</artifactId>
<version>1.1.4</version>
</dependency>

Sample code shows how to use it.

package main.java.com.automation.keyword.app;

import org.apache.log4j.Logger;
import org.apache.xmlbeans.impl.xb.xsdschema.Public;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import com.paulhammant.ngwebdriver.ByAngular;
import com.paulhammant.ngwebdriver.NgWebDriver;
import main.java.com.automation.keyword.driver.Driver;
import main.java.com.automation.keyword.driver.Utils;

public class NgWebDriverPoC {

public Utils utils = new Utils();

public Logger log = Logger.getLogger(PoC.class.getName());

public void angularWait(WebDriver driver) {

/*
* Need to downcast to the NgWebDriver in order to use some of its methods
*/
try {

NgWebDriver ngWebDriver = new NgWebDriver((JavascriptExecutor) driver);
ngWebDriver.waitForAngularRequestsToFinish();
log.info("waiting for Angular Requests to finish");

//  The waitForAngularRequestsToFinish method throws up ScriptTimeoutException many times and its better to catch it than have the script fail
} catch (ScriptTimeoutException e) {
log.info("ScriptTimeoutException while waiting for Angular Requests to finish");
}
}

public void angularJSDemo() {

String angularURL = "https://hello-angularjs.appspot.com/sorttablecolumn";

utils.openBrowser(angularURL);

WebDriver driver = Driver.getDriver();

angularWait(driver);

/*
* By adding the NgWebDriver library we can directly call some of its methods to locate angular elements We dont
* need to downcast the driver object
*/
driver.findElement(ByAngular.model("name")).sendKeys("ABC");
driver.findElement(ByAngular.model("employees")).sendKeys("100");
driver.findElement(ByAngular.model("headoffice")).sendKeys("Charlotte NC");
driver.findElement(ByAngular.buttonText("Submit")).click();

String hqCity = driver.findElement(ByAngular.repeater("company in companies").row(3).column("name")).getText();
log.info("City - " + hqCity);
hqCity = driver.findElement(ByAngular.repeater("company in companies").row(2).column("headoffice")).getText();
log.info("City - " + hqCity);

}

}



No comments:

Post a Comment