Mock an API response
Serve a fixed JSON payload for an endpoint so you can reach a rare or fragile UI state.
Force an endpoint to return exactly the data you want. Mocking makes an empty list, an error state, or a specific record reachable without a real backend fixture.
Fulfill the route with JSON
Register a route on the page. The handler receives a RouteInterface and answers with a status, content type, and body.
use function Playwright\Testing\expect;
use Playwright\Network\RouteInterface;
$page->route('**/api/orders', static function (RouteInterface $route): void {
$route->fulfill([
'status' => 200,
'contentType' => 'application/json',
'body' => json_encode([
['id' => 1001, 'status' => 'paid'],
['id' => 1002, 'status' => 'pending'],
]),
]);
});
$page->goto('https://app.example.test/orders');
expect($page->getByRole('row'))->toHaveCount(2);
expect($page->getByText('pending'))->toBeVisible();
Register the route before you navigate
$page->goto('https://app.example.test/orders'); // page requests /api/orders here
$page->route('**/api/orders', $handler); // too late: the request already went out
A route registered after goto() can miss the request. Set up every route first, then navigate. The glob pattern matches the endpoint on any host, so keep it as narrow as the URL allows.
Mock an error state
Change the status and body to exercise the failure path the real backend rarely produces:
use Playwright\Network\RouteInterface;
$page->route('**/api/orders', static function (RouteInterface $route): void {
$route->fulfill([
'status' => 500,
'contentType' => 'application/json',
'body' => json_encode(['error' => 'internal']),
]);
});
$page->goto('https://app.example.test/orders');
expect($page->getByRole('alert'))->toBeVisible();
Expected result
The page renders the state produced by the mocked response: two rows for the success payload, or an alert for the error payload. The test should still assert visible UI, not only that the route handler ran.
Go next
- Network and API testing: the full interception model
- Block unwanted requests: abort instead of fulfill