End-to-End Testing
This project uses Playwright to run browser-level tests against a real moltis gateway process.
The goal is simple: catch web UI regressions before they ship.
Why This Approach
- Tests run in a real browser (Chromium), not a DOM mock.
- Tests hit real gateway routes and WebSocket behavior.
- Runtime state is isolated so local machine config does not leak into test outcomes.
Current Setup
The e2e harness lives in crates/web/ui:
playwright.config.jsconfigures Playwright and web server startup.e2e/start-gateway.shboots the gateway in deterministic test mode.e2e/specs/smoke.spec.jscontains smoke coverage for critical routes.
How Startup Works
e2e/start-gateway.sh:
- Creates isolated runtime directories under
target/e2e-runtime. - Seeds
IDENTITY.mdandUSER.mdso onboarding does not block tests. - Exports
MOLTIS_CONFIG_DIR,MOLTIS_DATA_DIR, and test port env. - Starts the gateway with:
cargo run --bin moltis -- --no-tls --bind 127.0.0.1 --port <PORT>
--no-tls is intentional here so Playwright can probe http://.../health during readiness checks.
Running E2E
From repo root (recommended):
just ui-e2e-install
just ui-e2e
Headed mode:
just ui-e2e-headed
Directly from crates/web/ui:
npm install
npm run e2e:install
npm run e2e
Test Artifacts
On failures, Playwright stores artifacts in:
crates/web/ui/test-results/(screenshots, video, traces)crates/web/ui/playwright-report/(HTML report)
Open a trace with:
cd crates/web/ui
npx playwright show-trace test-results/<test-dir>/trace.zip
Writing Stable Tests
- Prefer stable IDs/selectors over broad text matching.
- Assert route + core UI state, avoid over-asserting cosmetic details.
- Keep smoke tests fast and deterministic.
- Add focused scenario tests for high-risk features (chat send flow, settings persistence, skills, projects, crons).
CI Integration
The just ui-e2e target is the intended command for CI.
Pull requests use the local-validation flow: the E2E workflow waits for a
local/e2e commit status, published by ./scripts/local-validate.sh.
Pushes to main, tags, and manual dispatch still run the hosted E2E job.