DEV Community

Cover image for TestFly Part 11: Network interception and API mocking in Selenium 4 with CDP
Hakan GÜL
Hakan GÜL

Posted on Originally published at hakangul.lovable.app

TestFly Part 11: Network interception and API mocking in Selenium 4 with CDP

Network mocking has long been treated as something only Playwright does. TestFly adds Chrome DevTools Protocol (CDP) interception and network throttling to Selenium 4 in Java. You can simulate offline mode, throttle the connection to slow 3G, stub third-party API responses and fail tests automatically on browser JavaScript errors, all without an external proxy server.

Why frontend tests need network interception

A single page application (SPA) talks to many backends: distributed microservices, third-party payment gateways, analytics trackers. In traditional Selenium tests this caused trouble:

  • To test an edge case such as a 500 Internal Server Error or a slow payment response, you had to change backend database state or configure a proxy server such as BrowserMob Proxy.
  • Slow third-party widgets and CDN outages made tests flaky.
  • JavaScript errors in the browser console went unnoticed unless an explicit assertion failed.

TestFly uses Selenium 4's native CDP bridge to intercept and modify HTTP traffic at the browser process level.

Simulating slow 3G and offline mode

Mobile-first web apps need to be tested on poor connections:

package io.testfly.examples.network;

import io.testfly.network.NetworkSpeed;
import io.testfly.test.BaseTest;
import org.testng.annotations.Test;

public class NetworkThrottlingTest extends BaseTest {

    @Test
    public void testOfflineBannerVisibility() {
        open("/dashboard");

        // 1. Emulate instant network disconnection
        network().emulateOffline();

        // 2. Perform action requiring network
        find("#sync-btn").click();

        // 3. Verify offline warning UI appears immediately
        assertThat(find("#offline-alert")).hasText("You are currently offline");

        // 4. Restore regular network speed
        network().resetThrottling();
    }

    @Test
    public void testSlow3GSpinnerState() {
        // Emulate realistic mobile latency: 2000ms latency, 400kbps download
        network().throttle(NetworkSpeed.SLOW_3G);

        open("/heavy-report");
        assertThat(find(".loading-spinner")).isVisible();
    }
}
Enter fullscreen mode Exit fullscreen mode

Mocking backend API responses (stubbing)

You can simulate server failures or return custom JSON without touching the backend environment:

@Test
public void testPaymentGateway500ErrorHandling() {
    // Intercept outgoing POST requests to payment service and return HTTP 500
    network().intercept(route -> route
        .matchingUrl("**/api/v1/charge")
        .respondWith(500, "{\"error\": \"Payment processor unavailable\"}")
    );

    open("/checkout");
    find("#pay-btn").click();

    // Verify graceful error message shown to user
    assertThat(find(".error-toast")).hasText("Payment processor unavailable, please try again.");
}
Enter fullscreen mode Exit fullscreen mode

Catching silent console errors

An uncaught JavaScript exception can break the page for users even when every DOM assertion passes. TestFly's ConsoleErrorCollector watches the browser logs:

```yaml title="testfly.yml"
browser:
captureConsoleErrors: true
failOnConsoleErrors: true # Fails the test if severe JS errors are detected




When a severe JavaScript error occurs (`Uncaught TypeError`, or a `404 Not Found` for a critical script), TestFly logs the stack trace and fails the test with diagnostic context you can act on.

## FAQ

### Does TestFly require a separate proxy server like BrowserMob?

No. TestFly talks to the browser engine over the Chrome DevTools Protocol (CDP) WebSocket, so there are no extra ports, proxies or certificates to set up.

### Does CDP network interception work with headless Chrome?

Yes. Headful and headless Chrome/Chromium both support CDP network interception in CI/CD environments.

### Can I mock response headers and status codes?

Yes. The fluent `respondWith()` builder lets you override headers (for example `Content-Type: application/json` or CORS headers) and return any HTTP status code.

---

*Originally published on [hakangul.lovable.app](https://hakangul.lovable.app/blog/testfly-part-11-selenium-cdp-network-interception-and-mocking).*
Enter fullscreen mode Exit fullscreen mode

Top comments (0)