BlackBeltTechnology

run-dashboard-e2e-local-changes

"Run Playwright E2E (tests/e2e/) against the docker/ all-in-one harness so it reflects LOCAL code changes, not a stale cached image."

BlackBeltTechnology 319 49 Updated 3w ago
GitHub

Install

npx skillscat add blackbelttechnology/pi-agent-dashboard/run-dashboard-e2e-local-changes

Install via the SkillsCat registry.

SKILL.md

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

  1. 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).
  2. Run the suite (or one spec): npm run test:e2e or npx 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).
  3. Fast iteration after a build: PW_E2E_USE_RUNNING=1 npm run test:e2e attaches to an already-running harness and skips teardown.
  4. 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 testid package-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:e2e globalSetup 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 env PI_E2E_SEED=1 PI_TEST_PEERS=both ./docker/test-up.sh -d (writes .pi-test-harness.json with the derived port); (3) poll curl :$PORT/api/health until 200; (4) run PW_E2E_USE_RUNNING=1 PW_E2E_PORT=$PORT PW_CHANNEL=chrome npx playwright test <spec> (skips globalSetup build + teardown); (5) ./docker/test-down.sh after.
  • CO-RESIDENT HARNESS GUARD (#451): test-up.sh compares (n+1) × MEM_LIMIT against the daemon's MemTotal (n = other running pi-dash-test-* projects; default MEM_LIMIT = 4g). It REFUSES to start when (n+1) × MEM_LIMIT >= MemTotal — the refusal runs before the image build and before .pi-test-harness.json is written, and names the other project + the arithmetic. Free the peer (./docker/test-down.sh from ITS worktree) or override with PI_HARNESS_ALLOW_OVERSUBSCRIBE=1. When the limits fit but a peer is up it proceeds with ONE warning: a red result is then not attributable to your change while the peer lives. An unreadable MEM_LIMIT/docker info warns and proceeds (never refuses on missing data). See docker/TESTING.md.
  • NO COMMITTED WALL-CLOCK BUDGET (#450): playwright.config.ts sets no globalTimeout, so a full local run is unbounded by design — the old 15-min budget aborted long runs and reported a timeout instead of a verdict. Termination is bounded by the per-test timeout (60s), expect.timeout (10s) and the harness-down short-circuit (3 probe failures → remaining specs skipped). Want a cap? Pass --global-timeout=<ms> on the CLI; never re-add it to the config (the CI shard job owns timeout-minutes). CI adds a blob reporter (sharded workflow .github/workflows/ci-e2e-browser.yml); local runs keep list + html.
  • MANUAL test-up MUST mirror the managed globalSetup env: PI_E2E_SEED=1 PI_TEST_PEERS=both PI_E2E_OAUTH=1 (and pass PW_GATEWAY_PORT=<gatewayPort> from .pi-test-harness.json when attaching). Without PI_E2E_OAUTH=1 the MCP token specs (mcp-token-settings, mcp-tiered-token) narrow trustedNetworks to [], cannot restore it (their JWT cookie is not honoured), and every later spec fails with OffBoxError: ticket mint denied -- a whole-suite cascade that looks like a regression but is harness config.
  • MANDATORY seed env on manual test-up.sh: without PI_E2E_SEED=1 the onboarding "Add folder" CTA renders DISABLED (title="Set up credentials first", gated on providersReady), so spawnFreshGitSession/pinDirectory time out at 60s. The managed globalSetup sets PI_E2E_SEED=1 + PI_TEST_PEERS=both; a hand-rolled test-up.sh -d does NOT — pass them explicitly.
  • Specs needing global roles/models data (e.g. roles-custom.spec.ts asserting builtinRoleNames-driven UI) MUST spawn a live session first: the client only sends request_roles/request_models through the first non-ended session (App.tsx), so with zero sessions the roles panel never receives builtinRoleNames and renders its flat back-compat layout.

Verification

  1. docker compose -f docker/compose.yml build ends with Image pi-dashboard:local Built.
  2. npm run test:e2e prints N passed and the teardown removes the pi-dash-test-* container/volumes/network.
  3. A spec asserting your new UI (e.g. recommended-requires) passes only after the rebuild, not before.

Categories