Tuesday, October 6, 2026

Network Log Capture

 import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v154.network.Network;
import org.openqa.selenium.devtools.v154.network.model.RequestId;

public class NetworkLogCapture {
    public static Logger APP_LOGS = LogManager.getLogger(NetworkLogCapture.class.getName());

    private DevTools devTools;
    private final List<String> failedRequests = new ArrayList<>();

    public void enableNetworkLogging(ChromeDriver driver) {
        devTools = driver.getDevTools();
        devTools.createSession();
        // Store URL per requestId for correlation
        Map<String, String> requestUrlMap = new ConcurrentHashMap<>();

        // Enable Network domain
        devTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(),
                Optional.empty()));

        // Log all requests
        devTools.addListener(Network.requestWillBeSent(), request -> {
            String url = request.getRequest().getUrl();
            requestUrlMap.put(request.getRequestId().toString(), url);
            APP_LOGS.info("\n=== REQUEST ===");
            APP_LOGS.info("URL     : " + url);
            APP_LOGS.info("Method  : " + request.getRequest().getMethod());
            APP_LOGS.info("Headers : " + request.getRequest().getHeaders());
            // Request body (only for POST/PUT)
            request.getRequest().getPostDataEntries().ifPresent(b -> APP_LOGS.info("REQUEST BODY   : " + b));
            // Fetch post data via CDP if not inline
            try {
                RequestId requestId = request.getRequestId();
                String postData = devTools.send(Network.getRequestPostData(requestId)).getPostData();
                APP_LOGS.info("[REQUEST BODY - CDP] " + postData);
            } catch (Exception e) {
                APP_LOGS.info("[REQUEST BODY] Not available: " + e.getMessage());
            }
        });

        // Log all responses
        devTools.addListener(Network.responseReceived(), response -> {
            int status = response.getResponse().getStatus();
            String url = response.getResponse().getUrl();

            // Flag non-2xx responses (blocked, failed, etc.)
            if (status >= 400 || status == 0) {
                failedRequests.add(status + " | " + url);
                APP_LOGS.info("\n=== RESPONSE HEADERS ===");
                APP_LOGS.info("Status  : " + status);
                APP_LOGS.info("URL     : " + url);
                APP_LOGS.info("Headers : " + response.getResponse().getHeaders());
            }
        });

        // Log load failures (blocked by firewall/CSP)
        devTools.addListener(Network.loadingFinished(), finished -> {
            String url = requestUrlMap.getOrDefault(finished.getRequestId().toString(), "");
            try {
                Network.GetResponseBodyResponse body = devTools.send(Network.getResponseBody(finished.getRequestId()));

                APP_LOGS.info("\n=== RESPONSE BODY (" + url + ") ===");
                APP_LOGS.info(body.getBase64Encoded() ? new String(java.util.Base64.getDecoder().decode(body.getBody()))
                        : body.getBody());
            } catch (Exception e) {
                APP_LOGS.info("[RESPONSE BODY] Skipped: " + e.getMessage());
            }
        });

        // Log load failures (blocked by firewall/CSP)
        devTools.addListener(Network.loadingFailed(), failed -> {
            APP_LOGS.error("[FAILED] " + failed.getErrorText() + " | blocked=" + failed.getBlockedReason()
                    + " | url type=" + failed.getType());
        });
    }

    public void printFailedRequests() {
        APP_LOGS.info("=== FAILED/BLOCKED REQUESTS ===");
        failedRequests.forEach(msg -> APP_LOGS.error(msg));
    }
}

Friday, April 10, 2026

Appium Automating Mobile Gestures

Android gesture: There is a couple of basic gestures, like swipe, fling or pinch, which are commonly used in Android applications 

public void swipeUp() {
        Dimension size = driver.manage().window().getSize();
        int startX = size.getWidth() / 2;
        int startY = (int) (size.getHeight() * 0.8);
        int endY = (int) (size.getHeight() * 0.2);
        performSwipe(startX, startY, startX, endY);
    }

    public void swipeDown() {
        Dimension size = driver.manage().window().getSize();
        int startX = size.getWidth() / 2;
        int startY = (int) (size.getHeight() * 0.2);
        int endY = (int) (size.getHeight() * 0.8);
        performSwipe(startX, startY, startX, endY);
    }

    public void swipeLeft() {
        Dimension size = driver.manage().window().getSize();
        int startX = (int) (size.getWidth() * 0.8);
        int endX = (int) (size.getWidth() * 0.2);
        int y = size.getHeight() / 2;
        performSwipe(startX, y, endX, y);
    }

    public void swipeRight() {
        Dimension size = driver.manage().window().getSize();
        int startX = (int) (size.getWidth() * 0.2);
        int endX = (int) (size.getWidth() * 0.8);
        int y = size.getHeight() / 2;
        performSwipe(startX, y, endX, y);
    }

    public void longPress(WebElement element) {
        Point center = getCenter(element);
        PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
        Sequence longPressSeq = new Sequence(finger, 0);
        longPressSeq.addAction(finger.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), center.getX(), center.getY()));
        longPressSeq.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
        longPressSeq.addAction(new Pause(finger, Duration.ofSeconds(2)));
        longPressSeq.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
        driver.perform(Collections.singletonList(longPressSeq));
    }

    public void doubleTap(WebElement element) {
        Point center = getCenter(element);
        PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
        Sequence doubleTapSeq = new Sequence(finger, 0);
        doubleTapSeq.addAction(finger.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), center.getX(), center.getY()));
        doubleTapSeq.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
        doubleTapSeq.addAction(new Pause(finger, Duration.ofMillis(50)));
        doubleTapSeq.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
        doubleTapSeq.addAction(new Pause(finger, Duration.ofMillis(100)));
        doubleTapSeq.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
        doubleTapSeq.addAction(new Pause(finger, Duration.ofMillis(50)));
        doubleTapSeq.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
        driver.perform(Collections.singletonList(doubleTapSeq));
    }

    private void performSwipe(int startX, int startY, int endX, int endY) {
        PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
        Sequence swipe = new Sequence(finger, 0);
        swipe.addAction(finger.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), startX, startY));
        swipe.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
        swipe.addAction(finger.createPointerMove(Duration.ofMillis(600), PointerInput.Origin.viewport(), endX, endY));
        swipe.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
        driver.perform(Collections.singletonList(swipe));
    }

    private Point getCenter(WebElement element) {
        Point loc = element.getLocation();
        Dimension size = element.getSize();
        return new Point(loc.getX() + size.getWidth() / 2, loc.getY() + size.getHeight() / 2);
    } 

How to capture browser network logs

Create a Chrome devtool object 

protected static DevTools devTools;

 

Call below function in the setup method.

/**
     * To capture browser network logs
     */
    public void getBrowserNetworkLogs() {
        if (getBrowserName().equalsIgnoreCase("CHROME")) {

            // Create a session with DevTools
            devTools = ((ChromeDriver) driver).getDevTools();
            devTools.createSession();
            devTools.send(Network.clearBrowserCache());
            devTools.send(Network.setCacheDisabled(true));

            // Enable network tracking
            devTools.send(Network.enable(java.util.Optional.empty(), java.util.Optional.empty(),
                    java.util.Optional.empty(), java.util.Optional.empty(), java.util.Optional.empty()));
            // final RequestId[] requestIds = new RequestId[1];

            // Capturing request information of a network call
            /*
             * devTools.addListener(Network.requestWillBeSent(), request -> {
             * APP_LOGS.error("Request: " + request.getRequest().getUrl()); });
             */

            // Capturing response information of a network call
            devTools.addListener(Network.responseReceived(), response -> {
                RequestId requestId = response.getRequestId();

                if (response.getResponse().getStatus() != 200) {
                    String responseUrl = response.getResponse().getUrl();
                    if (responseUrl.contains("chubb") && !responseUrl.contains("favicon.ico")
                            && !responseUrl.contains("chubb-publico")) {
                        int responsStatus = response.getResponse().getStatus();
                        // String responseType = response.getType().toJson();
                        String statusText = response.getResponse().getStatusText();
                        String responseHeaders = response.getResponse().getRequestHeaders() != null
                                ? response.getResponse().getRequestHeaders().toString()
                                : "N/A";
                        String responseBody = devTools.send(Network.getResponseBody(requestId)).getBody();
                        String requestPostData = devTools.send(Network.getRequestPostData(requestId)).toString();

                        APP_LOGS.error("Response Url: " + responseUrl);
                        APP_LOGS.error("Response Status Code: " + responsStatus);
                        APP_LOGS.error("Response Text: " + statusText);
                        APP_LOGS.error("Response Headers: " + responseHeaders);
                        APP_LOGS.error("Response Body: " + responseBody);
                        APP_LOGS.error("Request Post Data: " + requestPostData);
                    }
                }
            });

        } else {
            APP_LOGS.info("Browser network log not captured for: " + getBrowserName());
        }
    }
 

 Close the dvetools connection in the tearDown methid.


        if (devTools != null) {
            devTools.send(Network.disable());
        }