Selenium Chrome DevTools Protocol (CDP)

     In the previous article, we discussed Selenium Relative Locators or Friendly Locators features. In this article, we will discuss Selenium 4’s new APIs for CDP (Chrome DevTools Protocol). This feature will provide greater control over the browser used for testing. You should use the Selenium 4 library or dependency as a prerequisite to access the new APIs for CDP (Chrome DevTools Protocol) feature. The capabilities of the Selenium 4 CDP includes:

  • Simulating Device Mode.
  • Simulate Network Speed.
  • Mocking Geolocation.
  • Capture HTTP Requests.
  • Access Console Logs.
  • Capturing Performance Metrics.
  • Basic Authentication.

     Before starting the above capabilities, I would like to share about Chrome DevTools. Chrome DevTools is a set of tools built directly into Chromium-based browsers like Chrome, Opera, and Microsoft Edge to help developers debug and investigate websites. As automation engineers, we mostly use the Element tab of the Chrome DevTools to inspect elements in the DOM. Now we will discuss all the above capabilities of the Selenium 4 CDP.

Simulating Device Mode

     Nowadays most applications are responsive. The end-users have a variety of platforms, devices and orientations. During testing, we might want to place the application in various dimensions to trigger the responsiveness of the application. To achieve this in Selenium with help of executeCdpCommand() method. This method needs to execute the device’s metrics Emulation.setDeviceMetricsOverride with four required parameters (width, height, mobile and deviceScaleFactor). Following are the sample snippet to simulate device mode:

WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();
DevTools devTools = ((ChromeDriver) driver).getDevTools();
devTools.createSession();
@SuppressWarnings("serial")
HashMap deviceMetrics = new HashMap() {
{
put("width", 400);
put("height", 800);
put("mobile", true);
put("deviceScaleFactor", 50);
}
};
((ChromiumDriver) driver).executeCdpCommand("Emulation.setDeviceMetricsOverride", deviceMetrics);
driver.get("https://journeyofquality.com/");
Simulate Network Speed

     Simulating the network speed is one of the important test cases. Users can access web applications via handheld devices that are connected to wifi or cellular networks. We can test how the application behaves under such conditions where the internet connection is slow (2G) or goes offline intermittently. The CDP command to fake a network connection is Network.emulateNetworkConditions with required parameters (offline, latency, downloadThroughput, uploadThroughput, connectionType). To test offline, you can set the first parameter offline to true. Connection type includes NONE, CELLULAR2G, CELLULAR3G, CELLULAR4G, BLUETOOTH, ETHERNET, WIFI, WIMAX, OTHER. Following are the sample snippet to simulate network speed in 2G situation:

WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();
DevTools devTools = ((ChromeDriver) driver).getDevTools();
devTools.createSession();
// Set the desired network speed
devTools.send(Network.emulateNetworkConditions(false, 20, 20, 50, Optional.of(ConnectionType.CELLULAR2G)));
driver.get("https://journeyofquality.com/");
Mocking Geolocation

     Geolocation testing is the testing of an application for various geographical locations. Geolocation testing is difficult because setting up the infrastructure for all of these physical geolocations is not a feasible solution. By mocking the geolocation, we could cover all the scenarios and more. The CDP command to fake a geolocation is Emulation.setGeolocationOverride with required parameters (latitude, longitude, accuracy). Following are the sample snippet to mock geolocation:

WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();
DevTools devTools = ((ChromeDriver) driver).getDevTools();
devTools.createSession();
@SuppressWarnings("serial")
HashMap coordinates = new HashMap() {
{
put("latitude", 10.56192);
put("longitude", 76.46788);
put("accuracy", 1);
}
};
((ChromiumDriver) driver).executeCdpCommand("Emulation.setGeolocationOverride", coordinates);
driver.navigate().to("https://www.gps-coordinates.net/my-location");
Capture HTTP Requests

     With help of the Selenium CDP feature, we can capture the HTTP transactions the application is invoking and access the method, data, headers and more. First, we have to start capturing network traffic with help of Network.enable. For each request captured by the application we then extract the URL with getRequest().getUrl() and the HTTP Method with getRequest().getMethod(). Once we are done capturing the requests, we can send the CDP command Network.disable to stop capturing the network traffic. Following are the sample snippet to capture the HTTP requests:

WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();
DevTools devTools = ((ChromeDriver) driver).getDevTools();
devTools.createSession();
devTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty()));
devTools.addListener(Network.requestWillBeSent(), entry -> {
System.out.println("Request URI : " + entry.getRequest().getUrl() + "\n" + " with method : "
+ entry.getRequest().getMethod() + "\n");
entry.getRequest().getMethod();
});
driver.get("https://journeyofquality.com/");
devTools.send(Network.disable());
Access Console Logs

     During testing and working on an application with specific data or specific conditions, logs help us in debugging and capturing the error messages, giving more insights that are published in the Console tab of the Chrome DevTools. We can capture the console logs through Selenium scripts. We have to enable the log capture using Log.enable(). For each log captured by the application we then extract the log text with getText() and log level with getLevel() methods. Following are the sample snippet to capture the console logs:

WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();
DevTools devTools = ((ChromeDriver) driver).getDevTools();
devTools.createSession();
devTools.send(Log.enable());
devTools.addListener(Log.entryAdded(), logEntry -> {
System.out.println("Logs: " + logEntry.getText());
System.out.println("Log Level: " + logEntry.getLevel());
});
driver.get("https://journeyofquality.com/2020/11/26/generate-and-validate-selectors-using-chropath/");
}
Capturing Performance Metrics

     Nowadays, poor-performing websites and slower loading pages make unhappy customers. Customers mostly recommend performance benchmarking prior to releasing the application to the market. So we should detect performance bottlenecks iteratively. We can validate these metrics along with the functional regression on every build with the support of the CDP command Performance.enable(), Performance.getMetrics() and Performance.disable(). Following are the sample snippet to capture the performance metrics:

WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();
DevTools devTools = ((ChromeDriver) driver).getDevTools();
devTools.createSession();
devTools.send(Performance.enable(Optional.empty()));
driver.get("https://journeyofquality.com/");
List metrics = devTools.send(Performance.getMetrics());
List metricNames = metrics.stream().map(o -> o.getName()).collect(Collectors.toList());
devTools.send(Performance.disable());
List metricsToCheck = Arrays.asList("Timestamp", "Documents", "Frames", "JSEventListeners",
"LayoutObjects", "MediaKeySessions", "Nodes", "Resources", "DomContentLoaded", "NavigationStart");
metricsToCheck.forEach(
metric -> System.out.println(metric + " is : " + metrics.get(metricNames.indexOf(metric)).getValue()));
Basic Authentication

     Selenium can only able to engage with DOM elements and interacting with browser popups is not supported. So there is a challenge for pop-ups such as authentication dialogs. We can bypass the browser popups by using the CDP APIs to handle the authentication directly with DevTools with help of the CPD command to set additional headers for the requests is Network.setExtraHTTPHeaders. Following are the sample snippet to perform basic authentication:

String username = "guest";
String password = "guest";
WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();
DevTools devTools = ((ChromeDriver) driver).getDevTools();
devTools.createSession();
devTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty()));

// Send authorization header
Map headers = new HashMap<>();
String basicAuth = "Basic "
+ new String(new Base64().encode(String.format("%s:%s", username, password).getBytes()));
headers.put("Authorization", basicAuth);
devTools.send(Network.setExtraHTTPHeaders(new Headers(headers)));

// Open the application
driver.get("https://jigsaw.w3.org/HTTP/Basic/");
String loginSuccessMsg = driver.findElement(By.xpath("//p[normalize-space()='Your browser made it!']")).getText();
if (loginSuccessMsg.contains("Your browser made it!")) {
System.out.println("Login successful");
} else {
System.out.println("Login failed");
}

     I hope you really enjoyed reading this article and also got some idea of the capabilities of Selenium 4 CDP. We can now enhance the tests to capture HTTP network traffic, collect performance metrics, capture console logs, handle basic authentication, and mock geolocations, time zones, and device modes. Try to use the above capabilities in your automation testing if required.

make it perfect!

Leave a comment

Create a website or blog at WordPress.com

Up ↑