/** * Smoke tests — verify the app launches and core UI elements are present. * * These tests run first and validate the fundamental layout elements that * every subsequent spec depends on. Supports both Tauri and Electrobun UIs. */ import { browser, expect } from '@wdio/globals'; import * as S from '../helpers/selectors.ts'; import { exec } from '../helpers/execute.ts'; describe('Smoke tests', () => { it('should launch and have the correct title', async () => { await browser.waitUntil( async () => { const title = await browser.getTitle(); return title.includes('Agent Orchestrator') || title.includes('AGOR') || title.includes('Svelte'); }, { timeout: 15_000, timeoutMsg: 'App did not load within 15s' }, ); const title = await browser.getTitle(); // Tauri: "Agent Orchestrator", Electrobun dev: "Svelte App" expect(title.length).toBeGreaterThan(0); }); it('should render the app shell', async () => { const exists = await exec((sel: string) => { return document.querySelector(sel) !== null; }, S.APP_SHELL); if (exists) { const shell = await browser.$(S.APP_SHELL); await expect(shell).toBeDisplayed(); } }); it('should show the sidebar', async () => { // Wait for sidebar to appear (may take time after splash screen) await browser.waitUntil( async () => exec(() => { const el = document.querySelector('.sidebar-rail') ?? document.querySelector('.sidebar') ?? document.querySelector('[data-testid="sidebar-rail"]'); if (!el) return false; return getComputedStyle(el).display !== 'none'; }) as Promise, { timeout: 10_000, timeoutMsg: 'Sidebar not visible within 10s' }, ); }); it('should show the project grid', async () => { const grid = await browser.$(S.PROJECT_GRID); await expect(grid).toBeDisplayed(); }); it('should display the status bar', async () => { const visible = await exec(() => { const el = document.querySelector('[data-testid="status-bar"]') ?? document.querySelector('.status-bar'); if (!el) return false; return getComputedStyle(el).display !== 'none'; }); expect(visible).toBe(true); }); it('should show version text in status bar', async () => { const text = await exec(() => { const el = document.querySelector('.status-bar .version'); return el?.textContent?.trim() ?? ''; }); if (text) { expect(text.length).toBeGreaterThan(0); } }); it('should show group buttons in sidebar (Electrobun) or tab bar (Tauri)', async function () { const hasGroups = await exec(() => { return document.querySelectorAll('.group-btn').length > 0; }); const hasTabBar = await exec(() => { return document.querySelector('.sidebar-rail') !== null || document.querySelector('[data-testid="sidebar-rail"]') !== null; }); // At least one navigation mechanism must exist expect(hasGroups || hasTabBar).toBe(true); }); it('should show the settings gear icon', async () => { const exists = await exec(() => { return (document.querySelector('[data-testid="settings-btn"]') ?? document.querySelector('.sidebar-icon') ?? document.querySelector('.rail-btn')) !== null; }); expect(exists).toBe(true); }); it('should show the notification bell', async () => { const exists = await exec(() => { // Tauri: .bell-btn | Electrobun: .notif-btn return (document.querySelector('.notif-btn') ?? document.querySelector('.bell-btn') ?? document.querySelector('[data-testid="notification-bell"]')) !== null; }); // Bell may not exist in all configurations expect(typeof exists).toBe('boolean'); }); it('should show at least the workspace area', async () => { const workspace = await browser.$(S.WORKSPACE); if (await workspace.isExisting()) { await expect(workspace).toBeDisplayed(); } }); it('should toggle sidebar with settings button', async () => { await exec(() => { const btn = document.querySelector('[data-testid="settings-btn"]') ?? document.querySelector('.sidebar-icon') ?? document.querySelector('.rail-btn'); if (btn) (btn as HTMLElement).click(); }); // Wait for either panel (Tauri: .sidebar-panel, Electrobun: .settings-drawer) await browser.waitUntil( async () => exec(() => document.querySelector('.sidebar-panel, .settings-drawer, .settings-panel') !== null, ) as Promise, { timeout: 5_000 }, ).catch(() => {}); // may not appear in all configs const visible = await exec(() => { const el = document.querySelector('.sidebar-panel') ?? document.querySelector('.settings-drawer') ?? document.querySelector('.settings-panel'); if (!el) return false; return getComputedStyle(el).display !== 'none'; }); if (visible) { expect(visible).toBe(true); // Close it await exec(() => { const btn = document.querySelector('.panel-close') ?? document.querySelector('.settings-close'); if (btn) (btn as HTMLElement).click(); }); await browser.pause(500); } }); it('should show project cards in grid', async () => { const count = await exec(() => { // Tauri: .project-box | Electrobun: .project-card return document.querySelectorAll('.project-box, .project-card').length; }); // May be 0 in minimal fixture, but selector should be valid expect(count).toBeGreaterThanOrEqual(0); }); it('should show the AGOR title', async () => { const text = await exec((sel: string) => { const el = document.querySelector(sel); return el?.textContent?.trim() ?? ''; }, S.AGOR_TITLE); if (text) { expect(text).toBe('AGOR'); } }); it('should have terminal section in project card', async () => { const exists = await exec((sel: string) => { return document.querySelector(sel) !== null; }, S.TERMINAL_SECTION); // Terminal section may or may not be visible depending on card state expect(typeof exists).toBe('boolean'); }); it('should have window close button (Electrobun) or native decorations', async () => { // Electrobun has a custom close button; Tauri uses native decorations const hasClose = await exec(() => { return document.querySelector('.close-btn') !== null; }); // Just verify the check completed — both stacks are valid expect(typeof hasClose).toBe('boolean'); }); });