1d3744f2d7
- 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).
143 lines
6.7 KiB
Markdown
143 lines
6.7 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
# 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.
|