Quick Tutorial: Playwright Mock API

Published on May 28, 2024

Mock APIs | Playwright

Getting started

Let’s run a quick example of mocking data from an API with Playwright. Imagine we want to run some UI tests or visual regression, but we don’t want a dependency on the API’s being called. We will be testing the UI aspect in isolation, by intercepting the API request.

This is the API we are calling and below is what the data looks like on the page:

API: https://demo.playwright.dev/api-mocking

We have created the test file below, the page.route is the API path we are intercepting. The json is the data we will be mocking from the API. And route.fulfill is fulfilling the routes request with our custom response data.

import { test, expect } from '@playwright/test';

test("mocks a fruit and doesn't call api", async ({ page }) => {
// Mock the api call before navigating
await page.route('*/**/api/v1/fruits', async route => {
const json = [
{ name: 'Orange', id: 1 },
{ name: 'Apple', id: 2 },
{ name: 'Mango', id: 3 }
];
await route.fulfill({ json });
});
// Go to the page
await page.goto('https://demo.playwright.dev/api-mocking');
await page.pause()

// Assert that the Strawberry fruit is visible
await expect(page.getByText('Strawberry')).toBeVisible();
});

I added an await page.pause() to the test so we can inspect the request and see what is happening. As you can see only 3 items are being displayed, as the original API was not called and the data has been mocked successfully.

Why is this useful?

As we mentioned at the start, we have completely removed our dependency on the API. We have a consistent mock data set, which we know will be returned every time we execute our test — so we can focus our assertions on the UI aspects of our website, how it displays, renders and looks visually. This decoupling of client and API is important, as its also likely they are developed as separate projects. (integration between both is also important, but can be a separate suite of tests)