A Deep Dive into Requests Interception Using Playwright’s page.*
: Key Differences and Best Practices for Test Automation
Intercepting network requests is an essential feature in modern test automation, enabling testers to mock responses, validate outgoing requests, and simulate various network scenarios. Playwright, a powerful browser automation tool, offers a suite of features for request interception through its page.*
APIs. This article will explore all available options for request interception in Playwright, provide practical examples, and conclude with a comparison table summarizing their differences and best practices.
Why Intercept Network Requests?
Intercepting network requests during automated testing can help you:
- Mock API responses to isolate tests from backend changes or downtime.
- Test how the application handles slow or failed network calls.
- Validate outgoing requests and ensure adherence to API contracts.
- Control test data dynamically without modifying server behaviour.
Playwright provides several methods for achieving these goals. Let’s explore each.
1. page.route
The page.route
method allows you to define a handler for specific network requests. This handler can modify, fulfill, or abort requests based on custom logic.
Example Usage:
await page.route('**/api/data', route => {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ message: 'Mocked data' })
});
});
Features:
- Granular control: Match requests using glob patterns or regular expressions.
- Handlers: Use handlers to mock responses, abort requests, or pass through original requests.
Best Use Cases:
- Mocking API calls for frontend tests.
- Simulating edge cases, such as server errors or delays.
2. page.on('request')
and page.on('response')
Playwright’s event listeners provide insights into network activity by exposing request
and response
events. These methods are useful for validating request parameters and response content.
Example Usage:
page.on('request', request => {
console.log(`Request made: ${request.url()} - ${request.method()}`);
}); page.on('response', response => {
console.log(`Response received: ${response.url()} - ${response.status()}`);
});
Features:
- Real-time monitoring: Logs network activity during test execution.
- Validation: Verify outgoing requests and incoming responses.
Best Use Cases:
- Debugging network issues.
- Verifying API integration behaviour.
3. page.on('requestfailed')
The page.on('requestfailed')
event is triggered when a network request fails. This can be useful for debugging failed requests or testing how the application handles such scenarios.
Example Usage:
page.on('requestfailed', request => {
console.log(`Request failed: ${request.url()} - ${request.failure()?.errorText}`);
});
Features:
- Error tracking: Captures failure reasons such as DNS errors or connection timeouts.
- Debugging: Provides insights into why specific requests failed.
Best Use Cases:
- Testing how the application handles network failures.
- Debugging connectivity issues.
4. page.on('requestfinished')
The page.on('requestfinished')
event is triggered when a network request is completed. This can be used to validate the sequence and completion of network activity.
Example Usage:
page.on('requestfinished', request => {
console.log(`Request finished: ${request.url()} - ${request.method()}`);
});
Features:
- Completion tracking: Monitors when network requests have been completed.
- Validation: Ensures all expected requests are successfully processed.
Best Use Cases:
- Verifying that all expected network requests are completed.
- Tracking resource loading during page interactions.
5. page.waitForRequest()
The page.waitForRequest
method allows you to wait for a specific request to be made. This is particularly useful in scenarios where actions on the page trigger network requests.
Example Usage:
await page.click('button#submit');
const request = await page.waitForRequest('**/api/submit');
console.log(`Request made to: ${request.url()}`);
Features:
- Targeted waiting: Ensures specific requests are made before proceeding.
- Synchronization: Avoids flaky tests by waiting for network activity.
Best Use Cases:
- Synchronizing tests with network calls triggered by user interactions.
- Debugging dynamic behavior that depends on API requests.
6. page.route
with Conditional Handling
Using page.route
, you can implement conditional logic to handle different requests in unique ways. This is especially useful for applications with dynamic API behavior.
Example Usage:
await page.route('**/api/*', route => {
if (route.request().url().includes('/users')) {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ users: [] })
});
} else {
route.continue();
}
});
Features:
- Dynamic handling: Customize behavior for specific endpoints.
- Fallback options: Use
route.continue()
to pass unhandled requests through.
Best Use Cases:
- Mocking complex APIs with multiple endpoints.
- Combining mock responses with live requests.
7. context.route
While page.route
works at the page level, context.route
applies request interception rules to all pages within a browser context.
Example Usage:
await context.route('**/api/global', route => {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ globalData: true })
});
});
Features:
- Global scope: Automatically applies to all pages in the context.
- Convenience: Simplifies test setup for multi-page workflows.
Best Use Cases:
- Testing applications with multi-tab or multi-page functionality.
- Mocking shared API responses across multiple pages.
Comparison Table
Best Practices for Request Interception
- Use Glob Patterns Wisely: Avoid overly generic patterns like
**/*
, which may unintentionally match unintended requests. - Leverage
context.route
for Multi-Page Scenarios: Simplify setups by intercepting requests at the context level for workflows involving multiple tabs. - Combine Interception and Monitoring: Use
page.route
to mock or modify requests, andpage.on('response')
to validate the application’s behavior. - Synchronize with
page.waitForRequest
: Ensure actions triggering network requests are fully processed before proceeding. - Clean Up After Tests: Ensure all routes and event listeners are removed to avoid memory leaks and unpredictable behaviour in subsequent tests.
Conclusion
Playwright provides a comprehensive toolkit for intercepting and handling network requests. Whether you need to mock API responses, validate network activity, or simulate edge cases, its page.*
and context.*
APIs have you covered. By understanding their features, limitations, and best use cases, you can enhance your test automation framework and create robust, reliable tests.
Happy testing!