Follow setup, use and cleanup
In the example, setup happens before await use(page). The test then receives that page as checkout. Code after use can perform cleanup. Here the built-in page and context fixtures handle browser-state cleanup; the custom fixture creates no external records.
Choose what belongs in setup
The prepared customer is useful for the successful-order scenario. It would be the wrong starting state for a missing-customer scenario unless that test explicitly cleared the field. Keep shared setup small enough that the initial state remains obvious to the reader.
Keep scenarios independent
Test-scoped fixtures are set up for each test that needs them; worker-scoped fixtures have a wider lifetime. The example uses test scope and includes a second scenario checking quantity one and no confirmation. Browser isolation does not automatically remove records created in a shared database.
Interview question: fixture or page object?
A fixture manages a dependency's lifecycle. A page object groups interactions behind a reusable interface. They can work together: a fixture could construct a page object and supply it to the test. This small demo uses Page directly because it has only a few controls.
Read the checkout example
This is the same test file provided by the linked lab. Follow the lab for installation, configuration and expected results.
import { test as base, expect, type Page } from '@playwright/test';
const test = base.extend<{ checkout: Page }>({
checkout: async ({ page }, use) => {
await page.goto('/labs/checkout.html');
await page.getByLabel('Demo customer').fill('Demo Learner');
await use(page);
// The built-in page/context fixtures provide browser-state cleanup.
},
});
test('prepared customer can place an order', async ({ checkout }) => {
await checkout.getByRole('button', { name: 'Place demo order' }).click();
await expect(checkout.getByRole('status')).toHaveText('Demo order confirmed: INR 100');
});
test('another test starts with quantity one', async ({ checkout }) => {
await expect(checkout.getByLabel('Quantity', { exact: true })).toHaveValue('1');
await expect(checkout.getByRole('status')).toBeEmpty();
});
Run this example in the practical lab →Official references
Use these sources for current API behaviour and setup requirements. SPOTHUB is an independent training provider.
