CleanupRegistry's catch-all was masking every kind of teardown error, not just the intended "resource already gone" 404. A backend returning 500 on delete would leak orphans run after run without ever surfacing. Now treat 2xx and 404 as success, log any other status (and any thrown network error) to stderr with the resource label, and keep running the remaining items. The suite stays best-effort but no longer hides accumulating leaks. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dashboard E2E tests
Browser-driven tests for the PiCloud dashboard, powered by Playwright.
Prerequisites
The tests drive a real dashboard against a real backend. Bring up both before running:
# 1. Postgres
docker compose up -d postgres
# 2. Backend (port 18080 matches dashboard/vite.config.ts dev proxy)
PICLOUD_BIND=127.0.0.1:18080 \
PICLOUD_ADMIN_USERNAME=admin \
PICLOUD_ADMIN_PASSWORD=admin \
DATABASE_URL=postgres://picloud:picloud@127.0.0.1:15432/picloud \
cargo run -p picloud
# 3. Browser binaries (one-time, ~200 MB)
cd dashboard && npm run test:e2e:install
The Vite dev server is started automatically by Playwright's webServer
config — you do not need to run npm run dev yourself.
Running
cd dashboard
npm run test:e2e # headless, full suite
npm run test:e2e:ui # interactive UI runner
npx playwright test smoke # run a single spec
npx playwright show-report
Env vars
| Var | Default | Notes |
|---|---|---|
E2E_BASE_URL |
http://localhost:5173 |
Origin tests navigate against (dashboard is mounted at /admin). |
E2E_API_BASE |
http://127.0.0.1:18080 |
Backend used by globalSetup health probe + admin login. |
E2E_DASHBOARD_ORIGIN |
http://localhost:5173 |
Used to seed localStorage during globalSetup. |
E2E_ADMIN_USERNAME |
admin |
Bootstrap admin to log in as. |
E2E_ADMIN_PASSWORD |
admin |
Match PICLOUD_ADMIN_PASSWORD above. |
PICLOUD_DASHBOARD_PORT |
5173 |
Dev server port — picked up by both Vite and Playwright. |
How isolation works
Tests share one backend + one Postgres. To avoid cross-test interference:
- A shared bootstrap admin session is captured once in
tests/e2e/.auth/admin.json(gitignored) and reused by every test viastorageState. - Each test creates resources with a unique slug / username produced by
fixtures/ids.ts(e2e-<prefix>-w<worker>-<random>). - Each test registers cleanup via
fixtures/cleanup.tsand tears down inafterEach. Cleanup is best-effort: a missing resource doesn't fail the suite, so a test can pre-delete and still register the entry.
Layout
tests/e2e/
global-setup.ts # health probe + admin login + storageState seed
smoke.spec.ts # A.5 smoke
fixtures/
auth.ts # UI login/logout helpers (for login-flow specs)
api.ts # bearer-token-backed APIRequestContext
ids.ts # unique slug/username generators (test-fixture)
cleanup.ts # afterEach resource teardown