Files
matrix_client_pc/frontend/E2E.md
T
Egutierrez 1d3744f2d7 test(e2e): Playwright UI smoke + Go integration tests against MAS
- 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).
2026-05-25 17:20:05 +02:00

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 of go 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 /whoami and surfaces a clear error. Integration tests rely on the env var or on /whoami succeeding — 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:

  1. wails dev (with or without -browser) compiles the full Go binary — goolm requires cgo, libolm transitive deps, and our SQLite driver. In a WSL / headless CI environment that's slow (60-90s warmup) and noisy.
  2. 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.ts
    • LoginScreen renders with Sign-in button — finds the matrix_client_pc heading + the Sign in with Matrix button.
    • LoginScreen mentions homeserver + MAS context — verifies the matrix-af2f3d homeserver + "Matrix Authentication Service" copy.
    • LoginScreen shows version tag — pins the v0.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_TOKEN is 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.