Today I had the pleasure of using Playwright to write some E2E tests.
What I really enjoyed, was how it allows you to extend the built-in test function.
This is super-useful to, for example, extract out repetitive setup and teardown logic.
Before
This is how I would approach writing test setup/teardown logic coming from a framework like Mocha or Jest:
users.spec.ts
import { test } from '@playwright/test'import { Db } from './Db'test.describe('Users', () => {let db: Dbtest.beforeEach(async () => {db = await Db.connect()await db.cleanup()})test.afterEach(async () => {await db.disconnect()})test('logs the user in', async ({ page }) => {await db.createUser()// ...})})
After
Using Playwright's test.extend
we can make this so much cleaner. Notice how I'm no longer importing test
from @playwright/test
here:
users.spec.ts
import { test } from './test-helpers/test'test.describe('Users', () => {test('logs the user in', async ({ db, page }) => {await db.createUser()// ...})})
Here's how:
test-helpers/test.ts
import { test as playwrightTest } from '@playwright/test'import { Db } from '../Db'interface TestParams {db: Db}export const test = base.extend<TestParams>({db: async ({}, use) => {// Previously in test.beforeEach:const db = await Db.connect()await db.cleanup()// Run the test:await use(db)// Previously in test.afterEach:await db.disconnect()},})