E2E Testing Guide (Playwright)
End-to-end tests verify real user flows in a browser. We use Playwright — it launches Chromium, navigates pages, clicks buttons, and asserts results.
Prerequisites
- Docker services running —
make up(API, DB, Worker) - Books in the database — at least one EN book with chapters (global setup auto-discovers them)
- Node deps installed —
pnpm installin repo root
Web dev server starts automatically via Playwright config (
reuseExistingServer: truelocally).
Quick Start
# Install Playwright browsers (first time only)pnpm exec playwright install chromium
# Run all E2E tests headlesspnpm -C apps/web test:e2e
# Run in UI mode (interactive, recommended for QA)pnpm -C apps/web test:e2e:uiUI Mode (Recommended for QA)
Launch:
pnpm -C apps/web test:e2e:uiWhat you see
- Left sidebar — test files and individual tests
- Right panel — browser rendering + action log
- Bottom — console output, errors, trace
How to use
| Action | How |
|---|---|
| Run all tests | Click “Run all” button (top) |
| Run single test | Click the play icon next to a test name |
| Filter by file | Click a file in the sidebar to show only its tests |
| Filter by project | Use the project dropdown (chromium / mobile) |
| Watch mode | Toggle the eye icon — tests auto-rerun on file change |
| Re-run failed | Click the red test → “Retry” |
Reading failures
When a test fails:
- Error message — shown inline, describes what assertion failed
- Screenshot — captured on failure, visible in the attachments tab
- Trace — click “Trace” to open Playwright Trace Viewer (timeline of every action, network request, DOM snapshot)
Headless Mode
# All testspnpm -C apps/web test:e2e
# Single filepnpm -C apps/web test:e2e -- e2e/tests/smoke.spec.ts
# Single test by namepnpm -C apps/web test:e2e -- -g "loads homepage"
# Specific project onlypnpm -C apps/web test:e2e -- --project=chromiumpnpm -C apps/web test:e2e -- --project=mobileViewing Reports
After a headless run, Playwright generates an HTML report:
pnpm exec playwright show-report apps/web/e2e/playwright-reportThe report shows pass/fail per test, duration, and links to traces and screenshots for failures.
Trace Viewer
Traces are captured on first retry. Open a trace:
pnpm exec playwright show-trace apps/web/e2e/test-results/<test-folder>/trace.zipShows: timeline of actions, DOM snapshots before/after each step, network requests, console logs.
Test Structure
apps/web/e2e/├── playwright.config.ts # Config, projects, webServer├── global-setup.ts # Auth + test data discovery├── global-teardown.ts # Cleanup├── fixtures/│ ├── auth.fixture.ts # Auth fixture (logged-in context)│ └── test-data.ts # Test data helpers├── helpers/│ ├── api.ts # API login helpers│ └── reader.ts # waitForReaderLoad└── tests/ # 10 specs (2026-10-15) ├── smoke.spec.ts # @smoke gate: pages render, API health ├── reader-smoke.spec.ts # @reader-smoke gate: position, Next/Prev, highlights, TOC, auto-add to library ├── reader-pdf.spec.ts # @reader-pdf gate: Original-layout PDF ├── auth.spec.ts # Login, user session ├── search.spec.ts # Search query → results ├── bookmarks.spec.ts # Add/remove bookmark round trip to the server ├── reader-mobile.spec.ts # Mobile reader smoke (iPhone viewport) ├── guest-landing.spec.ts # No POST /auth/guest on landing pages ├── vocabulary.spec.ts # SRS word list + review └── delete-account.spec.ts # Account deletionProjects
| Project | Viewport | Runs tests matching |
|---|---|---|
chromium |
Desktop Chrome | All except *mobile* |
mobile |
iPhone 13 (Chromium) | Only *mobile* |
There is no admin project and no admin spec any more.
Troubleshooting
| Problem | Fix |
|---|---|
ERR_CONNECTION_REFUSED |
Services not running. Run make up and wait for API to be healthy. |
.test-data.json not found or empty |
Global setup failed. Check API is reachable at localhost:8080 and has books. |
| Auth failures | Ensure ENABLE_TEST_AUTH=true in .env or API is in dev mode. |
| Stale test data | Delete apps/web/e2e/.test-data.json and apps/web/e2e/.auth/, then re-run. |
| Browser not installed | pnpm exec playwright install chromium |
| Tests timeout | Increase timeout in config or check if web server started (look at terminal output). |