agent-orchestrator/tests/e2e/specs/phase-d-errors.test.ts
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

191 lines
6.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { browser, expect } from '@wdio/globals';
import { exec } from '../helpers/execute.ts';
// Phase D — Error Handling UI Tests (D4D5)
// Tests toast notifications, notification center, and error state handling.
// ─── Helpers ──────────────────────────────────────────────────────────
/** Close any open overlays/panels to reset UI state. */
async function resetToHomeState(): Promise<void> {
// Close settings panel if open
const panel = await browser.$('.sidebar-panel');
if (await panel.isDisplayed().catch(() => false)) {
await exec(() => {
const btn = document.querySelector('.settings-close') || document.querySelector('.panel-close');
if (btn) (btn as HTMLElement).click();
});
await browser.pause(300);
}
// Close notification panel if open
await exec(() => {
const panel = document.querySelector('[data-testid="notification-panel"]');
if (panel) {
const backdrop = document.querySelector('.notification-center .backdrop');
if (backdrop) (backdrop as HTMLElement).click();
}
});
await browser.pause(200);
// Dismiss search overlay
const overlay = await browser.$('.search-overlay');
if (await overlay.isExisting()) await browser.keys('Escape');
await browser.pause(200);
}
// ─── Scenario D4: Toast Notifications ────────────────────────────────
describe('Scenario D4 — Toast Notifications', () => {
before(async () => {
await resetToHomeState();
});
it('should render ToastContainer in the app', async () => {
const container = await browser.$('.toast-container');
await expect(container).toBeExisting();
});
it('should display notification center bell icon', async () => {
const bell = await browser.$('[data-testid="notification-bell"]');
await expect(bell).toBeDisplayed();
});
it('should show notification dropdown when bell clicked', async () => {
// Click bell via JS for reliability
await exec(() => {
const bell = document.querySelector('[data-testid="notification-bell"]');
if (bell) (bell as HTMLElement).click();
});
await browser.pause(500);
const panel = await browser.$('[data-testid="notification-panel"]');
await expect(panel).toBeDisplayed();
// Verify panel has a title
const title = await exec(() => {
const el = document.querySelector('[data-testid="notification-panel"] .panel-title');
return el?.textContent?.trim() ?? '';
});
expect(title).toBe('Notifications');
});
it('should show panel actions area in notification center', async () => {
// Panel should still be open from previous test
const panelExists = await exec(() => {
return document.querySelector('[data-testid="notification-panel"]') !== null;
});
if (!panelExists) {
await exec(() => {
const bell = document.querySelector('[data-testid="notification-bell"]');
if (bell) (bell as HTMLElement).click();
});
await browser.pause(500);
}
// Verify panel-actions div exists (buttons may be conditional on having notifications)
const actionsDiv = await browser.$('[data-testid="notification-panel"] .panel-actions');
await expect(actionsDiv).toBeExisting();
// Verify the panel list area exists (may show empty state)
const list = await browser.$('[data-testid="notification-panel"] .panel-list');
await expect(list).toBeExisting();
// Close panel
await exec(() => {
const backdrop = document.querySelector('.notification-center .backdrop');
if (backdrop) (backdrop as HTMLElement).click();
});
await browser.pause(300);
});
it('should close notification panel on Escape', async () => {
// Open panel
await exec(() => {
const bell = document.querySelector('[data-testid="notification-bell"]');
if (bell) (bell as HTMLElement).click();
});
await browser.pause(400);
const panelBefore = await browser.$('[data-testid="notification-panel"]');
await expect(panelBefore).toBeDisplayed();
// Press Escape
await browser.keys('Escape');
await browser.pause(400);
// Panel should be gone
const panelAfter = await exec(() => {
return document.querySelector('[data-testid="notification-panel"]') !== null;
});
expect(panelAfter).toBe(false);
});
});
// ─── Scenario D5: Error States ───────────────────────────────────────
describe('Scenario D5 — Error States', () => {
before(async () => {
await resetToHomeState();
});
it('should not show any loadError warnings on fresh launch', async () => {
// Check that no .load-error elements are visible
const loadErrors = await browser.$$('.load-error');
let visibleCount = 0;
for (const el of loadErrors) {
if (await el.isDisplayed().catch(() => false)) {
visibleCount++;
}
}
expect(visibleCount).toBe(0);
});
it('should show status bar with agent state indicators', async () => {
const statusBar = await browser.$('[data-testid="status-bar"]');
await expect(statusBar).toBeDisplayed();
// Verify status bar contains project count text
const text = await statusBar.getText();
expect(text).toContain('projects');
});
it('should show notification center in a functional state', async () => {
const center = await browser.$('[data-testid="notification-center"]');
await expect(center).toBeDisplayed();
// Bell should be clickable without errors
await exec(() => {
const bell = document.querySelector('[data-testid="notification-bell"]');
if (bell) (bell as HTMLElement).click();
});
await browser.pause(400);
// Verify panel rendered without crash
const panel = await browser.$('[data-testid="notification-panel"]');
await expect(panel).toBeDisplayed();
// Close
await exec(() => {
const backdrop = document.querySelector('.notification-center .backdrop');
if (backdrop) (backdrop as HTMLElement).click();
});
await browser.pause(200);
});
it('should render project boxes without error indicators', async () => {
const boxes = await browser.$$('[data-testid="project-box"]');
expect(boxes.length).toBeGreaterThanOrEqual(1);
// Verify no project box has an error overlay or error class
const errorBoxes = await exec(() => {
const boxes = document.querySelectorAll('[data-testid="project-box"]');
let errorCount = 0;
for (const box of boxes) {
if (box.querySelector('.project-error') || box.classList.contains('error')) {
errorCount++;
}
}
return errorCount;
});
expect(errorBoxes).toBe(0);
});
});