Tauri + Svelte 5 + Rust application for orchestrating multiple AI coding agents. Includes Claude, Aider, Codex, and Ollama provider support, multi-agent communication (btmsg/bttask), session anchors, plugin sandbox, FTS5 search, Landlock sandboxing, and 507 vitest + 110 cargo tests.
143 lines
5 KiB
Markdown
143 lines
5 KiB
Markdown
# E2E Tests (WebDriver)
|
|
|
|
Tauri apps use the WebDriver protocol for E2E testing (not Playwright directly).
|
|
The app runs inside WebKit2GTK on Linux, so tests interact with the real WebView.
|
|
|
|
## Prerequisites
|
|
|
|
- Rust toolchain (for building the Tauri app)
|
|
- Display server (X11 or Wayland) — headless Xvfb works for CI
|
|
- `tauri-driver` installed: `cargo install tauri-driver`
|
|
- `webkit2gtk-driver` system package: `sudo apt install webkit2gtk-driver`
|
|
- npm devDeps already in package.json (`@wdio/cli`, `@wdio/local-runner`, `@wdio/mocha-framework`, `@wdio/spec-reporter`)
|
|
|
|
## Running
|
|
|
|
```bash
|
|
# From v2/ directory — builds debug binary automatically, spawns tauri-driver
|
|
npm run test:e2e
|
|
|
|
# Skip rebuild (use existing binary)
|
|
SKIP_BUILD=1 npm run test:e2e
|
|
|
|
# With test isolation (custom data/config dirs)
|
|
BTERMINAL_TEST_DATA_DIR=/tmp/bt-test/data BTERMINAL_TEST_CONFIG_DIR=/tmp/bt-test/config npm run test:e2e
|
|
```
|
|
|
|
The `wdio.conf.js` handles:
|
|
1. Building the debug binary (`cargo tauri build --debug --no-bundle`) in `onPrepare`
|
|
2. Spawning `tauri-driver` before each session (TCP readiness probe, 10s deadline)
|
|
3. Killing `tauri-driver` after each session
|
|
4. Passing `BTERMINAL_TEST=1` env var to the app for test mode isolation
|
|
|
|
## Test Mode (`BTERMINAL_TEST=1`)
|
|
|
|
When `BTERMINAL_TEST=1` is set:
|
|
- File watchers (watcher.rs, fs_watcher.rs) are disabled to avoid inotify noise
|
|
- Wake scheduler is disabled (no auto-wake timers)
|
|
- Data/config directories can be overridden via `BTERMINAL_TEST_DATA_DIR` / `BTERMINAL_TEST_CONFIG_DIR`
|
|
|
|
## CI setup (headless)
|
|
|
|
```bash
|
|
# Install virtual framebuffer + WebKit driver
|
|
sudo apt install xvfb webkit2gtk-driver
|
|
|
|
# Run with Xvfb wrapper
|
|
xvfb-run npm run test:e2e
|
|
```
|
|
|
|
## Writing tests
|
|
|
|
Tests use WebdriverIO with Mocha. Specs go in `specs/`:
|
|
|
|
```typescript
|
|
import { browser, expect } from '@wdio/globals';
|
|
|
|
describe('BTerminal', () => {
|
|
it('should show the status bar', async () => {
|
|
const statusBar = await browser.$('[data-testid="status-bar"]');
|
|
await expect(statusBar).toBeDisplayed();
|
|
});
|
|
});
|
|
```
|
|
|
|
### Stable selectors
|
|
|
|
Prefer `data-testid` attributes over CSS class selectors:
|
|
|
|
| Element | Selector |
|
|
|---------|----------|
|
|
| Status bar | `[data-testid="status-bar"]` |
|
|
| Sidebar rail | `[data-testid="sidebar-rail"]` |
|
|
| Settings button | `[data-testid="settings-btn"]` |
|
|
| Project box | `[data-testid="project-box"]` |
|
|
| Project ID | `[data-project-id="..."]` |
|
|
| Project tabs | `[data-testid="project-tabs"]` |
|
|
| Agent session | `[data-testid="agent-session"]` |
|
|
| Agent pane | `[data-testid="agent-pane"]` |
|
|
| Agent status | `[data-agent-status="idle\|running\|..."]` |
|
|
| Agent messages | `[data-testid="agent-messages"]` |
|
|
| Agent prompt | `[data-testid="agent-prompt"]` |
|
|
| Agent submit | `[data-testid="agent-submit"]` |
|
|
| Agent stop | `[data-testid="agent-stop"]` |
|
|
| Terminal tabs | `[data-testid="terminal-tabs"]` |
|
|
| Add tab button | `[data-testid="tab-add"]` |
|
|
| Terminal toggle | `[data-testid="terminal-toggle"]` |
|
|
| Command palette | `[data-testid="command-palette"]` |
|
|
| Palette input | `[data-testid="palette-input"]` |
|
|
|
|
### Key constraints
|
|
|
|
- `maxInstances: 1` — Tauri doesn't support parallel WebDriver sessions
|
|
- Mocha timeout is 60s — the app needs time to initialize
|
|
- Tests interact with the real WebKit2GTK WebView, not a browser
|
|
- Use `browser.execute()` for JS clicks when WebDriver clicks don't trigger Svelte handlers
|
|
- Agent tests (Scenario 7) require a real Claude CLI install + API key — they skip gracefully if unavailable
|
|
|
|
## Test infrastructure
|
|
|
|
### Fixtures (`fixtures.ts`)
|
|
|
|
Creates isolated test environments with temp data/config dirs and git repos:
|
|
|
|
```typescript
|
|
import { createTestFixture, destroyTestFixture } from '../fixtures';
|
|
|
|
const fixture = createTestFixture('my-test');
|
|
// fixture.dataDir, fixture.configDir, fixture.projectDir, fixture.env
|
|
destroyTestFixture(fixture);
|
|
```
|
|
|
|
### Results DB (`results-db.ts`)
|
|
|
|
JSON-based test results store for tracking runs and steps:
|
|
|
|
```typescript
|
|
import { ResultsDb } from '../results-db';
|
|
|
|
const db = new ResultsDb();
|
|
db.startRun('run-001', 'v2-mission-control', 'abc123');
|
|
db.recordStep({ run_id: 'run-001', scenario_name: 'Smoke', step_name: 'renders', status: 'passed', ... });
|
|
db.finishRun('run-001', 'passed', 5000);
|
|
```
|
|
|
|
## File structure
|
|
|
|
```
|
|
tests/e2e/
|
|
├── README.md # This file
|
|
├── wdio.conf.js # WebdriverIO config with tauri-driver lifecycle
|
|
├── tsconfig.json # TypeScript config for test specs
|
|
├── fixtures.ts # Test fixture generator (isolated environments)
|
|
├── results-db.ts # JSON test results store
|
|
└── specs/
|
|
├── bterminal.test.ts # Smoke tests (CSS class selectors, 50+ tests)
|
|
└── agent-scenarios.test.ts # Phase A scenarios (data-testid selectors, 22 tests)
|
|
```
|
|
|
|
## References
|
|
|
|
- Tauri WebDriver docs: https://v2.tauri.app/develop/tests/webdriver/
|
|
- WebdriverIO docs: https://webdriver.io/
|
|
- tauri-driver: https://crates.io/crates/tauri-driver
|