Adds a canonical WDIO spec that captures screenshots, page-source dumps, and mock request logs at named checkpoints, plus an afterTest hook that dumps failure artifacts. Wrapper script prints the run dir so coding agents (and humans) can inspect the flow from disk. Co-authored-by: Jwalin Shah <jshah1331@gmail.com> Co-authored-by: WOZCODE <contact@withwoz.com>
5.9 KiB
E2E Testing Guide
Overview
Desktop E2E tests use WebDriverIO (WDIO) to drive the Tauri app via two automation backends:
| Platform | Driver | Port | App format | Selectors |
|---|---|---|---|---|
| Linux (CI default) | tauri-driver |
4444 | Debug binary | CSS / DOM |
| macOS (local dev) | Appium Mac2 | 4723 | .app bundle |
XPath / accessibility |
Linux is the default CI path (ubuntu-22.04). macOS E2E is available for local development and as an optional CI workflow.
Quick start
Linux (CI default)
# Install tauri-driver (one-time)
cargo install tauri-driver
# Build the E2E app
yarn workspace openhuman-app test:e2e:build
# Run all flows
yarn workspace openhuman-app test:e2e:all:flows
# Run a single spec
bash app/scripts/e2e-run-spec.sh test/e2e/specs/smoke.spec.ts smoke
On headless Linux (CI), tests run under Xvfb for a virtual display.
macOS (local dev)
# Install Appium + Mac2 driver (one-time, needs Node 24+)
npm install -g appium
appium driver install mac2
# Build the .app bundle
yarn workspace openhuman-app test:e2e:build
# Run all flows
yarn workspace openhuman-app test:e2e:all:flows
Docker on macOS (Linux E2E locally)
Run the same Linux-based E2E stack from macOS using Docker:
# Build + run all E2E flows
docker compose -f e2e/docker-compose.yml run --rm e2e
# Build the app first (if needed)
docker compose -f e2e/docker-compose.yml run --rm e2e \
yarn workspace openhuman-app test:e2e:build
# Run a single spec
docker compose -f e2e/docker-compose.yml run --rm e2e \
bash app/scripts/e2e-run-spec.sh test/e2e/specs/smoke.spec.ts smoke
Requires Docker Desktop or Colima. The repo is bind-mounted so builds persist between runs.
Architecture
Platform detection
app/test/e2e/helpers/platform.ts exports:
isTauriDriver()—trueon Linux (tauri-driver session)isMac2()—trueon macOS (Appium Mac2 session)supportsExecuteScript()—truewhenbrowser.execute()works (tauri-driver only)
Element helpers
app/test/e2e/helpers/element-helpers.ts provides a unified API:
| Helper | Mac2 (macOS) | tauri-driver (Linux) |
|---|---|---|
waitForText(text) |
XPath over @label/@value/@title | XPath over DOM text content |
waitForButton(text) |
XCUIElementTypeButton XPath | button / [role="button"] XPath |
clickText(text) |
W3C pointer actions | Standard el.click() |
clickNativeButton(text) |
W3C pointer actions on XCUIElementTypeButton | Standard el.click() on button |
clickToggle() |
XCUIElementTypeSwitch / XCUIElementTypeCheckBox | [role="switch"] / input[type="checkbox"] |
waitForWindowVisible() |
XCUIElementTypeWindow | Window handle check |
waitForWebView() |
XCUIElementTypeWebView | document.readyState check |
hasAppChrome() |
XCUIElementTypeMenuBar | Window handle check |
dumpAccessibilityTree() |
Accessibility XML | HTML page source |
Deep link helpers
app/test/e2e/helpers/deep-link-helpers.ts handles auth deep links:
- tauri-driver:
browser.execute(window.__simulateDeepLink(url))(primary),xdg-open(fallback) - Appium Mac2:
macos: deepLinkextension command (primary),open -a ...(fallback)
Writing cross-platform specs
- Use helpers from
element-helpers.ts— never use rawXCUIElementType*selectors in specs - Use
clickNativeButton(text)instead of inline button-clicking code - Use
hasAppChrome()instead of checking forXCUIElementTypeMenuBar - Use
waitForWebView()instead of checking forXCUIElementTypeWebView - For macOS-only tests, use
process.platformguards or separate spec files
Environment variables
| Variable | Default | Description |
|---|---|---|
TAURI_DRIVER_PORT |
4444 |
tauri-driver WebDriver port |
APPIUM_PORT |
4723 |
Appium server port |
E2E_MOCK_PORT |
18473 |
Mock backend server port |
OPENHUMAN_WORKSPACE |
(temp dir) | App workspace directory |
OPENHUMAN_SERVICE_MOCK |
0 |
Enable service mock mode |
OPENHUMAN_E2E_AUTH_BYPASS |
unset | Enable JWT bypass auth |
DEBUG_E2E_DEEPLINK |
(verbose) | Set to 0 to silence deep link logs |
E2E_FORCE_CARGO_CLEAN |
unset | Force cargo clean before E2E build |
CI workflows
Default (every push/PR)
The e2e-linux job runs on ubuntu-22.04:
- Installs system deps (webkit2gtk, Xvfb, dbus)
- Installs
tauri-drivervia cargo - Builds the app with mock server URL baked in
- Runs all E2E flows under Xvfb
Optional macOS E2E
The e2e-macos job runs only via manual dispatch (workflow_dispatch with run_macos_e2e: true):
- Installs Appium + Mac2 driver
- Builds the
.appbundle - Runs all E2E flows
Troubleshooting
Linux: "WebView not ready" timeout
Ensure DISPLAY is set and Xvfb is running:
export DISPLAY=:99
Xvfb :99 -screen 0 1280x1024x24 &
Also ensure dbus is started (required by webkit2gtk):
eval $(dbus-launch --sh-syntax)
Linux: tauri-driver not found
cargo install tauri-driver
macOS: Deep links not working in tauri dev
Deep links require a .app bundle. Use yarn tauri build --debug --bundles app instead.
Docker: Build is slow on first run
The first Docker build compiles Rust + tauri-driver from source. Subsequent runs use cached layers. Cargo registry and git sources are cached via Docker volumes.
Agent-observable artifact flow
For a canonical, inspectable run that drops screenshots, page-source dumps, and mock request logs on disk:
bash app/scripts/e2e-agent-review.sh
Artifacts land in app/test/e2e/artifacts/<timestamp>-agent-review/. Full details + helper API: AGENT-OBSERVABILITY.md. Any failing test triggers wdio.conf.ts's afterTest hook, which writes failure-*.png + failure-*.source.xml into the same run dir.