A self-paced, hands-on workshop that teaches modern end-to-end testing with Cucumber + Playwright against a real, fully-functional reference app. You write features, step definitions, page objects, and fixtures — and watch a real browser drive a real full-stack app.
Target audience: developers new to E2E testing, or comfortable with Playwright but new to BDD and modern patterns like API-seeded data, storage state, and parallel isolation.
apps/api/— a NestJS REST API (users, projects, tasks, JWT auth) backed by SQLite via Prisma. Seeds itself with dev users on boot. Exposes an env-guarded/test/*seam for fast E2E fixture creation.apps/web/— a React + Vite + Tailwind app. Master-detail project management UI (projects list → detail with inline task CRUD, users list + detail, login/profile).apps/web-e2e/— the E2E project. Built withplaywright-bdd, which compiles Gherkin.featurefiles into Playwright tests. 49 scenarios, parallel-safe, finishes in ~20s.modules/— the workshop itself. 12 modules, each a focused README that walks you from empty E2E suite to full reference suite.docs/concepts.md— high-level reference of every pattern used in the suite, with links to where each pattern lives in the code.
# 1. Install Node 20 (matches .nvmrc)
nvm install 20 && nvm use 20
# 2. Install dependencies
npm ci
# 3. Install Playwright browsers (one-time)
npx playwright install chromium
# 4. Boot the api + web together
npm startOpen http://localhost:4200 and sign in:
| Password | Role | |
|---|---|---|
admin@example.com |
Admin123! |
admin |
alice@example.com |
Password1! |
member |
bob@example.com |
Password1! |
member |
Run the full E2E suite (auto-boots api + web if they aren't already):
npm run e2eOther common scripts (all pre-wired in package.json):
npm run e2e:smoke— quick sanity subsetnpm run e2e:auth/:projects/:tasks/:users— run a single feature areanpm run e2e:ui— open Playwright's interactive UI modenpm run e2e:headed— watch the tests drive a real visible browsernpm run e2e:report— open the HTML report from the last runnpm run e2e:flaky— reproduce the deliberate flake demo (Module 09)npm run db:reset— wipe + reseed the dev database
The workshop is 12 modules on linear main, delivered as tagged commits. Each module has a start tag (app in place, E2E scaffold missing the thing you're about to build) and a complete tag (canonical solution).
Typical participant flow, per module:
# Begin a module — checks out the start tag, creates my/03 working branch
npm run module:begin 03
# Read modules/03-fixtures-hooks-world/README.md, follow the walkthrough,
# do the Exercise at the end. Iterate:
npm run e2e -- --grep @module-03
# When it passes, compare your work to the canonical solution
npm run module:compare 03
# Broke it? Reset the branch and start over
npm run module:reset 03
# Current state
npm run module:statusThe module:* scripts are thin wrappers around git — you can do the same things by hand:
git checkout 03-start
git checkout -b my/03
# ... hack ...
git diff 03-complete -- apps/web-e2eSee docs/participant-workflow.md for the full git dance and recovery recipes.
| # | Module | What you build |
|---|---|---|
| 00 | Setup & app tour | Verify the environment, explore the app |
| 01 | First feature + step defs | login.feature — 2 scenarios, green |
| 02 | Page objects + locator strategy | LoginPage, BasePage, refactor steps to POM |
| 03 | Fixtures, hooks, world | scenarioWorld, seedUser fixture, cleanup |
| 04 | Tagging, outlines, data tables | @smoke, Scenario Outline, ` |
| 05 | Auth & storage state | storageState per role, login-once-per-worker |
| 06 | API + UI hybrid | Seed data via /test/seed/*, assert via UI |
| 07 | Network mocking | page.route stubs: slow, error, offline |
| 08 | Custom commands / step composition | Given I am logged in as {role} |
| 09 | Parallel, retries, flake | fullyParallel, --repeat-each, the @flaky demo |
| 10 | Debugging | UI mode, trace viewer, test.step(), page.pause() |
| 11 | Reporting | HTML report, cucumber JSON, optional Allure |
| 12 | Env config + capstone | .env/config, write a feature solo |
Total time: a focused pass through all 12 modules takes 6–10 hours. Do it over a couple of evenings or a weekend.
If you want the "why behind the patterns" without following the modules linearly:
→ docs/concepts.md — every pattern in the suite, with pointers to the actual files.
| Layer | Pick |
|---|---|
| Monorepo | Nx 22 |
| Node | 20 LTS (pinned via .nvmrc + engines) |
| API | NestJS 11 + Prisma 6 + SQLite + JWT + class-validator |
| Web | React 19 + Vite + Tailwind v4 + react-router |
| E2E | @playwright/test + playwright-bdd (compiles .feature → Playwright tests) |
| Browser | Chromium only (multi-browser matrix is out of scope for v1) |
| Platform | macOS + Linux first-class; Windows via WSL2 |
All decisions are documented in PLAN.md.
MIT. See LICENSE.