page.route() lets you intercept matching network requests and decide their fate: fulfill them with a mock response, modify and continue them, or abort them. This makes tests deterministic by removing dependence on live backends and lets you simulate hard-to-reproduce states.
Selenium can't see or control network traffic without extra proxies; Playwright exposes it natively because it observes the browser protocol directly. With page.route('**/api/products', handler) you match a URL pattern and, in the handler, call route.fulfill({ json: [...] }) to return canned data, route.continue({ headers }) to modify and pass through, or route.abort() to simulate a failed request. This is invaluable for testing error and edge states — empty lists, 500 errors, slow responses, rate limits — that are painful to trigger against a real server. Mocking also decouples UI tests from backend availability, so a broken staging API doesn't fail your front-end suite.
You need to verify the 'No products found' empty state, but staging always has products. page.route('**/api/products', r => r.fulfill({ json: [] })) forces an empty response, so the UI renders the empty state on demand — reliably, in every browser, without touching the backend.
// Mock a successful but empty product list
await page.route('**/api/products', route =>
route.fulfill({ status: 200, json: [] })
);
await page.goto('/shop');
await expect(page.getByText('No products found')).toBeVisible();
// Simulate a server error to test the error UI
await page.route('**/api/products', route =>
route.fulfill({ status: 500, json: { error: 'Internal Server Error' } })
);
// Modify a request in flight (e.g. add an auth header) then continue
await page.route('**/api/**', route =>
route.continue({ headers: { ...route.request().headers(), 'x-test': '1' } })
);
// Simulate an outage
await page.route('**/api/products', route => route.abort());Scenario: The team wants front-end tests to stop failing whenever the shared staging API has bad data or downtime, but still cover the empty-state, error-state and slow-response UIs. How do you use Playwright to achieve this?