The Queues tab at /admin/apps/default/queues was returning "Cannot parse `app_id` with value `default`: UUID parsing failed". 27 admin endpoints across 6 files used strict `Path<AppId>` instead of the canonical `Path<String>` + `resolve_app()` pattern from app_repo.rs:34. Working endpoints (apps, app_members, users_admin) all use the lenient pattern; this commit brings the remaining 6 files into line: - queues_api.rs — 2 handlers - files_api.rs — 2 handlers - secrets_api.rs — 3 handlers - topics_api.rs — 4 handlers - dead_letters_api.rs — 5 handlers - triggers_api.rs — 10 handlers The handler bodies (authz, repo calls) are unchanged; only the path extractor and the per-file `ensure_app_exists` helper (now renamed `resolve_app`) move. Lib tests updated to pass `.to_string()` at the call site (Path now takes String, not AppId). email_inbound_api.rs deliberately stays strict-UUID — it's a public webhook receiver consumed by external providers, not by the slug-based dashboard. Adds Playwright spec `dashboard/tests/e2e/navigation/tabs.spec.ts` covering every per-app tab (queues, files, dead-letters, users, invitations, plus the main page hosting triggers/secrets/topics) with a negative assertion against the "Cannot parse" error text plus a focused regression test for the original queues report. 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