dorfteich/apps/web/e2e
Claude Opus 4.8 19fb24c527
All checks were successful
CD / Build and push images (push) Successful in 3m24s
CI / Lint, typecheck, test (push) Successful in 2m16s
CI / Auth e2e pack (push) Successful in 2m52s
CI / Build container images (push) Has been skipped
CD / Deploy to Test (push) Successful in 8s
CD / Smoke tests against Test (push) Successful in 1m14s
CD / Promote to Int (push) Successful in 11s
Add search UI with scoping and snippets (#50)
A search palette over the #49 full-text search.

- web:
  - `SearchPalette`: opened from a top-bar button or the global "/" shortcut
    (ignored while typing in a field). Scoped to the current pond by default
    with an "all my ponds" toggle and, when scoped, a label filter. Results
    list title, pond, label chips, and a highlighted snippet; recent searches
    (localStorage) show before typing; empty/error/hint states.
  - `HighlightedSnippet` renders the match — the api wraps hits in shared
    sentinels (private-use codepoints), split here into `<mark>` so no HTML
    from the content is interpreted.
  - Fully keyboard-operable: "/" opens, ↑/↓ move, Enter opens the page,
    Esc closes.
  - i18n `search` namespace (de + en); palette + result styles.
- api: a pondId scope test proves search narrows to one pond.
- e2e `search.spec.ts` (new CI pack): body content added via the editor is
  found and highlighted, the scope toggle keeps the result, and Enter opens
  the page.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PGdhRiwU1WRL4XxJfZYipY
2026-07-09 13:36:06 +02:00
..
auth.spec.ts Bind the CI dev server to all interfaces and surface login errors 2026-07-05 06:07:49 +02:00
backlinks.spec.ts Add backlinks panel and phantom-pages view (#48) 2026-07-09 13:05:32 +02:00
collab.spec.ts Add remote cursors and a presence strip (#37) 2026-07-08 18:22:41 +02:00
content.spec.ts Switch the editor to live collaboration (#36) 2026-07-08 18:00:19 +02:00
editor.spec.ts Add TipTap page editor with REST persistence (#25) 2026-07-06 11:08:43 +02:00
helpers.ts Add auth e2e regression pack with fixtures and CI stack 2026-07-05 05:43:05 +02:00
image.spec.ts Add image paste and insert in the editor (#28) 2026-07-08 11:30:25 +02:00
labels.spec.ts Add label UI: tree management, page assignment, and sidebar filter (#44) 2026-07-09 11:41:42 +02:00
link.spec.ts Add link UX: edit URL and open in new tab (#29) 2026-07-08 11:50:34 +02:00
markdown.spec.ts Add Markdown copy, paste, and per-page export endpoint (#30) 2026-07-08 12:05:11 +02:00
offline.spec.ts Harden the offline e2e for slower CI timing (#38) 2026-07-08 22:24:29 +02:00
README.md Add M2 fixtures and content regression pack (#32) 2026-07-08 13:14:48 +02:00
reorder.spec.ts Add manual page ordering with drag-and-drop (#45) 2026-07-09 12:18:44 +02:00
search.spec.ts Add search UI with scoping and snippets (#50) 2026-07-09 13:36:06 +02:00
sidebar.spec.ts Add pond sidebar with page list, sort modes, and pond switcher (#26) 2026-07-06 12:37:44 +02:00
smoke.spec.ts Add collaboration server skeleton (Hocuspocus) with health, container, and CI/CD (#33) 2026-07-08 14:53:44 +02:00
trash.spec.ts Add page trash: soft delete, restore, and purge job (#31) 2026-07-08 12:48:17 +02:00
wikilink.spec.ts Add wikilink node with autocomplete (#46) 2026-07-09 12:42:01 +02:00

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

# 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-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 14, 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:

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 <feature>.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.