Web testing

Facts verified 2026-07-30 by claude-code/2026.07. Generated from the authored source at docs/llm-wiki/web-testing.md — the wiki owns these facts (ADR: D1 of docs/plans/20260811_documentation_system_execution.md). Edit that file, then regenerate: python docs/portfolio/_build/generate_wiki_pages.py.


The suites

  • Registry IDs (in docs/portfolio/_data/tests.yaml): TEST-WEB-01 components, TEST-WEB-02 API routes, TEST-WEB-03 E2E, TEST-E2E-01 kavai_server compatibility smokes (the only one marked passing).
  • Two Vitest configs: web/vitest.config.ts (node env, tests/api/, threads pool, VITEST_SHARD, JUnit output) and web/vitest.components.config.ts (jsdom, tests/components/ + tests/integration/, single-threaded for CI memory, excludes unstable dashboard/bounding-box-visualizer/image-viewer suites).
  • Playwright: web/playwright.config.ts — Chromium only, webServer auto-boots npm run dev on :3000 (PLAYWRIGHT_REUSE_EXISTING_SERVER), CI: 2 retries + trace on first retry + PLAYWRIGHT_SHARD.

Commands (from web/)

  • npm run test:components / test:api / test:e2e; packs: test:e2e:core (@core tag), test:e2e:extras (@extra), test:e2e:m2 (M2 acceptance + perf gates: FPS ≥ 30, AI-query P95 < 3 s, FCP < 5 s).
  • test:api sets SKIP_LOAD_TESTS=1; load tests run deliberately via npm run test:load.
  • kavai_server smokes: pixi run test-e2e-kavai-server at repo root (scripts/e2e-kavai-server.sh boots extern/KavApps kavai_server on :8080, runs ask-live-smoke/ask-gallery-smoke with AI_SERVER_URL pointed at it).

Machinery

  • Component setup (tests/components/setup.ts): jest-dom matchers, MSW server (tests/mocks/handlers.ts fakes /api/datasets, /api/ag-ui-chat, /api/systems, …), lucide-react Proxy icon mock.
  • API tests, two styles — prefer direct handler import with vi.mock of @/lib/supabase/server/admin (template: tests/api/equipment-positions.test.ts with its chainable PostgREST-ish stub); legacy style fetches http://localhost:3000/api/... and mocks when CI=true (datasets.test.ts).
  • Real JWTs: tests/jwt-utils.ts + vitest-global-setup.ts mint tokens via Supabase magic-link admin API (admin/generate_link).
  • Playwright auth/fixtures: tests/global-setup.ts saves playwright/.auth/storageState.json (+ onboarding user) and provisions org/dataset fixtures; orgs created by specs must be prefixed Playwright so the stale sweep deletes leftovers.

Conventions

  • Selectors: data-testid or accessible roles — never CSS classes.
  • In-code @registry TS-FE-* headers are legacy; the registry of record is tests.yaml (map suites to FRs there, don’t invent new TS-FE-* IDs).
  • Placement: route handler → tests/api/, component/hook → tests/components/, journey → tests/e2e/; mock at the boundary (Supabase, external services), never the code under test.
  • TDD where it makes sense: test-first for route handlers (mocked-handler red/green loop), pure logic, and always for bug fixes (failing repro first); test-after for Cesium/WebGL rendering, E2E journeys, and still-moving UI. Feature rhythm: failing route tests → handler → component tests per UI state → one E2E assertion; route changes also update swagger.yaml + the API inventory.