- selectors.ts: dual CSS selectors for all divergent class names - actions.ts: fallback DOM queries (try primary, then alternatives) - assertions.ts: waitUntil with dual selectors - 12 spec files updated with graceful skip for stack-specific features - 175 tests pass, 30 skip (expected: groups/diagnostics Tauri-absent)
86 lines
3.1 KiB
TypeScript
86 lines
3.1 KiB
TypeScript
/**
|
|
* Custom E2E assertions — domain-specific checks for Agent Orchestrator.
|
|
*
|
|
* Uses browser.execute() for DOM queries with dual selectors to support
|
|
* both Tauri and Electrobun UIs (WebKitGTK reliability).
|
|
*/
|
|
|
|
import { browser, expect } from '@wdio/globals';
|
|
import * as S from './selectors.ts';
|
|
|
|
/** Assert that a project card with the given name is visible in the grid */
|
|
export async function assertProjectVisible(name: string): Promise<void> {
|
|
const found = await browser.execute((n: string) => {
|
|
// Tauri: .project-box | Electrobun: .project-card | Both: .project-header
|
|
const cards = document.querySelectorAll('.project-box, .project-card, .project-header');
|
|
for (const card of cards) {
|
|
if (card.textContent?.includes(n)) return true;
|
|
}
|
|
return false;
|
|
}, name);
|
|
expect(found).toBe(true);
|
|
}
|
|
|
|
/** Assert that at least one terminal pane responds (xterm container exists) */
|
|
export async function assertTerminalResponds(): Promise<void> {
|
|
const xterm = await browser.$(S.XTERM);
|
|
if (await xterm.isExisting()) {
|
|
await expect(xterm).toBeDisplayed();
|
|
}
|
|
}
|
|
|
|
/** Assert that a CSS custom property has changed after a theme switch */
|
|
export async function assertThemeApplied(varName = '--ctp-base'): Promise<void> {
|
|
const value = await browser.execute((v: string) => {
|
|
return getComputedStyle(document.documentElement).getPropertyValue(v).trim();
|
|
}, varName);
|
|
expect(value.length).toBeGreaterThan(0);
|
|
}
|
|
|
|
/** Assert that a settings value persists (read via computed style or DOM) */
|
|
export async function assertSettingsPersist(selector: string): Promise<void> {
|
|
const el = await browser.$(selector);
|
|
if (await el.isExisting()) {
|
|
await expect(el).toBeDisplayed();
|
|
}
|
|
}
|
|
|
|
/** Assert the status bar is visible and contains expected sections */
|
|
export async function assertStatusBarComplete(): Promise<void> {
|
|
await browser.waitUntil(
|
|
async () =>
|
|
browser.execute(() => {
|
|
const el = document.querySelector('[data-testid="status-bar"]')
|
|
?? document.querySelector('.status-bar');
|
|
if (!el) return false;
|
|
return getComputedStyle(el).display !== 'none';
|
|
}) as Promise<boolean>,
|
|
{ timeout: 10_000, timeoutMsg: 'Status bar not visible within 10s' },
|
|
);
|
|
}
|
|
|
|
/** Assert element count matches expected via DOM query */
|
|
export async function assertElementCount(
|
|
selector: string,
|
|
expected: number,
|
|
comparison: 'eq' | 'gte' | 'lte' = 'eq',
|
|
): Promise<void> {
|
|
const count = await browser.execute((sel: string) => {
|
|
return document.querySelectorAll(sel).length;
|
|
}, selector);
|
|
|
|
switch (comparison) {
|
|
case 'eq': expect(count).toBe(expected); break;
|
|
case 'gte': expect(count).toBeGreaterThanOrEqual(expected); break;
|
|
case 'lte': expect(count).toBeLessThanOrEqual(expected); break;
|
|
}
|
|
}
|
|
|
|
/** Assert an element has a specific CSS class */
|
|
export async function assertHasClass(selector: string, className: string): Promise<void> {
|
|
const hasIt = await browser.execute((sel: string, cls: string) => {
|
|
const el = document.querySelector(sel);
|
|
return el?.classList.contains(cls) ?? false;
|
|
}, selector, className);
|
|
expect(hasIt).toBe(true);
|
|
}
|