4.7 KiB
GUI Testing
Overview
Verstak Desktop uses Playwright for frontend E2E tests that run in a real Chromium browser with mocked Wails bindings. This tests the Svelte component logic, user interactions, and UI state transitions — without needing the actual Wails desktop shell.
What is tested
Frontend E2E (Playwright)
Located in frontend/e2e/, run via npm run test:e2e.
These tests:
- Launch a Vite dev server with mock Wails bindings
- Open the app in a real Chromium browser via Playwright
- Simulate user clicks, wait for UI transitions, assert DOM state
- Collect console errors and page errors on failure
- Capture screenshots on failure
Test suites
| File | Suite | Tests | Status |
|---|---|---|---|
plugin-manager-disable-enable.spec.js |
A: Disable/Enable refresh | 4 | 3 pass, 1 fail* |
sidebar-opens-view.spec.js |
B: Sidebar → view routing | 3 | 3 pass |
reload-updates-state.spec.js |
C: Reload updates UI | 3 | 2 pass, 1 fail* |
* Failing tests document known bugs (see below).
Known bugs detected by tests
Bug M5-1: Sidebar does not update when plugin state changes
Symptom: After disabling a plugin in Plugin Manager, the sidebar item for that plugin remains visible. After re-enabling, it stays visible (doesn't disappear then reappear — it was never gone).
Root cause: Sidebar.svelte loads plugin/contribution data once in
onMount and stores it in local sidebarItems. When PluginManager
disables/enables a plugin and calls ReloadPlugins, the PluginManager
component re-fetches data, but Sidebar does not react to the change — it
still holds the stale list.
Affected tests:
A: Disable plugin: button changes to Enable, sidebar item disappearsA: Disable → Enable full flow in sequenceC: Reload after mock state change reflects new plugin status
Fix needed: Sidebar must either:
- Re-fetch contributions when it receives a custom event (e.g.
verstak:plugins-reloaded), or - Read plugin state reactively from a shared store that both PluginManager and Sidebar subscribe to.
What is NOT tested
Real desktop GUI (WebKitGTK + Wails native shell)
The Playwright tests run the frontend in a standard Chromium browser with mocked Wails bindings. They do not test:
- Actual WebKitGTK rendering (Wails uses WebKitGTK, not Chromium)
- Native window management (minimize, maximize, resize)
- Native file dialogs (SelectDirectory, SelectVaultForOpen)
- Clipboard integration
- System tray / menu bar
- Plugin frontend bundle loading from real filesystem
- Wails event system (window.runtime.EventsOn/Emit)
For real Wails smoke tests, a separate layer is needed using:
- AT-SPI2 (Linux accessibility tree inspection)
- xdotool / ydotool (input simulation)
- scrot / import (screenshot capture)
Running tests
cd frontend
# Run all E2E tests (headless)
npm run test:e2e
# Run with Playwright UI (interactive)
npm run test:e2e:ui
# Run in headed browser (visible)
npm run test:e2e:headed
Test infrastructure
Mock bridge (src/lib/test/wails-mock.js)
Replaces window['go']['api']['App'] with in-memory mock implementations of
all Wails backend methods. Provides:
- Mutable plugin state (enable/disable/status)
- Mutable vault state
- Mutable contributions (views, commands, sidebar items, settings panels)
- Test helpers via
window.__wailsMock:reset()— reset all state to defaultssetPluginStatus(id, status, enabled)— change plugin stategetPluginState(id)— read current statesetVaultStatus(status)— change vault state
Test harness (index.html)
The same index.html is used for both production and test. It detects whether
the Wails runtime (window['go']) is present. If not (i.e. running in a plain
browser), it loads the mock bridge before the Svelte app.
Playwright config (playwright.config.js)
- Dev server:
vite --mode test --port 5174 - Browser: Chromium headless
- Timeouts: 30s test, 10s expect
- Workers: 1 (sequential)
- Screenshots: on failure
- Traces: on first retry
- Results:
e2e-results/test-results.json
Adding new tests
- Create
e2e/your-test.spec.js - Import helpers from
./helpers.js - Use
test.beforeEachto reset mock state and navigate to/ - Use
test.afterEachto assert no console errors - Write scenarios as user actions + assertions
- Run with
npm run test:e2e
Selector conventions
- Plugin cards:
.plugin-cardfiltered by text - Buttons:
.btn-disable,.btn-enable,.btn-settings,.reload-btn - Sidebar items:
.sidebar .plugin-item - View container:
.view-container - View header:
.view-header h2 - Status badges:
.status-badge - Toast:
.toast