agent-orchestrator/tests/e2e/wdio.electrobun.conf.js
Hibryda 6a8181f33a fix(e2e): cross-protocol browser.execute() — works with both WebDriver + CDP
Root cause: WebDriverIO devtools protocol wraps functions in a polyfill
that puts `return` inside eval() (not a function body) → "Illegal return".

Fix: exec() wrapper in helpers/execute.ts converts function args to IIFE
strings before passing to browser.execute(). Works identically on both
WebDriver (Tauri) and CDP/devtools (Electrobun CEF).

- 35 spec files updated (browser.execute → exec)
- 4 config files updated (string-form expressions)
- helpers/actions.ts + assertions.ts updated
- 560 vitest + 116 cargo passing
2026-03-22 06:33:55 +01:00

145 lines
4.8 KiB
JavaScript

/**
* WebDriverIO config for Electrobun stack E2E tests.
*
* Uses CDP (Chrome DevTools Protocol) via CEF mode for reliable E2E automation.
* Electrobun must be built/run with AGOR_CEF=1 to bundle CEF and expose
* --remote-debugging-port=9222 (configured in electrobun.config.ts).
*
* Port conventions:
* 9222 — CDP debugging port (CEF)
* 9760 — Vite dev server (HMR)
* 9761 — (reserved, was WebKitWebDriver)
*/
import { execSync, spawn } from 'node:child_process';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { existsSync, rmSync } from 'node:fs';
import { sharedConfig } from './wdio.shared.conf.js';
import { waitForPort } from './helpers/actions.ts';
const __dirname = dirname(fileURLToPath(import.meta.url));
const projectRoot = resolve(__dirname, '../..');
const electrobunRoot = resolve(projectRoot, 'ui-electrobun');
const CDP_PORT = 9222;
// Use the Electrobun fixture generator (different groups.json format)
let fixture;
try {
const { createTestFixture } = await import('../../ui-electrobun/tests/e2e/fixtures.ts');
fixture = createTestFixture('agor-ebun-cdp');
} catch {
const { createTestFixture } = await import('./infra/fixtures.ts');
fixture = createTestFixture('agor-ebun-cdp');
}
process.env.AGOR_TEST = '1';
process.env.AGOR_CEF = '1';
process.env.AGOR_TEST_DATA_DIR = fixture.dataDir;
process.env.AGOR_TEST_CONFIG_DIR = fixture.configDir;
console.log(`[electrobun-cdp] Test fixture at ${fixture.rootDir ?? fixture.configDir}`);
let appProcess;
export const config = {
...sharedConfig,
// Use devtools protocol (CDP) instead of WebDriver
automationProtocol: 'devtools',
capabilities: [{
browserName: 'chromium',
'goog:chromeOptions': {
debuggerAddress: `localhost:${CDP_PORT}`,
},
}],
onPrepare() {
// Find existing binary or build
const candidates = [
resolve(electrobunRoot, 'build/dev-linux-x64/AgentOrchestrator-dev/AgentOrchestrator-dev'),
resolve(electrobunRoot, 'build/Agent Orchestrator'),
resolve(electrobunRoot, 'build/AgentOrchestrator'),
];
let electrobunBinary = candidates.find(p => existsSync(p));
if (!electrobunBinary && !process.env.SKIP_BUILD) {
console.log('[electrobun-cdp] Building with CEF...');
try {
execSync('npx vite build', { cwd: electrobunRoot, stdio: 'inherit' });
execSync('npx electrobun build --env=dev', { cwd: electrobunRoot, stdio: 'inherit' });
} catch (e) {
console.warn('[electrobun-cdp] Build failed:', e.message);
}
electrobunBinary = candidates.find(p => existsSync(p));
}
if (!electrobunBinary) {
// Fall back to `electrobun dev` which builds + launches in one step
console.log('[electrobun-cdp] No binary found, launching via electrobun dev...');
appProcess = spawn('npx', ['electrobun', 'dev'], {
cwd: electrobunRoot,
env: {
...process.env,
AGOR_CEF: '1',
AGOR_TEST: '1',
AGOR_TEST_DATA_DIR: fixture.dataDir,
AGOR_TEST_CONFIG_DIR: fixture.configDir,
},
stdio: 'pipe',
});
} else {
console.log(`[electrobun-cdp] Launching binary: ${electrobunBinary}`);
appProcess = spawn(electrobunBinary, [], {
env: {
...process.env,
AGOR_CEF: '1',
AGOR_TEST: '1',
AGOR_TEST_DATA_DIR: fixture.dataDir,
AGOR_TEST_CONFIG_DIR: fixture.configDir,
},
stdio: 'pipe',
});
}
appProcess.stdout?.on('data', (d) => process.stdout.write(`[app] ${d}`));
appProcess.stderr?.on('data', (d) => process.stderr.write(`[app] ${d}`));
appProcess.on('exit', (code) => console.log(`[electrobun-cdp] App exited with code ${code}`));
// Wait for CDP port to become available
return waitForPort(CDP_PORT, 30_000);
},
async before() {
// Wait for Electrobun app to render — use string script for CDP compatibility
await browser.waitUntil(
async () => {
const hasEl = await browser.execute(
'return document.querySelector(".app-shell") !== null' +
' || document.querySelector(".project-grid") !== null' +
' || document.querySelector(".status-bar") !== null'
);
return hasEl;
},
{ timeout: 20_000, interval: 500, timeoutMsg: 'Electrobun app did not load in 20s' },
);
console.log('[electrobun-cdp] App loaded.');
},
onComplete() {
if (appProcess) {
console.log('[electrobun-cdp] Stopping app...');
appProcess.kill('SIGTERM');
appProcess = undefined;
}
const cleanup = fixture.cleanup ?? (() => {
try {
if (fixture.rootDir) rmSync(fixture.rootDir, { recursive: true, force: true });
} catch { /* best-effort */ }
});
cleanup();
},
};