How to Intercept and Stub Network Traffic in Cypress

This article explains how Cypress manages HTTP requests during automated testing using its powerful network-handling API. You will learn the mechanics behind the cy.intercept() command, how to observe real network traffic without altering it, how to stub responses with mock data, and how to simulate edge cases like server errors and network delays.

The Role of cy.intercept()

Cypress intercepts and controls HTTP requests at the network layer using the cy.intercept() method. This command matches incoming HTTP requests initiated by your web application based on method, URL pattern, headers, or query parameters. Once matched, Cypress can either allow the request to pass through to the live server (spying) or replace the server response entirely with custom data (stubbing).

Spying on Network Traffic

Spying allows tests to monitor real network calls without altering the response data. This is useful for verifying that an application sends the correct payload or waiting for a specific asynchronous request to complete before running assertions.

To spy on a request: 1. Define the intercept matcher using cy.intercept(). 2. Assign an alias using .as(). 3. Wait for the request using cy.wait().

// Intercept GET requests to /api/users
cy.intercept('GET', '/api/users').as('getUsers');

// Trigger the action in the UI
cy.get('[data-testid="load-users-btn"]').click();

// Wait for the network request to finish and assert on the payload
cy.wait('@getUsers').then((interception) => {
  expect(interception.response.statusCode).to.eq(200);
  expect(interception.response.body).to.have.length(5);
});

Stubbing Network Responses

Stubbing isolates the frontend from backend dependencies by providing predefined responses. This eliminates network latency, prevents test flakiness caused by unstable APIs, and allows testing states that are difficult to reproduce against a live backend.

You can supply static data directly in the intercept definition:

cy.intercept('GET', '/api/users', {
  statusCode: 200,
  body: [
    { id: 1, name: 'Alex Johnson' },
    { id: 2, name: 'Maria Garcia' }
  ]
}).as('getMockUsers');

cy.visit('/dashboard');
cy.wait('@getMockUsers');
cy.get('.user-list-item').should('have.length', 2);

Using Fixtures for Response Data

For larger payloads, Cypress allows storing mock data in the cypress/fixtures directory and loading it directly into the stub:

cy.intercept('GET', '/api/products', { fixture: 'products.json' }).as('getProducts');

Simulating Network Conditions and Errors

Cypress can simulate negative test cases, such as server failures or slow connections, to verify that the UI handles failures gracefully.

Simulating HTTP Errors

cy.intercept('POST', '/api/checkout', {
  statusCode: 500,
  body: { error: 'Internal Server Error' }
}).as('failedCheckout');

cy.get('#submit-order').click();
cy.wait('@failedCheckout');
cy.get('.error-notification').should('contain', 'Unable to process your order.');

Simulating Network Delay

cy.intercept('GET', '/api/data', (req) => {
  req.on('response', (res) => {
    res.setDelay(2000); // Delays response by 2 seconds
  });
}).as('delayedData');

Modifying Requests Dynamically

The cy.intercept() command supports route handler functions that dynamically inspect and modify outgoing requests before they reach the server, or alter incoming responses before the browser receives them:

cy.intercept('POST', '/api/login', (req) => {
  // Modify the outgoing request header
  req.headers['x-custom-token'] = 'test-token-123';

  // Continue to the server and modify the response dynamically
  req.continue((res) => {
    res.body.role = 'administrator';
  });
});

By leveraging cy.intercept(), developers can create deterministic, fast, and resilient test suites that thoroughly validate both standard behavior and complex network failure scenarios.