apps/readest-app/docs/testing.md
Readest uses three test tiers, all powered by Vitest.
pnpm test)Runs tests in a jsdom environment. No browser or Tauri runtime required.
pnpm test # Run all unit tests
pnpm test -- src/__tests__/utils/misc.test.ts # Run a single file
pnpm test -- --watch # Watch mode
vitest.config.mtssrc/**/*.test.ts (excludes *.browser.test.ts and *.tauri.test.ts)pnpm test:browser)Runs tests in a real Chromium browser via Playwright. Required for code that depends on Web Workers, SharedArrayBuffer, OPFS, or other browser-only APIs.
pnpm test:browser
vitest.browser.config.mtssrc/**/*.browser.test.ts@vitest/browser-playwright)@tursodatabase/database-wasm), Web Worker integration, browser-specific storage APIs.pnpm test:tauri)Runs Vitest tests inside the Tauri WebView, with access to Tauri IPC and native plugin commands. Tests execute in the actual app environment.
In one terminal, start the app with the webdriver feature enabled:
pnpm tauri:dev:test # Dev mode (uses tauri dev server, faster iteration)
pnpm tauri:build:test # Debug release build (closer to production)
These commands compile the Rust backend with --features webdriver, which:
tauri-plugin-webdriver (embeds a W3C WebDriver server on port 4445)http://127.0.0.1:*), so Vitest's browser-mode iframe can call Tauri IPCKeep this running while you run tests.
In another terminal:
pnpm test:tauri
Vitest connects directly to the embedded WebDriver server (port 4445) in the running Tauri app and executes tests inside its WebView.
vitest.tauri.config.mtssrc/**/*.tauri.test.ts@vitest/browser-webdriverio (connects to port 4445)Tests access Tauri IPC via a shared helper:
import { invoke } from '../tauri/tauri-invoke';
it('calls a plugin command', async () => {
const result = await invoke('plugin:turso|load', { options: { path: 'sqlite::memory:' } });
expect(result).toBeDefined();
});
The invoke() helper accesses window.top.__TAURI_INTERNALS__ (Vitest runs in an iframe, Tauri injects IPC into the main frame).
Limitations: Only custom invoke commands and plugin commands listed in the webdriver capability work. Standard Tauri JS APIs (e.g. @tauri-apps/api) that rely on URL: local may not work from the Vitest iframe.
pnpm test:android)Drives the installed Readest app on an adb-connected Android device or
emulator: gestures are injected with adb shell input, and the app's state is
probed through the WebView's Chrome DevTools Protocol (forwarded from the
webview_devtools_remote_<pid> abstract socket). This is the only lane that
exercises real Android touch selection, native handle behavior, and page-turn
gestures (e.g. the issue #1553 hyphen-selection fixes).
# One-time: install a dev build on the device/emulator
pnpm dev-android
# Start an emulator if no device is attached (see `emulator -list-avds`)
emulator -avd Pixel_9_Pro &
# Run the lane (soft-skips when no adb/device/app is available)
pnpm test:android
# With several devices attached, pick one:
ANDROID_SERIAL=emulator-5554 pnpm test:android
vitest.android.config.mts (node environment, serial execution, retry: 1)src/**/*.android.test.tssrc/__tests__/android/helpers/ — adb.ts (gestures), cdp.ts (DevTools client), reader.ts (app-level probes)src/__tests__/fixtures/data/ (e.g. sample-alice.epub), opened transiently via a VIEW intent so the device library is never modifieddevicePixelRatio — never bake in coordinates.waitFor() on an observable condition (selection
state, handle count, frame position); reserve fixed pauses for gesture
pacing (long-press hold, corner dwell)..github/workflows/android-e2e.yml runs the lane on an x86_64 emulator
(ubuntu runner with KVM): it builds a debug APK for x86_64 (no signing
secrets needed), boots a cached AVD via reactivecircus/android-emulator-runner,
installs the APK, and runs pnpm test:android. It is intentionally not
PR-blocking — it runs nightly, on workflow_dispatch, or when a PR gets the
e2e-android label.
Full end-to-end tests using WebDriverIO, for UI-level testing against the running Tauri app. Same two-step workflow as Tauri integration tests.
# Terminal 1: start the app (same as for Tauri integration tests)
pnpm tauri:dev:test
# Terminal 2: run E2E tests
pnpm test:e2e
wdio.conf.tse2e/**/*.e2e.ts@wdio/mocha-framework)| Suffix | Runner | Environment |
|---|---|---|
*.test.ts | pnpm test | jsdom |
*.browser.test.ts | pnpm test:browser | Chromium (Playwright) |
*.tauri.test.ts | pnpm test:tauri | Tauri WebView |
*.e2e.ts | pnpm test:e2e | Tauri app (WDIO) |
*.android.test.ts | pnpm test:android | Android device (CDP) |