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
This commit is contained in:
parent
407e49cc32
commit
6a8181f33a
42 changed files with 630 additions and 541 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import { browser, expect } from '@wdio/globals';
|
||||
import { exec } from '../helpers/execute.ts';
|
||||
|
||||
// Phase C — Tab-Based Feature Tests (C5-C9)
|
||||
// Settings panel, project health, metrics tab, context tab, files tab.
|
||||
|
|
@ -7,7 +8,7 @@ import { browser, expect } from '@wdio/globals';
|
|||
|
||||
/** Get all project box IDs currently rendered. */
|
||||
async function getProjectIds(): Promise<string[]> {
|
||||
return browser.execute(() => {
|
||||
return exec(() => {
|
||||
const boxes = document.querySelectorAll('[data-testid="project-box"]');
|
||||
return Array.from(boxes).map(
|
||||
(b) => b.getAttribute('data-project-id') ?? '',
|
||||
|
|
@ -17,7 +18,7 @@ async function getProjectIds(): Promise<string[]> {
|
|||
|
||||
/** Switch to a tab in a specific project box. */
|
||||
async function switchProjectTab(projectId: string, tabIndex: number): Promise<void> {
|
||||
await browser.execute((id, idx) => {
|
||||
await exec((id, idx) => {
|
||||
const box = document.querySelector(`[data-project-id="${id}"]`);
|
||||
const tabs = box?.querySelectorAll('[data-testid="project-tabs"] .ptab');
|
||||
if (tabs && tabs[idx]) (tabs[idx] as HTMLElement).click();
|
||||
|
|
@ -32,7 +33,7 @@ describe('Scenario C5 — Settings Panel Sections', () => {
|
|||
// Close sidebar panel if open
|
||||
const panel = await browser.$('.sidebar-panel');
|
||||
if (await panel.isDisplayed().catch(() => false)) {
|
||||
await browser.execute(() => {
|
||||
await exec(() => {
|
||||
const btn = document.querySelector('.panel-close');
|
||||
if (btn) (btn as HTMLElement).click();
|
||||
});
|
||||
|
|
@ -40,7 +41,7 @@ describe('Scenario C5 — Settings Panel Sections', () => {
|
|||
}
|
||||
|
||||
// Open settings
|
||||
await browser.execute(() => {
|
||||
await exec(() => {
|
||||
const btn = document.querySelector('[data-testid="settings-btn"]');
|
||||
if (btn) (btn as HTMLElement).click();
|
||||
});
|
||||
|
|
@ -48,7 +49,7 @@ describe('Scenario C5 — Settings Panel Sections', () => {
|
|||
});
|
||||
|
||||
it('should show Appearance section with theme dropdown', async () => {
|
||||
const hasTheme = await browser.execute(() => {
|
||||
const hasTheme = await exec(() => {
|
||||
const panel = document.querySelector('.sidebar-panel .settings-panel');
|
||||
if (!panel) return false;
|
||||
const text = panel.textContent ?? '';
|
||||
|
|
@ -58,7 +59,7 @@ describe('Scenario C5 — Settings Panel Sections', () => {
|
|||
});
|
||||
|
||||
it('should show font settings (UI font and Terminal font)', async () => {
|
||||
const hasFonts = await browser.execute(() => {
|
||||
const hasFonts = await exec(() => {
|
||||
const panel = document.querySelector('.sidebar-panel .settings-panel');
|
||||
if (!panel) return false;
|
||||
const text = panel.textContent ?? '';
|
||||
|
|
@ -69,7 +70,7 @@ describe('Scenario C5 — Settings Panel Sections', () => {
|
|||
|
||||
it('should show default shell setting in Agents category', async () => {
|
||||
// Switch to Agents category which contains shell settings
|
||||
const hasShell = await browser.execute(() => {
|
||||
const hasShell = await exec(() => {
|
||||
// Check across all settings categories
|
||||
const panel = document.querySelector('.sidebar-panel .settings-panel');
|
||||
if (!panel) return false;
|
||||
|
|
@ -81,7 +82,7 @@ describe('Scenario C5 — Settings Panel Sections', () => {
|
|||
|
||||
it('should have theme dropdown with many themes', async () => {
|
||||
// Click the theme dropdown
|
||||
const opened = await browser.execute(() => {
|
||||
const opened = await exec(() => {
|
||||
const btn = document.querySelector('.appearance .custom-dropdown .dropdown-btn');
|
||||
if (btn) { (btn as HTMLElement).click(); return true; }
|
||||
return false;
|
||||
|
|
@ -89,13 +90,13 @@ describe('Scenario C5 — Settings Panel Sections', () => {
|
|||
|
||||
if (opened) {
|
||||
await browser.pause(300);
|
||||
const optionCount = await browser.execute(() => {
|
||||
const optionCount = await exec(() => {
|
||||
return document.querySelectorAll('.dropdown-menu .dropdown-item').length;
|
||||
});
|
||||
expect(optionCount).toBeGreaterThanOrEqual(15);
|
||||
|
||||
// Close dropdown
|
||||
await browser.execute(() => {
|
||||
await exec(() => {
|
||||
const btn = document.querySelector('.appearance .custom-dropdown .dropdown-btn');
|
||||
if (btn) (btn as HTMLElement).click();
|
||||
});
|
||||
|
|
@ -105,7 +106,7 @@ describe('Scenario C5 — Settings Panel Sections', () => {
|
|||
|
||||
after(async () => {
|
||||
// Close settings
|
||||
await browser.execute(() => {
|
||||
await exec(() => {
|
||||
const btn = document.querySelector('.panel-close');
|
||||
if (btn) (btn as HTMLElement).click();
|
||||
});
|
||||
|
|
@ -117,7 +118,7 @@ describe('Scenario C5 — Settings Panel Sections', () => {
|
|||
|
||||
describe('Scenario C6 — Project Health Indicators', () => {
|
||||
it('should show status dots on project headers', async () => {
|
||||
const hasDots = await browser.execute(() => {
|
||||
const hasDots = await exec(() => {
|
||||
const dots = document.querySelectorAll('.project-header .status-dot');
|
||||
return dots.length;
|
||||
});
|
||||
|
|
@ -129,7 +130,7 @@ describe('Scenario C6 — Project Health Indicators', () => {
|
|||
const ids = await getProjectIds();
|
||||
if (ids.length < 1) return;
|
||||
|
||||
const dotColor = await browser.execute((id) => {
|
||||
const dotColor = await exec((id) => {
|
||||
const box = document.querySelector(`[data-project-id="${id}"]`);
|
||||
const dot = box?.querySelector('.status-dot');
|
||||
if (!dot) return 'not-found';
|
||||
|
|
@ -142,7 +143,7 @@ describe('Scenario C6 — Project Health Indicators', () => {
|
|||
});
|
||||
|
||||
it('should show status bar agent counts', async () => {
|
||||
const counts = await browser.execute(() => {
|
||||
const counts = await exec(() => {
|
||||
const bar = document.querySelector('[data-testid="status-bar"]');
|
||||
if (!bar) return '';
|
||||
return bar.textContent ?? '';
|
||||
|
|
@ -159,7 +160,7 @@ describe('Scenario C7 — Metrics Tab', () => {
|
|||
const ids = await getProjectIds();
|
||||
if (ids.length < 1) return;
|
||||
|
||||
const hasMetrics = await browser.execute((id) => {
|
||||
const hasMetrics = await exec((id) => {
|
||||
const box = document.querySelector(`[data-project-id="${id}"]`);
|
||||
const tabs = box?.querySelectorAll('[data-testid="project-tabs"] .ptab');
|
||||
if (!tabs) return false;
|
||||
|
|
@ -175,7 +176,7 @@ describe('Scenario C7 — Metrics Tab', () => {
|
|||
const projectId = ids[0];
|
||||
|
||||
// Find and click Metrics tab
|
||||
await browser.execute((id) => {
|
||||
await exec((id) => {
|
||||
const box = document.querySelector(`[data-project-id="${id}"]`);
|
||||
const tabs = box?.querySelectorAll('[data-testid="project-tabs"] .ptab');
|
||||
if (!tabs) return;
|
||||
|
|
@ -188,7 +189,7 @@ describe('Scenario C7 — Metrics Tab', () => {
|
|||
}, projectId);
|
||||
await browser.pause(500);
|
||||
|
||||
const hasContent = await browser.execute((id) => {
|
||||
const hasContent = await exec((id) => {
|
||||
const box = document.querySelector(`[data-project-id="${id}"]`);
|
||||
const panel = box?.querySelector('.metrics-panel, .metrics-tab');
|
||||
return panel !== null;
|
||||
|
|
@ -212,7 +213,7 @@ describe('Scenario C8 — Context Tab Visualization', () => {
|
|||
// Switch to Context tab (index 2)
|
||||
await switchProjectTab(projectId, 2);
|
||||
|
||||
const hasContextUI = await browser.execute((id) => {
|
||||
const hasContextUI = await exec((id) => {
|
||||
const box = document.querySelector(`[data-project-id="${id}"]`);
|
||||
const ctx = box?.querySelector('.context-tab, .context-stats, .token-meter, .stat-value');
|
||||
return ctx !== null;
|
||||
|
|
@ -237,7 +238,7 @@ describe('Scenario C9 — Files Tab & Code Editor', () => {
|
|||
await switchProjectTab(projectId, 3);
|
||||
await browser.pause(500);
|
||||
|
||||
const hasTree = await browser.execute((id) => {
|
||||
const hasTree = await exec((id) => {
|
||||
const box = document.querySelector(`[data-project-id="${id}"]`);
|
||||
const tree = box?.querySelector('.file-tree, .directory-tree, .files-tab');
|
||||
return tree !== null;
|
||||
|
|
@ -250,7 +251,7 @@ describe('Scenario C9 — Files Tab & Code Editor', () => {
|
|||
const ids = await getProjectIds();
|
||||
if (ids.length < 1) return;
|
||||
|
||||
const fileNames = await browser.execute((id) => {
|
||||
const fileNames = await exec((id) => {
|
||||
const box = document.querySelector(`[data-project-id="${id}"]`);
|
||||
const items = box?.querySelectorAll('.tree-name');
|
||||
return Array.from(items ?? []).map(el => el.textContent?.trim() ?? '');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue