Add standing Playwright e2e suite; fix two real bugs it caught
The whole point of driving a real browser instead of curling api/frontend separately: none of this session's prior "live verification" ever exercised the same-origin routing production relies on (Caddy: /ws*+/api/* -> api, else -> frontend), so a real browser's relative fetch()/WebSocket calls were never actually proven to resolve. e2e/proxy.ts mirrors that routing (no caddy binary available locally); global-setup.ts/global-teardown.ts orchestrate throwaway infra + seeded data + the api/frontend/proxy processes end to end. Getting the suite green surfaced two genuine bugs invisible to unit tests: - index.pug loaded map.js via two <script type="module"> tags (one moved to <head> to fix load-order, the original left in place by mistake), causing Alpine's x-init="init()" to run twice and Leaflet to throw "Map container is already initialized" on the second call. - map.js's exportRegion() passed the Alpine-reactive `regionBounds` object straight into worker.postMessage(); Alpine wraps assigned state in Proxies, which the structured clone algorithm can't clone, so every export silently failed. Fixed by spreading into a plain object first. Covers the two flows flagged all session as verified only at the unit/curl level: the marker click-to-place/edit popup (including that a marker created while linked shows up in a second browser context with the same session, proving server-side sync) and the region-select drag + glTF export (including a real triggered file download).
This commit is contained in:
@@ -101,6 +101,33 @@ bun test
|
||||
Each test file creates and tears down its own server row (random token per run) so runs never
|
||||
collide with each other or with real dev data — see `api/src/test-helpers.ts`.
|
||||
|
||||
## Running the e2e suite
|
||||
|
||||
`bun test` above exercises `api` and `frontend` independently — it never proves the browser can
|
||||
actually reach both through the same origin the way production's Caddy routing does (`/ws*` and
|
||||
`/api/*` -> `api`, everything else -> `frontend`, see `Caddyfile`). `e2e/` is a standing
|
||||
Playwright suite that closes that gap: it drives a real Chromium browser against the full stack
|
||||
behind a small routing-equivalent proxy (`e2e/proxy.ts` — no `caddy` binary is available in this
|
||||
dev environment, so it isn't real Caddy, just the same three routing rules).
|
||||
|
||||
```
|
||||
cd e2e
|
||||
bun install
|
||||
bunx playwright install chromium # one-time, downloads the browser binary
|
||||
bunx playwright test
|
||||
```
|
||||
|
||||
`global-setup.ts` does everything by itself — no manual container/migration steps needed first
|
||||
(unlike the `bun test` section above): throwaway Postgres/Redis/MinIO containers
|
||||
(`mcmapper-e2e-*`, distinct names/ports from the `bun test` ones so both can run at once),
|
||||
migrations, a seeded server + linked account/session + a 5x5-chunk terrain footprint around the
|
||||
world origin, then the `api`/`frontend`/proxy processes. `global-teardown.ts` kills every spawned
|
||||
process and removes the containers afterward. Covers the two UI flows most worth a real
|
||||
click-through: the marker click-to-place/edit popup (`tests/markers.spec.ts`, including that a
|
||||
marker created while linked shows up in a second browser context with the same session — the
|
||||
cross-device sync claim) and the region-select drag + glTF export (`tests/region-export.spec.ts`,
|
||||
including a real triggered file download).
|
||||
|
||||
## Attribution
|
||||
|
||||
See `THIRD_PARTY_NOTICES.md`.
|
||||
|
||||
Reference in New Issue
Block a user