CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-testcafe

Automated browser testing for the modern web development stack.

Pending
Overview
Eval results
Files

request-interception.mddocs/

Request Interception

TestCafe provides powerful HTTP request and response interception capabilities through request hooks, allowing you to monitor, log, and mock network traffic during test execution.

Capabilities

Request Logging

Monitor and log HTTP requests and responses for debugging and verification.

/**
 * Creates a request logger to monitor HTTP traffic
 * @param requestFilterRuleInit - Filter rule to specify which requests to log
 * @param logOptions - Configuration options for logging behavior
 * @returns RequestLogger instance for attaching to tests
 */
function RequestLogger(
    requestFilterRuleInit?: string | RegExp | object | Function,
    logOptions?: RequestLoggerOptions
): RequestLogger;

interface RequestLogger {
    /** Array of logged request objects */
    requests: LoggedRequest[];
    
    /** Number of requests that have been logged */
    count: number;
    
    /**
     * Checks if request matching criteria was logged
     * @param predicate - Function to test each logged request
     * @returns True if matching request exists
     */
    contains(predicate: (request: LoggedRequest) => boolean): boolean;
    
    /**
     * Clears all logged requests
     */
    clear(): void;
}

interface RequestLoggerOptions {
    /** Log request body content */
    logRequestBody?: boolean;
    
    /** Log response body content */
    logResponseBody?: boolean;
    
    /** Stringify request body */
    stringifyRequestBody?: boolean;
    
    /** Stringify response body */
    stringifyResponseBody?: boolean;
}

interface LoggedRequest {
    /** Request information */
    request: {
        url: string;
        method: string;
        headers: object;
        body?: string;
        isAjax: boolean;
    };
    
    /** Response information */
    response: {
        statusCode: number;
        statusText: string;
        headers: object;
        body?: string;
    };
}

Usage Examples:

import { RequestLogger } from 'testcafe';

const logger = RequestLogger();

fixture('Request Logging')
    .page('https://example.com')
    .requestHooks(logger);

test('Monitor API calls', async t => {
    await t.click('#load-data-button');
    
    // Wait for requests to complete
    await t.wait(2000);
    
    // Check logged requests
    await t.expect(logger.count).gte(1);
    
    // Find specific API call
    const apiCall = logger.requests.find(request => 
        request.request.url.includes('/api/data')
    );
    
    await t.expect(apiCall).ok();
    await t.expect(apiCall.response.statusCode).eql(200);
});

// Log only specific requests
const apiLogger = RequestLogger(/\/api\//, {
    logRequestBody: true,
    logResponseBody: true
});

test('Monitor specific API endpoints', async t => {
    await t.click('#submit-form');
    
    // Check API request was made
    const postRequest = apiLogger.requests.find(req => 
        req.request.method === 'POST' && 
        req.request.url.includes('/api/submit')
    );
    
    await t.expect(postRequest).ok();
    await t.expect(postRequest.request.body).contains('formData');
});

Request Mocking

Mock HTTP requests and responses to control application behavior during tests.

/**
 * Creates a request mock for intercepting and responding to HTTP requests
 * @returns RequestMock instance for configuring mock responses
 */
function RequestMock(): RequestMock;

interface RequestMock {
    /**
     * Configures mock to respond to requests matching the filter
     * @param requestFilterRuleInit - Filter rule to match requests
     * @param responseEventConfigurer - Response configuration
     * @returns RequestMock instance for chaining
     */
    onRequestTo(
        requestFilterRuleInit: string | RegExp | object | Function,
        responseEventConfigurer: ResponseEventConfigurer
    ): RequestMock;
}

interface ResponseEventConfigurer {
    /**
     * Responds with specified data and status
     * @param body - Response body content
     * @param statusCode - HTTP status code (default: 200)
     * @param headers - Response headers
     * @returns Response configuration
     */
    respond(body?: any, statusCode?: number, headers?: object): void;
    
    /**
     * Responds with data from file
     * @param filePath - Path to response file
     * @param statusCode - HTTP status code (default: 200)  
     * @param headers - Response headers
     * @returns Response configuration
     */
    respondWithFile(filePath: string, statusCode?: number, headers?: object): void;
}

Usage Examples:

import { RequestMock } from 'testcafe';

// Mock API responses
const mockAPI = RequestMock()
    .onRequestTo(/\/api\/users/)
    .respond([
        { id: 1, name: 'John Doe', email: 'john@example.com' },
        { id: 2, name: 'Jane Smith', email: 'jane@example.com' }
    ], 200, {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
    })
    .onRequestTo(/\/api\/error/)
    .respond({ error: 'Not found' }, 404);

fixture('Request Mocking')
    .page('https://example.com')
    .requestHooks(mockAPI);

test('Mock successful API response', async t => {
    await t.click('#load-users-button');
    
    // Verify mocked data is displayed
    await t.expect(Selector('.user-list .user-item').count).eql(2);
    await t.expect(Selector('.user-item').nth(0).innerText).contains('John Doe');
});

test('Mock error response', async t => {
    await t.click('#trigger-error-button');
    
    // Verify error handling
    await t.expect(Selector('.error-message').innerText).contains('Not found');
});

// Mock with file response
const fileMock = RequestMock()
    .onRequestTo(/\/api\/large-data/)
    .respondWithFile('./fixtures/large-response.json', 200, {
        'Content-Type': 'application/json'
    });

Custom Request Hooks

Create custom request hooks for advanced request/response processing.

/**
 * Base class for creating custom request hooks
 */
class RequestHook {
    /**
     * Creates custom request hook
     * @param requestFilterRuleInit - Filter rule to specify which requests to intercept
     */
    constructor(requestFilterRuleInit?: string | RegExp | object | Function);
    
    /**
     * Called when request is made (override in subclass)
     * @param event - Request event object
     * @returns Promise for async processing
     */
    onRequest(event: RequestEvent): Promise<void>;
    
    /**
     * Called when response is received (override in subclass)
     * @param event - Response event object
     * @returns Promise for async processing
     */
    onResponse(event: ResponseEvent): Promise<void>;
}

interface RequestEvent {
    /** Request information */
    request: {
        url: string;
        method: string;
        headers: object;
        body: string;
        isAjax: boolean;
    };
    
    /** Modify request headers */
    setHeaders(headers: object): void;
    
    /** Remove request header */
    removeHeader(name: string): void;
}

interface ResponseEvent {
    /** Request information */
    request: {
        url: string;
        method: string;
        headers: object;
        body: string;
        isAjax: boolean;
    };
    
    /** Response information */
    response: {
        statusCode: number;
        statusText: string;
        headers: object;
        body: string;
    };
    
    /** Modify response headers */
    setHeaders(headers: object): void;
    
    /** Remove response header */
    removeHeader(name: string): void;
}

Usage Examples:

import { RequestHook } from 'testcafe';

// Custom authentication hook
class AuthHook extends RequestHook {
    constructor() {
        super(/\/api\//);
    }
    
    async onRequest(event) {
        // Add authentication header to API requests
        event.setHeaders({
            'Authorization': 'Bearer test-token',
            'X-Test-Mode': 'true'
        });
    }
    
    async onResponse(event) {
        // Log API responses
        console.log(`API ${event.request.method} ${event.request.url}: ${event.response.statusCode}`);
    }
}

// Custom timing hook
class TimingHook extends RequestHook {
    constructor() {
        super();
        this.requestTimes = new Map();
    }
    
    async onRequest(event) {
        this.requestTimes.set(event.request.url, Date.now());
    }
    
    async onResponse(event) {
        const startTime = this.requestTimes.get(event.request.url);
        const duration = Date.now() - startTime;
        console.log(`Request to ${event.request.url} took ${duration}ms`);
    }
}

const authHook = new AuthHook();
const timingHook = new TimingHook();

fixture('Custom Request Hooks')
    .page('https://example.com')
    .requestHooks([authHook, timingHook]);

test('Custom request processing', async t => {
    await t.click('#api-call-button');
    
    // Requests will be processed by custom hooks
    await t.wait(1000);
});

Request Filtering

Define sophisticated filters for targeting specific requests.

// String URL filter
const stringFilter = 'https://api.example.com/users';

// RegExp URL filter  
const regexpFilter = /\/api\/.*\/data/;

// Object filter with multiple criteria
const objectFilter = {
    url: /\/api\//,
    method: 'POST',
    headers: {
        'content-type': /application\/json/
    }
};

// Function filter with custom logic
const functionFilter = (request) => {
    return request.url.includes('/api/') && 
           request.method === 'GET' &&
           request.headers['authorization'];
};

Usage Examples:

// Filter by URL pattern
const apiLogger = RequestLogger(/\/api\/v\d+\//);

// Filter POST requests to specific endpoint
const postLogger = RequestLogger({
    url: 'https://api.example.com/submit',
    method: 'POST'
});

// Filter by custom criteria
const customLogger = RequestLogger((request) => {
    return request.isAjax && 
           request.url.includes('/data') &&
           !request.url.includes('/cache');
});

// Filter by headers
const authLogger = RequestLogger({
    url: /\/api\//,
    headers: {
        'authorization': /Bearer .+/
    }
});

fixture('Request Filtering')
    .page('https://example.com')
    .requestHooks([apiLogger, postLogger, customLogger, authLogger]);

test('Filtered request monitoring', async t => {
    // Trigger various types of requests
    await t
        .click('#get-data-button')
        .click('#post-form-button')
        .click('#cached-request-button');
    
    // Check filtered results
    await t.expect(apiLogger.count).gte(1);
    await t.expect(postLogger.count).eql(1);
    await t.expect(customLogger.count).gte(1);
});

Request Hook Attachment

Attach request hooks to tests, fixtures, or globally.

// Fixture-level hooks
fixture('API Tests')
    .page('https://example.com')
    .requestHooks([logger, mock]);

// Test-level hooks  
test('Specific test with hooks', async t => {
    // Test implementation
}).requestHooks([specificLogger]);

// Multiple hooks
const hooks = [
    RequestLogger(/\/api\//),
    RequestMock().onRequestTo(/\/mock\//).respond({ success: true }),
    new CustomHook()
];

fixture('Multiple Hooks')
    .requestHooks(hooks);

Usage Examples:

const globalLogger = RequestLogger();
const apiMock = RequestMock()
    .onRequestTo(/\/api\/error/)
    .respond({ error: 'Mocked error' }, 500);

// Apply to entire fixture
fixture('Request Hook Attachment')
    .page('https://example.com')
    .requestHooks([globalLogger, apiMock]);

test('Test with fixture hooks', async t => {
    // Uses globalLogger and apiMock
    await t.click('#api-button');
});

// Test-specific additional hooks
const testLogger = RequestLogger(/\/specific-api\//);

test('Test with additional hooks', async t => {
    // Uses globalLogger, apiMock, and testLogger
    await t.click('#specific-api-button');
}).requestHooks([testLogger]);

// Conditional hook attachment
const conditionalHook = process.env.NODE_ENV === 'test' 
    ? RequestLogger() 
    : RequestMock().onRequestTo().respond();

fixture('Conditional Hooks')
    .requestHooks([conditionalHook]);

Install with Tessl CLI

npx tessl i tessl/npm-testcafe

docs

assertions.md

browser-automation.md

client-functions.md

element-selection.md

index.md

programmatic-api.md

request-interception.md

user-roles.md

tile.json