When to Use
Use when validating local dashboard changes via the Docker browser-E2E harness (npm run test:e2e), or when a new/edited E2E spec mysteriously fails to see your code. The harness's test-up.sh runs docker compose up WITHOUT --build, so it reuses a cached pi-dashboard:local image and your committed changes are NOT in the running container until you rebuild.
Procedure
- Rebuild the image from current source FIRST:
docker compose -f docker/compose.yml build(Dockerfile COPYs packages/ + runs npm install && npm run build → bakes local source). Slow (~4-6 min: apt + npm install + build). - Run the suite (or one spec):
npm run test:e2eornpx playwright test <spec-name>. Playwright globalSetup runs docker/test-up.sh (compose up, reuses the just-built image), waits for /api/health 200, runs specs at http://localhost:18000, globalTeardown runs test-down.sh (removes container+volumes+network). - Fast iteration after a build:
PW_E2E_USE_RUNNING=1 npm run test:e2eattaches to an already-running harness and skips teardown. - Spec conventions: select existing app
data-testids (helpers/index.ts TESTIDS map for static keys; page.getByTestId(...-${id}) for dynamic). Navigate Settings→Packages via page.goto('/settings/packages') then wait for testidpackage-browser; RecommendedExtensions card renders inside it (non-collapsible Section).
Pitfalls
- Under heavy host load (multiple worktree test containers + many pi sessions), the managed
npm run test:e2eglobalSetup can blow its 180s health cap even with a pre-built image. Robust fallback = manual up + attach mode for a SINGLE spec: (1) pre-build the per-worktree tag; (2) bring the container up yourself WITH the seed envPI_E2E_SEED=1 PI_TEST_PEERS=both ./docker/test-up.sh -d(writes.pi-test-harness.jsonwith the derived port); (3) pollcurl :$PORT/api/healthuntil 200; (4) runPW_E2E_USE_RUNNING=1 PW_E2E_PORT=$PORT PW_CHANNEL=chrome npx playwright test <spec>(skips globalSetup build + teardown); (5)./docker/test-down.shafter. - MANDATORY seed env on manual
test-up.sh: withoutPI_E2E_SEED=1the onboarding "Add folder" CTA renders DISABLED (title="Set up credentials first", gated onprovidersReady), sospawnFreshGitSession/pinDirectorytime out at 60s. The managed globalSetup setsPI_E2E_SEED=1+PI_TEST_PEERS=both; a hand-rolledtest-up.sh -ddoes NOT — pass them explicitly. - Specs needing global roles/models data (e.g.
roles-custom.spec.tsassertingbuiltinRoleNames-driven UI) MUST spawn a live session first: the client only sendsrequest_roles/request_modelsthrough the first non-ended session (App.tsx), so with zero sessions the roles panel never receivesbuiltinRoleNamesand renders its flat back-compat layout.
Verification
docker compose -f docker/compose.yml buildends withImage pi-dashboard:local Built.npm run test:e2eprintsN passedand the teardown removes the pi-dash-test-* container/volumes/network.- A spec asserting your new UI (e.g. recommended-requires) passes only after the rebuild, not before.