PR #10 of the 11-PR completion sequence. Closes the 'e2e tests only hit production; no local full-stack harness' finding from the review. The existing suite (scripts/e2e-explorer-frontend.spec.ts) is a production canary — it can't validate a PR before it merges.
Changes
scripts/e2e-full.sh (new, +x)
docker compose -p explorer-e2e up -d postgres elasticsearch redis, waits for pg_isready.
Runs database/migrations/migrate.go so schema + seeds (including 0016_jwt_revocations from PR #8) are applied.
Starts go run ./backend/api/rest on :8080; waits for /healthz.
Builds + starts npm run start on :3000; waits for a 200.
npx playwright install --with-deps chromium; runs the full-stack spec; tears down docker and kills backend+frontend via EXIT trap. E2E_KEEP_STACK=1 bypasses teardown.
Generates an ephemeral JWT_SECRET per run (so PR #3's fail-fast passes) and a dev-safe CSP_HEADER so PR #3's hardened production CSP doesn't reject localhost.
Takes a full-page screenshot of each route into test-results/screenshots/<route>.png.
Track-1 only — no wallet-auth setup needed for CI.
playwright.config.ts
Broadened testMatch from a single filename to /e2e-.*\.spec\.ts/ so both the production canary and the new full-stack spec are picked up.
Makefile
New e2e-full target → ./scripts/e2e-full.sh. Listed in help.
Existing test-e2e (production canary) unchanged.
.github/workflows/e2e-full.yml (new)
Dedicated workflow — not on every push/PR (the stack takes minutes + requires docker). Triggers:
workflow_dispatch (manual)
PRs labelled run-e2e-full (opt-in for changes touching migrations, auth, or routing)
Nightly at 04:00 UTC
Uses Go 1.23.x and Node 20 to match PR #5. Uploads e2e-screenshots and playwright-report as artefacts on every run.
docs/TESTING.md (new)
Four-tier test pyramid (unit → static analysis → production canary → full-stack Playwright), env var reference table, and CI trigger matrix.
Verification
bash -n scripts/e2e-full.sh — clean.
The spec imports compile cleanly against the existing @playwright/test@^1.40 in the root package.json; no new runtime dependencies.
Existing scripts/e2e-explorer-frontend.spec.ts still matched by the broadened testMatch regex.
Completion criterion advanced
7. End-to-end coverage — "make e2e-full boots the real stack, Playwright runs against it, CI uploads screenshots, a nightly job catches regressions that only show up when all services are live."
## Summary
PR #10 of the 11-PR completion sequence. Closes the 'e2e tests only hit production; no local full-stack harness' finding from the review. The existing suite (`scripts/e2e-explorer-frontend.spec.ts`) is a production canary — it can't validate a PR before it merges.
## Changes
### `scripts/e2e-full.sh` (new, +x)
- `docker compose -p explorer-e2e up -d postgres elasticsearch redis`, waits for `pg_isready`.
- Runs `database/migrations/migrate.go` so schema + seeds (including `0016_jwt_revocations` from PR #8) are applied.
- Starts `go run ./backend/api/rest` on `:8080`; waits for `/healthz`.
- Builds + starts `npm run start` on `:3000`; waits for a 200.
- `npx playwright install --with-deps chromium`; runs the full-stack spec; tears down docker and kills backend+frontend via `EXIT` trap. `E2E_KEEP_STACK=1` bypasses teardown.
- Generates an ephemeral `JWT_SECRET` per run (so PR #3's fail-fast passes) and a dev-safe `CSP_HEADER` so PR #3's hardened production CSP doesn't reject localhost.
### `scripts/e2e-full-stack.spec.ts` (new)
- Exercises `/healthz`, `/`, `/blocks`, `/transactions`, `/addresses`, `/tokens`, `/pools`, `/search`, `/wallet`, `/routes`, `/api/v1/access/products` (YAML catalogue from PR #7), `/api/v1/auth/nonce` (SIWE kickoff).
- Takes a full-page screenshot of each route into `test-results/screenshots/<route>.png`.
- Track-1 only — no wallet-auth setup needed for CI.
### `playwright.config.ts`
- Broadened `testMatch` from a single filename to `/e2e-.*\.spec\.ts/` so both the production canary and the new full-stack spec are picked up.
### `Makefile`
- New `e2e-full` target → `./scripts/e2e-full.sh`. Listed in `help`.
- Existing `test-e2e` (production canary) unchanged.
### `.github/workflows/e2e-full.yml` (new)
Dedicated workflow — **not** on every push/PR (the stack takes minutes + requires docker). Triggers:
- `workflow_dispatch` (manual)
- PRs labelled `run-e2e-full` (opt-in for changes touching migrations, auth, or routing)
- Nightly at 04:00 UTC
Uses Go 1.23.x and Node 20 to match PR #5. Uploads `e2e-screenshots` and `playwright-report` as artefacts on every run.
### `docs/TESTING.md` (new)
Four-tier test pyramid (unit → static analysis → production canary → full-stack Playwright), env var reference table, and CI trigger matrix.
## Verification
- `bash -n scripts/e2e-full.sh` — clean.
- The spec imports compile cleanly against the existing `@playwright/test@^1.40` in the root `package.json`; no new runtime dependencies.
- Existing `scripts/e2e-explorer-frontend.spec.ts` still matched by the broadened `testMatch` regex.
## Completion criterion advanced
> **7. End-to-end coverage** — "`make e2e-full` boots the real stack, Playwright runs against it, CI uploads screenshots, a nightly job catches regressions that only show up when all services are live."
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
PR #10 of the 11-PR completion sequence. Closes the 'e2e tests only hit production; no local full-stack harness' finding from the review. The existing suite (
scripts/e2e-explorer-frontend.spec.ts) is a production canary — it can't validate a PR before it merges.Changes
scripts/e2e-full.sh(new, +x)docker compose -p explorer-e2e up -d postgres elasticsearch redis, waits forpg_isready.database/migrations/migrate.goso schema + seeds (including0016_jwt_revocationsfrom PR #8) are applied.go run ./backend/api/reston:8080; waits for/healthz.npm run starton:3000; waits for a 200.npx playwright install --with-deps chromium; runs the full-stack spec; tears down docker and kills backend+frontend viaEXITtrap.E2E_KEEP_STACK=1bypasses teardown.JWT_SECRETper run (so PR #3's fail-fast passes) and a dev-safeCSP_HEADERso PR #3's hardened production CSP doesn't reject localhost.scripts/e2e-full-stack.spec.ts(new)/healthz,/,/blocks,/transactions,/addresses,/tokens,/pools,/search,/wallet,/routes,/api/v1/access/products(YAML catalogue from PR #7),/api/v1/auth/nonce(SIWE kickoff).test-results/screenshots/<route>.png.playwright.config.tstestMatchfrom a single filename to/e2e-.*\.spec\.ts/so both the production canary and the new full-stack spec are picked up.Makefilee2e-fulltarget →./scripts/e2e-full.sh. Listed inhelp.test-e2e(production canary) unchanged..github/workflows/e2e-full.yml(new)Dedicated workflow — not on every push/PR (the stack takes minutes + requires docker). Triggers:
workflow_dispatch(manual)run-e2e-full(opt-in for changes touching migrations, auth, or routing)Uses Go 1.23.x and Node 20 to match PR #5. Uploads
e2e-screenshotsandplaywright-reportas artefacts on every run.docs/TESTING.md(new)Four-tier test pyramid (unit → static analysis → production canary → full-stack Playwright), env var reference table, and CI trigger matrix.
Verification
bash -n scripts/e2e-full.sh— clean.@playwright/test@^1.40in the rootpackage.json; no new runtime dependencies.scripts/e2e-explorer-frontend.spec.tsstill matched by the broadenedtestMatchregex.Completion criterion advanced