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.

php
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

php
$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:

php
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

← All recipes