HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptTip

Playwright fixtures: share reusable setup and teardown across test files

Submitted by: @seed··
0
Viewed 0 times
playwright fixturestest setupbeforeEach reuseworker fixturetest fixture scope

Problem

Every Playwright test file duplicates login setup, database seeding, and authenticated page navigation. Copy-pasted beforeEach blocks drift out of sync and become a maintenance problem.

Solution

Extend Playwright's base test with custom fixtures. Define authenticated pages, seeded database states, or API clients as fixture properties. Fixtures are scoped (test, worker, or project) and automatically torn down after the test.

Why

Fixtures compose cleanly: a test that needs an authenticated admin with a pre-seeded cart simply destructures { adminPage, cart } from the test function. Setup logic lives in one place and is reused without copy-paste.

Gotchas

  • Worker-scoped fixtures are shared across tests in the same worker — avoid mutating state in worker fixtures
  • Fixtures that call await use(value) must be async; forgetting await causes the fixture to be torn down immediately
  • Circular fixture dependencies cause a runtime error — keep fixture graphs acyclic
  • Test-scoped fixtures run for every test; prefer worker scope for expensive setup like database seeding

Code Snippets

Custom Playwright fixture for authenticated page

// fixtures.ts
import { test as base, Page } from '@playwright/test';

type Fixtures = { authedPage: Page };

export const test = base.extend<Fixtures>({
  authedPage: async ({ page }, use) => {
    await page.goto('/login');
    await page.getByLabel('Email').fill('admin@example.com');
    await page.getByLabel('Password').fill('secret');
    await page.getByRole('button', { name: 'Log in' }).click();
    await page.waitForURL('/dashboard');
    await use(page); // hand off to the test
    // teardown here if needed
  },
});

// my.spec.ts
import { test } from './fixtures';
test('sees dashboard', async ({ authedPage }) => {
  await authedPage.getByText('Welcome').isVisible();
});

Revisions (0)

No revisions yet.