* chore(deps): bump Tauri to 2.11 + all deps to latest within-major
Forwards-only, within-major dependency refresh across the JS and Rust
trees. No major-version crossings.
Tauri (Rust + JS kept mutually consistent):
- tauri 2.4 -> 2.11.3, tauri-build 2.4 -> 2.6, plugins -> latest 2.x
(dialog 2.7, fs 2.5, log 2.8, updater 2.10, deep-link 2.4, ...).
- @tauri-apps/api 2.11.1, cli 2.11.3, plugin-* aligned to the same 2.x.
- gen/schemas regenerated for the new plugin ACL permissions.
JS: raised all caret ranges to highest-within-major (radix-ui, tanstack,
framer-motion 12.41, zod 3.25, vite 6.4.3, vitest 4.1.9, typescript 5.9.3,
typescript-eslint 8.62, eslint 9.39, @types/node 20.19.43, ...). pnpm
install + dedupe; package-lock.json regenerated to match (npm-ci CI path).
React pin preserved: react & react-dom stay exactly 19.0.6 (kept equal to
avoid the React reconciler mismatch / blank-app failure mode).
pnpm.overrides added (pnpm ignored the npm-style top-level `overrides`):
- @radix-ui/react-primitive pinned 2.1.4 — 2.1.5+ adds a global
`declare module 'react'` CSSProperties augmentation (`--radix-${string}`)
that breaks rjsf StyleHTMLAttributes typing; the pin keeps every radix
component bump while dropping just the breaking transitive augmentation.
Held at safe boundary (would increase the typecheck error count):
- react-error-boundary held at ~6.0.3 (6.1.x retypes FallbackProps.error
Error -> unknown, breaking the app's typed fallbacks).
Verification (baseline = origin/main):
- frontend `tsc -b`: 34 -> 33 errors (0 new; 1 pre-existing fixed by
@types/node bump). Constraint "must not increase" satisfied.
- `cargo check` (src-tauri): 0 errors / 71 warnings, unchanged from baseline.
* test(e2e): real Tauri E2E harness (tauri-driver + WebdriverIO), decomplected from frontend smoke
The existing e2e-tests/*.spec.ts (Playwright `page.goto(:1420)`) drive the Vite
frontend in Chromium with NO Tauri IPC. That's frontend smoke, not E2E. This
adds the canonical Tauri 2.x E2E: tauri-driver launches the real hanzo-desktop
binary and WebdriverIO drives the native WebKit webview over WebDriver — real
window, real `window.__TAURI_INTERNALS__`, real commands.
Decomplected — one script per intent, no duplication:
- `pnpm test:e2e` -> wdio, real native app (apps/hanzo-desktop/e2e/)
- `pnpm test:smoke` -> playwright frontend smoke (apps/hanzo-desktop/e2e-tests/)
Playwright config + e2e-tests/README relabelled "frontend smoke — NOT Tauri E2E".
Harness (DRY):
- wdio.conf.ts (app root): capability is `tauri:options.application` ->
src-tauri/target/debug/hanzo-desktop, NO browserName (tauri-driver forwards an
unknown browserName to WebKitWebDriver otherwise). Spawns/kills tauri-driver in
beforeSession/afterSession/onComplete, frees stale ports, kills the driver's
native-driver child via its process group. ESM-safe (__dirname from
import.meta.url; the repo is "type":"module"). Headless on DISPLAY=:1.
- tsconfig.e2e.json: own TS project (node + DOM + @wdio/globals) so the specs
typecheck and stay out of the app's tsconfig.app/spec.
- e2e/helpers.ts: shared waitForAppMounted / navigateTo (client-side history,
the app uses BrowserRouter) / restoreSignedInSession (seeds the REAL persisted
zustand stores for a returning cloud user — unlocks ProtectedRoutes with no
IPC/behaviour mocks).
- Specs (minimal but real, no mocks): app-load (window + #root mount +
__TAURI_INTERNALS__ + onboarding), login (Login button gates on terms
checkbox), models (local "Zen Engine" surface + chat composer), chat (real
composer round-trip), mining (mining-page, on-chain/pending balances,
4-tier privacy selector, recent-proofs).
- e2e/README.md: how to run (needs webkit2gtk-driver + tauri-driver + a debug
build), macOS-unsupported caveat.
Deps: @wdio/{cli,local-runner,mocha-framework,spec-reporter,globals,types}
^9.29.0 (devDeps, within-major). pnpm + package-lock both updated.
Verified: config + specs typecheck (tsc -p tsconfig.e2e.json = 0 errors); app
typecheck unchanged at 33 (no e2e leakage); eslint ignores the e2e suites (their
own tsconfigs) — also clears the pre-existing e2e-tests parse error; tauri-driver
+ WebKitWebDriver present, debug binary builds & launches, wdio reaches session
creation. NOT faked green: on this box's bleeding-edge WebKitGTK 2.52.3 the
tauri-driver automation handshake hangs (IncompleteMessage / HEADERS_TIMEOUT) —
an upstream WebKitGTK>=2.46 issue, documented in e2e/README.md with mitigations.
Hanzo Desktop — real Tauri E2E (WebdriverIO + tauri-driver)
This suite drives the real, built hanzo-desktop binary over WebDriver. It
opens a native window, runs the production React bundle inside the Tauri webview,
and exercises real window.__TAURI_INTERNALS__ IPC.
This is the real end-to-end suite. The Playwright specs under
../e2e-tests/are frontend smoke only — they load the Vite dev server in headless Chromium with no Tauri runtime/IPC. Two distinct jobs, one script each:
script what it drives where pnpm test:e2ethe real native app e2e/(this dir, wdio)pnpm test:smokethe Vite frontend in Chromium e2e-tests/(playwright)
How it works
tauri-driver is a thin WebDriver proxy. It launches the app binary named in
tauri:options.application and bridges WebDriver to the platform webview driver:
- Linux →
WebKitWebDriver(apt packagewebkit2gtk-driver) - Windows →
msedgedriver - macOS → unsupported (WKWebView ships no WebDriver; see caveat below)
wdio.conf.ts (app root) spawns/kills tauri-driver around the session and
points the capability at src-tauri/target/debug/hanzo-desktop.
Prerequisites
- tauri-driver on
PATH:cargo install tauri-driver --locked - Native webview driver (Linux):
sudo apt-get install -y webkit2gtk-driver # provides WebKitWebDriver - A debug build of the app (the binary wdio launches):
# from apps/hanzo-desktop pnpm tauri build --debug # or just the Rust binary (frontend dist must already exist): cargo build --manifest-path src-tauri/Cargo.toml - A display. Headless CI: run under
Xvfb(or any X server) and exportDISPLAY(e.g.:1).
Run
# from repo root or apps/hanzo-desktop
pnpm test:e2e
Useful env overrides (all optional):
| var | default | purpose |
|---|---|---|
TAURI_DRIVER_PATH |
tauri-driver |
path to the tauri-driver binary |
TAURI_WEBDRIVER_PATH |
WebKitWebDriver (Linux) |
native webview driver |
TAURI_DRIVER_PORT |
4444 |
tauri-driver intermediary port |
TAURI_NATIVE_PORT |
4445 |
native driver port |
WDIO_LOG_LEVEL |
warn |
wdio log verbosity |
Example (explicit display + verbose):
DISPLAY=:1 WDIO_LOG_LEVEL=info pnpm test:e2e
What the specs cover (minimal but real, no mocks)
app-load.e2e.ts— native window opens, React mounts into#root,__TAURI_INTERNALS__is present (proves it's the real app), cold-start lands on onboarding.login.e2e.ts— the onboarding Login button is present and enables only after the terms checkbox is accepted.models.e2e.ts— the local Zen engine is named on the benchmark surface; the chat home mounts its model selector + composer.chat.e2e.ts— the real chat composer accepts input and submits (starts a job). A streamed assistant reply additionally needs a running local engine (see the note in the spec).mining.e2e.ts— the mining/wallet panel renders:mining-page, on-chain & pending balances, the four-tier privacy selector, recent-proofs table.
Surfaces behind ProtectedRoute are reached by restoring a real persisted
session (restoreSignedInSession() in helpers.ts) — the same localStorage
envelope the app writes for a returning, signed-in (cloud-mode) user. That is
real app state, not a behavioural mock.
macOS caveat
There is no WebDriver for WKWebView, so tauri-driver cannot drive the app
on macOS. Run this suite on Linux (or Windows with msedgedriver). On macOS,
use the Playwright frontend smoke (pnpm test:smoke) for UI-level coverage.
Known environment blocker — WebKitGTK ≥ 2.46 (Linux)
tauri-driver 2.0.x drives the app through WebKitGTK's WebDriver. On very new
WebKitGTK (observed: 2.52.3, Ubuntu 24.04 arm64) the automation-session
handshake hangs — tauri-driver logs Error serving connection: hyper::Error(IncompleteMessage) and the POST /session never returns (the app
binary launches fine standalone; the break is the driver↔webview automation
protocol, an upstream change in recent WebKitGTK). Symptom in wdio:
UND_ERR_HEADERS_TIMEOUT on session create.
Status of this harness in that environment: fully wired and config-valid —
config + specs typecheck (tsc -p tsconfig.e2e.json), tauri-driver and
WebKitWebDriver resolve, the debug binary builds and launches — but the suite
cannot complete a session until the toolchain catches up. Mitigations:
- Use a newer
tauri-driveronce published with WebKitGTK 2.5x support (cargo install tauri-driver --locked), or - Run against an environment with WebKitGTK ≤ ~2.44, or
- Run the suite on Windows (
msedgedriver), where this WebKitGTK-specific break does not apply.
This is deliberately not faked green — the harness is real; the blocker is upstream and environment-specific.