Files
galaxy-game/ui/docs/testing.md
T
Ilia Denisov a89048f6c5 docs(ui): finalize MVP plan structure and de-archaeologize topic docs
MVP web client (Phases 1-30) is complete; reorganize planning + living docs around that.

- PLAN.md kept as the staged MVP record (1-30) with a status block + pointers; removed the 31-36 stages, regression scenarios, and deferred-TODO section (moved out); fixed a stale cross-machine plan path.

- ui/PLAN-finalize.md (new): active web-finalization plan in 8 stages (visual system, a11y, i18n, error UX, PWA, build hygiene, docs, owner manual-QA loop); absorbs former Phases 33 and 35.

- ui/ROADMAP.md (new): post-MVP (Wails, Capacitor, realistic projection, acceptance + regression scenarios) and triaged deferred follow-ups.

- ui/docs/README.md (new): grouped topic-doc index.

- De-archaeologized all 20 ui/docs topic docs + ui/README.md + ui/core/README.md: stripped Phase-N build history, rewritten as current-state; deferred work now points at ROADMAP.md / PLAN-finalize.md. Docs-only; no code change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 23:17:51 +02:00

175 lines
6.9 KiB
Markdown

# UI Testing Tiers
UI client test toolchain. Project-wide testing layers (service /
inter-service / system) live in [`../../docs/TESTING.md`](../../docs/TESTING.md);
this doc covers the UI-specific tiers.
## Tier 1 — per-PR
Triggered by `.gitea/workflows/ui-test.yaml` on every push and pull
request that touches `ui/**`, `backend/**`, `gateway/**`, `game/**`,
`pkg/**`, `go.work`, or `go.work.sum`. Linux runner only.
The `actions/checkout@v4` step uses `submodules: recursive`, so the
runner pulls every git submodule the suite depends on (today only
`pkg/geoip/test-data`, the MaxMind-DB fixtures used by `pkg/geoip`).
Runs:
- `go test` over the monorepo Go modules, excluding two areas:
- `integration/` — needs Docker + testcontainers and is the
project's `make -C integration integration` gate.
- `client/` — the deprecated Fyne client (see `../PLAN.md` §74) is
frozen; its tests are not run in CI.
The `pkg/<name>/` modules are listed one by one in the workflow
because they are independent go.work modules and `./pkg/...` does
not recurse into separate modules. The exact command lives in
`.gitea/workflows/ui-test.yaml`.
- `pnpm test` (Vitest + `@testing-library/svelte` +
`@testing-library/jest-dom`) — component / unit tests under
`ui/frontend/tests/**/*.test.ts`.
- `pnpm exec playwright test` — end-to-end smoke against `pnpm run
dev` on port 5173. Four projects:
- `chromium-desktop` (Desktop Chrome)
- `webkit-desktop` (Desktop Safari)
- `chromium-mobile-iphone-13` (iPhone 13 viewport, Chromium engine)
- `chromium-mobile-pixel-5` (Pixel 5 viewport, Chromium engine)
Playwright traces and screenshots are retained on failure and uploaded
as Gitea Actions artefacts (`playwright-report` and `playwright-traces`,
14-day retention).
## Tier 2 — release
Triggered by `.gitea/workflows/ui-release.yaml` on tag push (`v*`).
Currently mirrors the Tier 1 step set; the dedicated release-only
checks are deferred:
- **Visual regression baseline check** — deferred to the
finalization plan (../Plan-finalize.md). Snapshots will live in
`ui/frontend/tests/__snapshots__/` until the project shifts to
Argos or another visual-diff service.
- **iOS smoke (Capacitor + Appium)** — planned (see ../ROADMAP.md).
Runs on a `macos-13` runner once the Capacitor mobile wrapper
exists.
Both blocks are present as commented sections in
`.gitea/workflows/ui-release.yaml`.
## Local execution
From `ui/frontend/`:
```sh
pnpm test # Vitest
pnpm exec playwright install # one-time
pnpm exec playwright test # all projects
pnpm exec playwright test --project=chromium-desktop
pnpm exec playwright show-report # open last HTML report
```
From the repository root, the same scope CI uses (backend serially
because most packages spawn their own Postgres testcontainer and
parallel bootstraps starve each other on constrained runners):
```sh
go test -count=1 -p 1 ./backend/...
go test -count=1 \
./gateway/... ./game/... \
./pkg/calc/... ./pkg/connector/... ./pkg/cronutil/... \
./pkg/error/... ./pkg/geoip/... ./pkg/model/... \
./pkg/postgres/... ./pkg/redisconn/... ./pkg/schema/... \
./pkg/storage/... ./pkg/transcoder/... ./pkg/util/...
```
## Local development stack
For UI work that needs a real authenticated stack (verifying the
FlatBuffers wire end-to-end, exercising a real lobby flow, hitting
real Mailpit), bring up `tools/local-dev/`:
```sh
make -C tools/local-dev up # postgres + redis + mailpit + backend + gateway
pnpm -C ui/frontend dev # Vite on the host, talks to the stack
```
`ui/frontend/.env.development` already targets the stack
(`http://localhost:8080`) and pins the matching response-signing
public key from `tools/local-dev/keys/`. Per-developer overrides go
into `.env.development.local` (gitignored).
The stack honours `BACKEND_AUTH_DEV_FIXED_CODE` (default `123456` in
`tools/local-dev/.env`) so the login form takes that literal in
addition to the real Mailpit code; see
[`../../tools/local-dev/README.md`](../../tools/local-dev/README.md)
for the full runbook (regenerating the dev keypair, switching the
mode off, troubleshooting common boot issues).
## Synthetic reports for visual testing (DEV)
For visual checks of the map, inspectors and order-overlay against
rich game states, the lobby exposes a DEV-only "Load synthetic
report" affordance (`import.meta.env.DEV`). The flow is:
1. Convert a legacy text report (`tools/local-dev/reports/{dg,gplus}/`)
to JSON with the Go CLI:
```sh
go run ./tools/local-dev/legacy-report/cmd/legacy-report-to-json \
--in tools/local-dev/reports/dg/KNNTS039.REP \
--out /tmp/dg39.json
```
See [`../../tools/local-dev/legacy-report/README.md`](../../tools/local-dev/legacy-report/README.md)
for what the parser populates today and how to extend it when a
new UI phase decodes a new `Report` field.
2. Run the UI dev server (`pnpm -C ui/frontend dev`), open the lobby,
and use the "Load JSON…" file picker in the **Synthetic test
reports (DEV)** section. The page navigates to
`/games/synthetic-<uuid>/map` with the report wired into the
in-game shell.
In synthetic mode:
- The map view, inspectors and races view render against the loaded
report exactly as they would for a real game.
- Composing orders works locally (overlay applies through
`applyOrderOverlay` as usual), but **nothing is sent to the
gateway** — `OrderDraftStore.scheduleSync` short-circuits because
the synthetic id is not a UUID and the layout deliberately does
not bind a `GalaxyClient` for this game.
- The order draft is persisted into the platform `Cache` under the
same `order-drafts` namespace as real games, keyed by the
synthetic id, so navigating back into the same synthetic session
restores the draft. The cache is cleared with
`__galaxyDebug.clearOrderDraft(gameId)` (DEV debug surface).
- A page reload loses the in-memory report registry; opening the
same synthetic id afterwards redirects to /lobby. Re-load the JSON
to reseed.
The synthetic-report parity rule requires every change that extends
`decodeReport` to also extend the legacy parser in lockstep, or to
record in the parser's `README.md` that the new field cannot be
derived from legacy text. This keeps the synthetic-mode coverage in
step with the contract as the UI grows.
## CI verification
Workflow changes are exercised on the primary CI host (`gitea.lan`).
Push the branch (`git push gitea …`), then open the run in the Gitea
UI to inspect the status and logs. See `CLAUDE.md` (`## Per-stage CI
gate`) for the per-stage workflow.
For a sub-second syntax check of a workflow YAML without pulling
images or running anything:
```sh
act -W .gitea/workflows/ui-test.yaml -n push
```
`act` doesn't honour Gitea-specific behaviours (artifact storage,
secrets, run triggers); use it only for syntax checks.