# End-to-end tests Playwright suites, most local-only — three run in CI/CD: | Suite | Target | Where it runs | | ----------------- | --------------------------------- | --------------------------------------------------------------------------- | | `smoke.spec.ts` | any deployed stage | CD pipeline against `https://test.dorfteich.cloud` after every deploy | | `auth.spec.ts` | full local stack **with Mailpit** | CI job `auth-e2e` on every PR/push; locally against the dev stack | | `content.spec.ts` | full local stack | same CI job `auth-e2e` (a second step), right after the auth pack | | everything else | full local stack | locally only — `editor`/`sidebar`/`image`/`link`/`markdown`/`trash`.spec.ts | `content.spec.ts` is the M2 content regression pack (issue #32): page lifecycle, editor basics, image paste, Markdown round-trip, and trash — enough to catch a regression across the whole content model without re-running every edge case the feature-specific packs above already cover. Its Markdown round-trip test is a real regression pin, not just a smoke check: it compares the seeded "Every Element" fixture page's exported Markdown byte-for-byte against the checked-in `content-page.md` (see "Content fixtures" below) — any schema/serializer change that alters how a node round-trips fails it, once the seed has re-run against the changed code (build → migrate → seed → test, exactly CI's order). ## Running locally ```sh # 1. Stack: database + Mailpit, api (3001), web dev server (5173) docker compose -f deploy/compose/docker-compose.yml -f deploy/compose/compose.dev.yml up -d db mailpit DATABASE_URL=postgresql://dorfteich:dorfteich@localhost:5434/dorfteich pnpm --filter @dorfteich/api db:seed DATABASE_URL=postgresql://dorfteich:dorfteich@localhost:5434/dorfteich PORT=3001 pnpm --filter @dorfteich/api start:dev & pnpm --filter @dorfteich/web dev & # 2. Tests E2E_BASE_URL=http://localhost:5173 E2E_MAILPIT_URL=http://localhost:8025 pnpm --filter @dorfteich/web e2e ``` `auth.spec.ts` skips itself when `E2E_MAILPIT_URL` is unset, so the CD smoke run never trips over it. ## Fixture matrix Seeded by `pnpm --filter @dorfteich/api db:seed` (idempotent — re-running never duplicates). Shared password: `fixture passwort 123`. Fixtures exist only on dev machines and disposable CI/Test databases. | Username | State | Purpose | | ----------------- | ------------------- | ---------------------------------------------------------------------------------------- | | `fixture-admin` | active, Site Admin | admin UI/permissions cases | | `fixture-user` | active | regular journeys, settings, sessions | | `fixture-editor` | active | second regular account for the collab-permissions pack (reader/editor of another's pond) | | `fixture-pending` | e-mail not verified | unverified-login cases | ## Content fixtures `db:seed` also creates a **shared** pond `content-fixtures` (owned by `fixture-user`) with two pages, for the content regression pack and manual QA: - **Every Element** (`every-element`) — every editor schema node and mark (issue #24: headings 1–4, all list types, table, blockquote, code block, horizontal rule, hard break, and all five marks). Loaded from the checked-in `apps/api/prisma/fixtures/content-page.yjs`, a Yjs snapshot generated from the human-readable `content-page.md` next to it — `content-page.md` is the thing to read or edit; the `.yjs` file is a build artifact of it, not source. - **Fixture Image** (`fixture-image`) — one real, servable uploaded image (the placeholder `fileId` inside the Markdown fixture above is not a real attachment; this page's image is). Regenerating after editing `content-page.md`: ```sh pnpm --filter @dorfteich/api fixtures:regenerate ``` This is deterministic — re-running without editing the Markdown produces a byte-identical `.yjs` file (the script pins the Yjs document's `clientID`, which is otherwise randomized per `Y.Doc` instance) — and it refuses to write a snapshot that isn't a fixed point of the Markdown round-trip (`docToMarkdown(markdownToDoc(x)) === x`), so a stale fixture can't get checked in silently. ## Conventions - New feature packs get their own `.spec.ts` next to these and extend the fixture matrix here (permission matrix arrives with M5, issue #60). - Use `contextForUser()` from `helpers.ts` for signed-in tests — it logs in through the api and hands you a browser context with the session cookie, no UI login repetition. - Flaky tests are defects (ADR 0014): fix or quarantine immediately.