This guide covers end-to-end testing for the WebdriverIO Desktop & Mobile services.
E2E tests verify the complete integration of WDIO services with real applications. They run against built applications in fixtures/e2e-apps/ using WebdriverIO's test runner.
e2e/
├── test/
│ ├── electron/ # Electron E2E tests
│ │ ├── api.spec.ts
│ │ ├── dialog.spec.ts
│ │ ├── mock.spec.ts
│ │ └── ...
│ └── tauri/ # Tauri E2E tests
│ ├── api.spec.ts
│ ├── logging.spec.ts
│ └── ...
├── lib/ # Shared test utilities
├── wdio.electron.conf.ts # Electron WDIO config
├── wdio.tauri.conf.ts # Tauri WDIO config
└── wdio.tauri-embedded.conf.ts # Tauri embedded WDIO config
fixtures/e2e-apps/
├── electron-builder/ # Electron app (builder packaging)
├── electron-forge/ # Electron app (forge packaging)
├── electron-no-binary/ # Electron app (no binary mode)
├── electron-script/ # Electron app (script mode)
└── tauri/ # Tauri app
-
Build the apps first:
# Build all E2E apps pnpm turbo build --filter electron-builder-e2e-app pnpm turbo build --filter electron-forge-e2e-app pnpm turbo build --filter tauri-e2e-app -
Build the services:
pnpm build
-
Platform-specific requirements:
- Windows: No special requirements
- macOS: May need to allow app execution in Security settings
- Linux: May need to install
webkit2gtk-driverfor Tauri
# Electron tests (builder packaging)
pnpm --filter @repo/e2e test:e2e:electron-builder
# Electron tests (forge packaging)
pnpm --filter @repo/e2e test:e2e:electron-forge
# Electron tests (script mode)
pnpm --filter @repo/e2e test:e2e:electron-script
# Tauri tests
pnpm --filter @repo/e2e test:e2e:tauri-basic
# Tauri specific modes
pnpm --filter @repo/e2e test:e2e:tauri-basic:window
pnpm --filter @repo/e2e test:e2e:tauri-basic:multiremote
pnpm --filter @repo/e2e test:e2e:tauri-basic:standaloneexport const config: WebdriverIO.Config = {
services: [
[
'electron',
{
appBinaryPath: './path/to/app',
appArgs: ['--arg1', '--arg2'],
},
],
],
// ...
};export const config: WebdriverIO.Config = {
services: ['tauri'],
capabilities: [{
browserName: 'tauri',
'tauri:options': {
application: '/path/to/app/binary',
},
}],
// ...
};Default mode - single browser instance:
capabilities: [{
browserName: 'tauri',
'tauri:options': {
application: appBinaryPath,
},
}],Multiple browser instances simultaneously:
capabilities: {
browserA: {
capabilities: {
browserName: 'tauri',
'tauri:options': { application: appBinaryPath },
},
},
browserB: {
capabilities: {
browserName: 'tauri',
'tauri:options': { application: appBinaryPath },
},
},
},When maxInstances > 1, the service automatically spawns a separate driver per worker:
// wdio.conf.ts
maxInstances: 3, // Enables per-worker mode automatically
capabilities: [{
browserName: 'tauri',
'tauri:options': {
application: appBinaryPath,
},
}],pnpm e2e:tauri-basic -- --logLevel debug
pnpm e2e:electron-builder -- --logLevel debugpnpm wdio wdio.tauri.conf.ts --spec test/tauri/api.spec.tsIf tests hang, check for port conflicts:
# Check what's using the default port
lsof -i :4444
# Kill stale processes
kill -9 <PID>Ensure app is built and path is correct:
ls -la fixtures/e2e-apps/tauri/src-tauri/target/debug/For Tauri deep link tests, the protocol handler must be registered. Setup scripts are provided per app:
# From root - protocol install runs automatically before E2E tests
pnpm e2e:tauri-basic
pnpm e2e:electron-builder
# Run protocol install only
pnpm protocol-install:tauri
pnpm protocol-install:electron-builderEach app has platform-specific setup scripts in fixtures/e2e-apps/<app>/scripts/ that detect the OS and register the protocol handler. These scripts are idempotent — running them multiple times is safe as they check if the protocol is already registered and skip if so.
E2E tests run in CI with matrix configuration:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
include:
- os: macos-latest
arch: x64
- os: macos-latest
arch: arm64| Platform | Notes |
|---|---|
| Windows | Requires .cmd for scripts, Edge driver for WebView2 |
| macOS | Universal builds tested separately, may need security overrides |
| Linux | Requires webkit2gtk-driver for Tauri |
- Create test file in
e2e/test/<framework>/ - Add test utilities in
e2e/lib/if needed - Update configuration if new capabilities needed
- Add to CI in
.github/workflows/ci.yml - Document in this file
- Isolate tests - Each test should be independent
- Clean up state - Reset app state between tests
- Use meaningful selectors - Prefer
data-testidattributes - Avoid flaky patterns - Use explicit waits, not fixed timeouts
- Log strategically - Add context for debugging, but avoid spam
- Test user flows - Focus on real user interactions, not implementation details