UI End-to-End Tests (Playwright)
Status (2026-10-01): the bundled local web dashboard was removed from the CLI (#5530), together with the
tests/ui/Playwright suite, its fixtures and thepytest-playwrighttest dependency. The CLI has no web UI to test. A replacement UI built on the planned Mission Status Read API (#5528) will live in its own repository and carry its own browser-driven suite. Restore the old suite from git history (missionplaywright-ui-e2e-bootstrap-01KWX72W, issue #1008) if it is useful there.
Why browser-driven tests
Backend and API tests cannot catch a bug where the server responds correctly
but the browser renders it wrong. That is exactly what shipped in PR #970: 338
backend tests and every architectural test passed while the dashboard's WP-card
click-through modal silently dropped the agent identity, because no test layer
exercised the click-then-render flow. CLAUDE.md's "Never claim the frontend
works without Playwright proof" rule comes from that incident.
Lessons to carry into any future UI suite
- Boot the app hermetically. Run it in-thread on an ephemeral port against a synthetic project root; never reuse a singleton that detaches a process or kills siblings on a shared port range.
- Seed fixture data in the exact shape the reader consumes, and keep that synthetic shape in one shared fixture so every test agrees with it.
- Wait for real state, never a fixed sleep.
- Assert the pre-interaction baseline first, so a later "populated" assertion proves a real transition.
- Scope every assertion to the container under test, never page-global: a field that also renders elsewhere on the page makes a page-global check pass even when the feature under test is broken.
- Prove non-vacuity before committing: break the render path (not the fixture data) and confirm the test fails, then revert.
- Run headless (
PWHEADLESS=1) and record the command and result in the PR.