Testing

Unit tests, the e2e harness, and CI gates.

Unit tests

Inline #[cfg(test)] modules, heaviest around the things that must not regress: the permission engine (has_perm resolution, board policy rules), crypto primitives in auth-core, DTO validators, and the notification target encoding. Run with just test (workspace, e2e excluded).

e2e: black-box by design

crates/e2e never imports the server. Tests drive a fully running stack over HTTP, exactly like a real client, against docker-compose.test.yml:

  • tmpfs Postgres on host port 55432 (fast, wiped, never shadowed by a native Postgres on 5432)
  • SeaweedFS as the S3-compatible stand-in for R2
  • Mailpit capturing SMTP (its REST API is how tests read emailed tokens)
  • a Turnstile stub answering success to everything
  • the real server, worker, and migration containers built from Dockerfile.dev

Run it with just e2e — it brings the stack up behind healthchecks, runs the suite with capped parallelism, always tears down, and preserves the suite's exit status.

The harness

TestClient is a cookie-jar HTTP client; each instance is an independent browser. with_ip() simulates distinct client IPs. signup_and_login() registers a unique user and completes email verification via Mailpit polling. Two deliberate direct-to-database helpers exist because the app has no first-admin path: grant_role(handle, Role) and backdate_user(handle, days).

Suites

auth, totp, account, moderation, rbac, board, notification, search, user_public, and smoke. Security regressions are pinned with sec_NNN names (e.g. concurrent single-use backup codes, notification IDOR probes) so they are recognizable and never quietly dropped.

CI

Workflow Gate
check.yml fmt --check, clippy --all-targets -D warnings, OpenAPI drift (cargo xtask openapi + git diff --exit-code swagger.json), plus a job applying all migrations to a fresh Postgres
test.yml workspace unit/integration tests (runs in parallel with check)
e2e.yml the full docker-stack e2e suite, dumping container logs on failure
build.yml / docker.yml build check and GHCR image publishing on version tags

The OpenAPI drift gate means swagger.json is always in sync with the code — run just openapi after changing any route.

Built by levish. The source code is available on GitHub.

Batteries included.

enko