- Playwright e2e against Vite dev server (LoginScreen renders, homeserver visible, version pinned). Fallback documented to swap to `wails dev -browser` via WAILS_DEV_URL when full backend bindings are required. - Go integration tests (//go:build integration,goolm) for Start + ListRooms + LoadTimeline + SendText + GetDiagnostics against real Synapse. Skip cleanly if MATRIX_INTEGRATION_TOKEN/USER env vars unset so CI never breaks unattended. - pnpm e2e/e2e:ui/e2e:report scripts. Per-run keyring namespace + t.TempDir XDG_CONFIG_HOME so integration tests don't clobber the production keyring entry. E2E.md explains how to run each layer + limits (OIDC not automated).
6.7 KiB
E2E tests — matrix_client_pc
Two layers cover the app end-to-end:
| Layer | Tool | What it proves | Where |
|---|---|---|---|
| A. Backend integration | go test -tags 'integration goolm' |
MatrixService Start / ListRooms / LoadTimeline / SendText / GetDiagnostics work against a real Synapse + MAS |
Repo root (integration_test.go) |
| B. UI smoke | Playwright + Vite dev server | The React frontend renders LoginScreen with the expected copy + button + version | frontend/ |
Component-level tests (Vitest + RTL with mocked backend) live under frontend/src/__tests__/ — they remain the primary feedback loop. The two layers below add the "did the wiring actually work" gate.
Layer A — Go integration tests (real Synapse)
integration_test.go is gated by two build tags:
integration— keeps it out ofgo test ./....goolm— matches the runtime build tag the app uses for the cryptohelper backend.
Every test calls readIntegrationEnv() which skips cleanly when MATRIX_INTEGRATION_TOKEN / MATRIX_INTEGRATION_USER are unset. CI never breaks for lack of creds — it just shows --- SKIP:.
Required env vars
| Var | Required | Example |
|---|---|---|
MATRIX_INTEGRATION_TOKEN |
yes | syt_ZXhhbXBsZQ... (MAS-issued access token) |
MATRIX_INTEGRATION_USER |
yes | @egutierrez:matrix-af2f3d.organic-machine.com |
MATRIX_INTEGRATION_DEVICE |
optional | ABCDEFGH (auto-discovered via /whoami if missing) |
MATRIX_INTEGRATION_TEST_ROOM |
optional | !abcd1234:matrix-af2f3d.organic-machine.com — enables the send/recv round-trip |
Run
MATRIX_INTEGRATION_TOKEN=syt_... \
MATRIX_INTEGRATION_USER='@egutierrez:matrix-af2f3d.organic-machine.com' \
MATRIX_INTEGRATION_TEST_ROOM='!somefoo:matrix-af2f3d.organic-machine.com' \
go test -tags 'integration goolm' -timeout 120s -v \
./projects/element_agents/apps/matrix_client_pc/...
Verify the build without credentials:
go vet -tags 'integration goolm' \
./projects/element_agents/apps/matrix_client_pc/...
go test -tags 'integration goolm' -timeout 60s -v \
./projects/element_agents/apps/matrix_client_pc/...
# All 4 tests SKIP cleanly.
What each test covers
| Test | Asserts |
|---|---|
TestIntegration_HomeserverReachable |
whoami against https://matrix-af2f3d.organic-machine.com returns the expected user_id (sanity gate; fastest fail) |
TestIntegration_StartAndListRooms |
Start(user) + ListRooms() returns >=1 joined room |
TestIntegration_GetDiagnostics |
After Start: Started, ClientReady, SyncActive all true; RoomsCount >= 1; LastError empty |
TestIntegration_RoundtripMessage |
SendText + LoadTimeline round-trip: the new event surfaces within 10s of polling. Skipped if MATRIX_INTEGRATION_TEST_ROOM missing |
Isolation
The tests use a per-run keyring namespace (fn_registry.matrix_client_pc.test.<unix_nano>) so they never touch the production keyring entry. XDG_CONFIG_HOME is overridden to a t.TempDir(), so the crypto store lands in a throwaway directory that disappears with the test process.
If the host has no D-Bus session (rare for headless CI), buildService calls t.Skip() instead of failing — the keyring is a hard dependency the test acknowledges it can't synthesise.
Limits
- OIDC login is NOT automated. The MAS browser-redirect flow needs a real human at a real browser. Integration tests assume a token already exists; if it doesn't, get one with
wails dev+ click "Sign in" once, then extract from~/.config/matrix_client_pc/...keyring entry. - Device binding. Some MAS sessions issue tokens without a device_id; the app's
Start()retries/whoamiand surfaces a clear error. Integration tests rely on the env var or on/whoamisucceeding — if both miss, the test fails fast with a readable message.
Layer B — Playwright UI smoke
Playwright drives a plain Vite dev server (not full wails dev) on a pinned port. The React app's only Wails runtime call on mount (GetLastUserID) throws synchronously because window.go is undefined, the finally clears the loading overlay, and LoginScreen renders identically to a fresh production launch. This catches HTML / CSS / bundle / Mantine theming regressions without needing the Go backend compiled with goolm + cgo on the test host.
Why not wails dev -browser?
Two reasons:
wails dev(with or without-browser) compiles the full Go binary —goolmrequires cgo, libolm transitive deps, and our SQLite driver. In a WSL / headless CI environment that's slow (60-90s warmup) and noisy.- The Go backend listens to OS keyring + opens browsers for OIDC. Both of those break in containerised / headless contexts.
If/when you do want the real bound runtime (e.g., to test that bindings actually expose the right names), set WAILS_DEV_URL to a running wails dev -browser URL and rerun:
# Terminal 1
cd projects/element_agents/apps/matrix_client_pc
wails dev -browser -loglevel Warning
# Note the URL it prints, usually http://localhost:34115
# Terminal 2
cd projects/element_agents/apps/matrix_client_pc/frontend
WAILS_DEV_URL=http://localhost:34115 pnpm e2e
The playwright.config.ts honours WAILS_DEV_URL and skips spawning its own webServer if you've started one externally (via reuseExistingServer).
Run
cd projects/element_agents/apps/matrix_client_pc/frontend
pnpm e2e # headless run
pnpm e2e:ui # interactive UI for debugging
pnpm e2e:report # open last HTML report
First run on a fresh machine:
pnpm install
pnpm exec playwright install chromium
Current specs
e2e/login_screen.spec.tsLoginScreen renders with Sign-in button— finds thematrix_client_pcheading + theSign in with Matrixbutton.LoginScreen mentions homeserver + MAS context— verifies thematrix-af2f3dhomeserver + "Matrix Authentication Service" copy.LoginScreen shows version tag— pins thev0.1.0 (issue 0147)string.
Limits
- No post-login flow. OIDC requires a real browser session against MAS; Playwright can't drive that headlessly without storing credentials. If
WAILS_E2E_TOKENis ever added, the suite can grow a "logged-in HomeScreen" spec — see issue tracker. - No real Wails IPC. The smoke verifies the static initial render only. Anything that depends on
window.go.*is excluded by design.
Combined run (local dev)
# 1. Layer A (skips if no creds)
go test -tags 'integration goolm' -timeout 60s -v \
./projects/element_agents/apps/matrix_client_pc/...
# 2. Layer B (no creds required)
cd projects/element_agents/apps/matrix_client_pc/frontend
pnpm e2e
Both layers should be green in <3 minutes on a warm cache.