When working with end-to-end testing frameworks like Playwright, mocking GraphQL requests can significantly improve test reliability and speed. Inspired by Jay Freestone's excellent blog post, Stubbing GraphQL Requests in Playwright, I decided to build a reusable utility function that allows for flexible GraphQL request interception and response stubbing.
In this post, I’ll walk you through my implementation of the interceptGQL utility and demonstrate how it can be used with Playwright to mock server responses for GraphQL queries and mutations.
The interceptGQL utility registers a route handler for all GraphQL requests to your backend, intercepting specific operations based on their operationName. You can define how each operation should respond and validate the variables passed in the request.
Here’s the implementation:
import { test as baseTest, Page, Route } from '@playwright/test'; import { namedOperations } from '../../src/graphql/autogenerate/operations'; type CalledWith = Record<string, unknown>; type Operations = keyof (typeof namedOperations)['Query'] | keyof (typeof namedOperations)['Mutation']; type InterceptConfig = { operationName: Operations | string; res: Record<string, unknown>; }; type InterceptedPayloads = { [operationName: string]: CalledWith[]; }; export async function interceptGQL( page: Page, interceptConfigs: InterceptConfig[] ): Promise<{ reqs: InterceptedPayloads }> { const reqs: InterceptedPayloads = {}; interceptConfigs.forEach(config => { reqs[config.operationName] = []; }); await page.route('**/graphql', (route: Route) => { const req = route.request().postDataJSON(); const operationConfig = interceptConfigs.find(config => config.operationName === req.operationName); if (!operationConfig) { return route.continue(); } reqs[req.operationName].push(req.variables); return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: operationConfig.res }), }); }); return { reqs }; } export const test = baseTest.extend<{ interceptGQL: typeof interceptGQL }>({ interceptGQL: async ({ browser }, use) => { await use(interceptGQL); }, });
To demonstrate the utility in action, let’s use it to test a Task Management Dashboard. We'll intercept a GraphQL query (GetTasks) and mock its response.
import { expect } from '@playwright/test'; import { namedOperations } from '../../../src/graphql/autogenerate/operations'; import { test } from '../../fixtures'; import { GetTasksMock } from './mocks/GetTasks.mock'; test.describe('Task Management Dashboard', () => { test.beforeEach(async ({ page, interceptGQL }) => { await page.goto('/tasks'); await interceptGQL(page, [ { operationName: namedOperations.Query['GetTasks'], res: GetTasksMock, }, ]); }); test('Should render a list of tasks', async ({ page }) => { const taskDashboardTitle = page.getByTestId('task-dashboard-title'); await expect(taskDashboardTitle).toHaveText('Task Dashboard'); const firstTaskTitle = page.getByTestId('0-task-title'); await expect(firstTaskTitle).toHaveText('Implement authentication flow'); const firstTaskStatus = page.getByTestId('0-task-status'); await expect(firstTaskStatus).toHaveText('In Progress'); }); test('Should navigate to task details page when a task is clicked', async ({ page }) => { await page.getByTestId('0-task-title').click(); await expect(page.getByTestId('task-details-header')).toHaveText('Task Details'); await expect(page.getByTestId('task-details-title')).toHaveText('Implement authentication flow'); }); });
This implementation and approach were inspired by Jay Freestone's excellent blog post, Stubbing GraphQL Requests in Playwright. His post provided a solid foundation for building the interceptGQL utility.
By incorporating this utility into your Playwright test suite, you can mock GraphQL queries and mutations with ease, improving test speed and reliability while simplifying complex scenarios.
The above is the detailed content of Playwright: GraphQL Requests in A Utility for Efficient Testing. For more information, please follow other related articles on the PHP Chinese website!