Some checks failed
CD / Build and push images (push) Successful in 3m5s
CI / Lint, typecheck, test (push) Successful in 2m31s
CI / Auth e2e pack (push) Failing after 2m0s
CI / Build container images (push) Has been skipped
CD / Deploy to Test (push) Successful in 9s
CD / Smoke tests against Test (push) Successful in 1m14s
CD / Promote to Int (push) Successful in 12s
Pond Admins configure the vision's fine-grained cases through a plain-language surface, on top of the base roles from #54. - shared: `AccessRuleView` (a grant enriched with subject/scope display names) and pure conflict helpers `scopeSpecificity`/`sameGrantSubject`/ `isRuleShadowed` (unit-tested) for the client-side shadowed-rule hint. New `access` i18n namespace (de+en) with sentence templates (ADR 0012). - api: `GET /ponds/:id/grants/access-rules` (Pond-Admin) returns the pond's grants enriched with each user's display name and each label/page scope's name, resolved in one batched query per kind. - web `access/`: `AccessRulesManager` in Pond Settings — the pond's rules grouped by subject and rendered as readable de/en sentences ("Anna may not edit pages labeled “Confidential”"), an add form (subject = member or the `signed-in`/`public` pseudo-subjects; scope = label from the tree or a specific page; role; allow/deny) that warns when a rule would be shadowed by a more specific existing one (shared algorithm) and requires an explicit confirmation before granting anything to `public`. Semantics are the shared resolver's — the UI only reflects permissions.md. - tests: shared `conflicts.test.ts`; an api db case for the enriched endpoint; a browser `access-rules` pack that configures BOTH vision patterns through the UI and verifies their effect end to end — "deny label X" (an editor loses a labelled page) and "only label Y" (a signed-in non-member, new `fixture-viewer`, reads only the labelled pages) — plus the shadow hint and the public confirmation, with its own CI step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EwZ4jR4KFAPvpjWevfUGX1
92 lines
5.1 KiB
Markdown
92 lines
5.1 KiB
Markdown
# 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-viewer` | active | signed-in non-member for `authenticated`/`public` access-rule cases (issue #55) |
|
||
| `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 `<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.
|