Answer
cy.intercept() — Intercept and Mock API Calls
cy.intercept() watches, stubs, or modifies any HTTP request the browser makes — XHR and fetch alike.
Basic Syntax
JavaScript
cy.intercept(method, url, response)
Spy on a Request (No Mock — Just Watch)
JavaScript
// Just alias the real request — don''t mock it
cy.intercept('GET', '/api/users').as('getUsers')
cy.visit('/users')
cy.wait('@getUsers') // wait for the real API call to complete
// Then assert on the response
cy.wait('@getUsers').then((interception) => {
expect(interception.response.statusCode).to.equal(200)
expect(interception.response.body).to.have.length.greaterThan(0)
})
Stub a Response (Mock the API)
JavaScript
// Return fake data instead of hitting real API
cy.intercept('GET', '/api/users', {
statusCode: 200,
body: [
{ id: 1, name: 'Alice', role: 'QA' },
{ id: 2, name: 'Bob', role: 'Dev' },
],
}).as('getUsers')
cy.visit('/users')
cy.wait('@getUsers')
cy.get('[data-testid="user-row"]').should('have.length', 2)
cy.contains('Alice').should('be.visible')
Stub with a Fixture File
JavaScript
// Use a JSON fixture file as the response
cy.intercept('GET', '/api/products', { fixture: 'products.json' }).as('getProducts')
cy.visit('/products')
cy.wait('@getProducts')
cy.get('[data-testid="product-card"]').should('have.length.greaterThan', 0)
Stub an Error Response
JavaScript
// Test how your app handles 500 errors
cy.intercept('GET', '/api/users', {
statusCode: 500,
body: { message: 'Internal Server Error' },
}).as('failedRequest')
cy.visit('/users')
cy.wait('@failedRequest')
cy.get('[data-testid="error-banner"]').should('be.visible')
cy.get('[data-testid="error-banner"]').should('contain', 'Something went wrong')
Intercept by URL Pattern (Wildcards)
JavaScript
// Match any URL containing /api/users
cy.intercept('GET', '**/api/users**').as('getUsers')
// Match with glob pattern
cy.intercept('GET', '/api/users/*').as('getUserById')
// Match with regex
cy.intercept('GET', /\/api\/users\/\d+/).as('getUserById')
Modify Request Before It Goes Out
JavaScript
cy.intercept('POST', '/api/login', (req) => {
// Add a custom header
req.headers['x-custom-header'] = 'cypress-test'
// You can also modify body
req.body.extra = 'injected'
}).as('login')
Real Scenario: Login Flow with Intercept
JavaScript
it('should redirect to dashboard after successful login', () => {
cy.intercept('POST', '/api/auth/login', {
statusCode: 200,
body: { token: 'fake-jwt-token', user: { name: 'Alice' } },
}).as('loginRequest')
cy.visit('/login')
cy.get('#email').type('alice@test.com')
cy.get('#password').type('Password123')
cy.get('[data-testid="login-btn"]').click()
// Wait and verify the POST was made
cy.wait('@loginRequest').its('request.body').should('deep.equal', {
email: 'alice@test.com',
password: 'Password123',
})
cy.url().should('include', '/dashboard')
})
