e2e-testing
E2E Testing
Playwright Test against the real application — real server, real browser, real data.
Conventions
- Tests live in
e2e/at the project root, NOT co-located with source - Authenticated tests:
e2e/flow-name.spec.ts— run with saved session automatically - Unauthenticated tests:
e2e/flow-name.unauth.spec.ts— fresh browser, no session - Run with
bun run e2e - Test data lives in
e2e/seeds/as JSON files - Import
testfrom./utils(shared fixture),expectfrom@playwright/test
import { expect } from "@playwright/test";
import { test } from "./utils";
The shared test fixture waits for [data-hydrated] after every page.goto() — buttons and handlers are ready immediately.
Playwright API
| API | Use |
|---|---|
page.goto("/path") |
Navigate to URL |
page.getByRole("button", { name }) |
Query by ARIA role |
page.getByText("text") |
Query by text content |
page.getByLabel("label") |
Query by form label |
locator.click() |
Click interaction |
locator.fill("value") |
Type into input |
expect(page).toHaveURL(pattern) |
Assert current URL |
expect(locator).toBeVisible() |
Assert element visible |
page.waitForURL(pattern) |
Wait for navigation |
page.context().storageState() |
Save auth state |
E2E vs Component Test
| Scenario | Test type |
|---|---|
| Multi-step user flow across pages | E2E |
| Authentication and authorization | E2E |
| CRUD lifecycle | E2E |
| API integration across pages | E2E |
| Isolated UI component behavior | Component |
| Form validation feedback | Component |
| Component state management | Component |
Rule of thumb: involves chained steps across the real app → E2E. Tests isolated UI behavior → component test.
Examples
See examples/ for complete test examples by pattern:
| Example | When to use |
|---|---|
examples/navigation.md |
Page transitions, link clicks, URL assertions |
examples/form-submission.md |
Form fills, submissions, validation |
examples/crud-flow.md |
Create, edit, delete lifecycle |
examples/auth-persistence.md |
Login setup, session reuse, unauthenticated tests |
Acceptance Checklist
- Test lives in
e2e/directory - Uses correct extension:
.spec.ts(authenticated) or.unauth.spec.ts(unauthenticated) - Imports
testfrom./utils,expectfrom@playwright/test - Tests a real user flow, not isolated component behavior
- Uses seed data from
e2e/seeds/when needed - No manual hydration waits (fixture handles it)
- Tests behavior, not implementation details
More from kvnwolf/devtools
commit
Wraps up work by syncing documentation, committing, pushing, and opening a pull request. Use when committing code, finishing a task, pushing changes, or creating a PR.
10base
Scaffolds a new TypeScript project from scratch. Use when starting a new project, bootstrapping a codebase, or setting up a project from zero.
10unit-testing
Writes unit tests following behavior-driven conventions with vitest. Use when creating tests, adding test coverage, or writing regression tests.
9convex
Provides instructions for working with Convex backend projects. Use when setting up Convex, creating queries/mutations/actions, consuming Convex data from React, defining tables, testing Convex functions, configuring environment variables, or prefetching data in route loaders.
7tanstack-start
Provides instructions for working with TanStack Start projects. Use when setting up, configuring, developing, creating routes, or creating server functions in a TanStack Start application.
5create-skill
Creates or modifies agent skills, including single-workflow and multi-workflow (orchestrator) skills. Use when the user wants to create, write, author, scaffold, edit, update, fix, or refactor a skill, or migrate a skill from single to multi-workflow.
5