| name | write-e2e |
| description | Write a Playwright E2E test for a specified flow using the project's auth setup pattern |
| disable-model-invocation | true |
| argument-hint | [flow-description] |
Write a Playwright E2E test for: $ARGUMENTS
Read docs/TESTING_STRATEGY.md Phase 4 before writing.
Auth — critical
Auth is established ONCE by tests/e2e/auth.setup.ts. Individual tests do NOT perform login.
The storageState: 'playwright/.auth/user.json' is set globally in playwright.config.ts — do NOT add test.use({ storageState }) in your test file unless you need a DIFFERENT auth state.
import { test, expect } from '@playwright/test'
test.describe('$ARGUMENTS', () => {
test('happy path', async ({ page }) => {
await page.goto('/dashboard')
})
})
Unauthenticated test (exception):
test('unauthenticated user redirects to login', async ({ page, context }) => {
await context.clearCookies()
await page.goto('/dashboard')
await expect(page).toHaveURL('/login')
})
File location
All E2E tests live in tests/e2e/. Name the file after the flow:
- Upload flow →
invoices-upload.spec.ts
- Auth guard →
auth-guard.spec.ts
Playwright patterns
await expect(page).toHaveURL('/dashboard')
await expect(page.getByRole('heading', { name: 'Invoices' })).toBeVisible()
await page.locator('input[type="file"]').setInputFiles({
name: 'test.pdf',
mimeType: 'application/pdf',
buffer: Buffer.from('%PDF-1.4 test'),
})
await page.route('**/api/invoices', route => route.abort('failed'))
Multi-user isolation
When testing that user A cannot access user B's data, use a SEPARATE browser context for user B:
test('cannot access another user\'s invoice', async ({ page, context }) => {
const secondCtx = await context.browser()!.newContext()
const secondPage = await secondCtx.newPage()
await secondCtx.close()
})
Env vars
process.env['TEST_USER_EMAIL']
process.env['TEST_USER_PASSWORD']
process.env['TEST_BASE_URL']
Coverage targets
- Happy path (core flow with authenticated test user)
- Error handling (use
page.route() to simulate server errors)
- Auth guard (unauthenticated access → redirect)
- Ownership (if applicable — user A cannot see user B's resource)
After writing
npx playwright test --project=setup
npx playwright test tests/e2e/<your-file>.spec.ts --project=chromium