import { browser, expect } from '@wdio/globals'; /** Reset UI to home state (close any open panels/overlays). */ async function resetToHomeState(): Promise { const settingsPanel = await browser.$('.settings-panel'); if (await settingsPanel.isExisting()) { const closeBtn = await browser.$('.settings-close'); if (await closeBtn.isExisting()) await closeBtn.click(); } const overlay = await browser.$('.search-overlay'); if (await overlay.isExisting()) await browser.keys('Escape'); } /** Open the settings panel, waiting for content to render. */ async function openSettings(): Promise { const panel = await browser.$('.sidebar-panel'); const isOpen = await panel.isDisplayed().catch(() => false); if (!isOpen) { // Use data-testid for unambiguous selection await browser.execute(() => { const btn = document.querySelector('[data-testid="settings-btn"]'); if (btn) (btn as HTMLElement).click(); }); await panel.waitForDisplayed({ timeout: 5000 }); } // Wait for settings content to mount await browser.waitUntil( async () => { const count = await browser.execute(() => document.querySelectorAll('.settings-tab .settings-section').length, ); return (count as number) >= 1; }, { timeout: 5000, timeoutMsg: 'Settings sections did not render within 5s' }, ); await browser.pause(200); } /** Close the settings panel if open. */ async function closeSettings(): Promise { const panel = await browser.$('.sidebar-panel'); if (await panel.isDisplayed().catch(() => false)) { await browser.execute(() => { const btn = document.querySelector('.panel-close'); if (btn) (btn as HTMLElement).click(); }); await browser.pause(500); } } describe('BTerminal — Settings Panel', () => { before(async () => { await resetToHomeState(); await openSettings(); }); after(async () => { await closeSettings(); }); it('should display the settings tab container', async () => { const settingsTab = await browser.$('.settings-tab'); await expect(settingsTab).toBeDisplayed(); }); it('should show settings sections', async () => { const sections = await browser.$$('.settings-section'); expect(sections.length).toBeGreaterThanOrEqual(1); }); it('should display theme dropdown', async () => { const dropdown = await browser.$('.custom-dropdown .dropdown-trigger'); await expect(dropdown).toBeDisplayed(); }); it('should open theme dropdown and show options', async () => { // Use JS click — WebDriver clicks don't reliably trigger Svelte onclick // on buttons inside scrollable panels via WebKit2GTK/tauri-driver await browser.execute(() => { const trigger = document.querySelector('.custom-dropdown .dropdown-trigger'); if (trigger) (trigger as HTMLElement).click(); }); await browser.pause(500); const menu = await browser.$('.dropdown-menu'); await menu.waitForExist({ timeout: 3000 }); const options = await browser.$$('.dropdown-option'); expect(options.length).toBeGreaterThan(0); // Close dropdown by clicking trigger again await browser.execute(() => { const trigger = document.querySelector('.custom-dropdown .dropdown-trigger'); if (trigger) (trigger as HTMLElement).click(); }); await browser.pause(300); }); it('should display group list', async () => { // Groups section is below Appearance/Defaults/Providers — scroll into view await browser.execute(() => { const el = document.querySelector('.group-list'); if (el) el.scrollIntoView({ behavior: 'instant', block: 'center' }); }); await browser.pause(300); const groupList = await browser.$('.group-list'); await expect(groupList).toBeDisplayed(); }); it('should close settings panel with close button', async () => { // Ensure settings is open await openSettings(); // Use JS click for reliability await browser.execute(() => { const btn = document.querySelector('.panel-close'); if (btn) (btn as HTMLElement).click(); }); await browser.pause(500); const panel = await browser.$('.sidebar-panel'); await expect(panel).not.toBeDisplayed(); }); }); describe('BTerminal — Settings Interaction', () => { before(async () => { await resetToHomeState(); await openSettings(); // Scroll to top for font controls await browser.execute(() => { const content = document.querySelector('.panel-content') || document.querySelector('.sidebar-panel'); if (content) content.scrollTop = 0; }); await browser.pause(300); }); after(async () => { await closeSettings(); }); it('should show font size controls with increment/decrement', async () => { const sizeControls = await browser.$$('.size-control'); expect(sizeControls.length).toBeGreaterThanOrEqual(1); const sizeBtns = await browser.$$('.size-btn'); expect(sizeBtns.length).toBeGreaterThanOrEqual(2); // at least - and + for one control const sizeInput = await browser.$('.size-input'); await expect(sizeInput).toBeExisting(); }); it('should increment font size', async () => { const sizeInput = await browser.$('.size-input'); const valueBefore = await sizeInput.getValue(); // Click the + button (second .size-btn in first .size-control) await browser.execute(() => { const btns = document.querySelectorAll('.size-control .size-btn'); // Second button is + (first is -) if (btns.length >= 2) (btns[1] as HTMLElement).click(); }); await browser.pause(300); const afterEl = await browser.$('.size-input'); const valueAfter = await afterEl.getValue(); expect(parseInt(valueAfter as string)).toBe(parseInt(valueBefore as string) + 1); }); it('should decrement font size back', async () => { const sizeInput = await browser.$('.size-input'); const valueBefore = await sizeInput.getValue(); // Click the - button (first .size-btn) await browser.execute(() => { const btns = document.querySelectorAll('.size-control .size-btn'); if (btns.length >= 1) (btns[0] as HTMLElement).click(); }); await browser.pause(300); const afterEl = await browser.$('.size-input'); const valueAfter = await afterEl.getValue(); expect(parseInt(valueAfter as string)).toBe(parseInt(valueBefore as string) - 1); }); it('should display group rows with active indicator', async () => { // Scroll to Groups section (below Appearance, Defaults, Providers) await browser.execute(() => { const el = document.querySelector('.group-list'); if (el) el.scrollIntoView({ behavior: 'instant', block: 'center' }); }); await browser.pause(300); const groupRows = await browser.$$('.group-row'); expect(groupRows.length).toBeGreaterThanOrEqual(1); const activeGroup = await browser.$('.group-row.active'); await expect(activeGroup).toBeExisting(); }); it('should show project cards', async () => { // Scroll to Projects section await browser.execute(() => { const el = document.querySelector('.project-cards'); if (el) el.scrollIntoView({ behavior: 'instant', block: 'center' }); }); await browser.pause(300); const cards = await browser.$$('.project-card'); expect(cards.length).toBeGreaterThanOrEqual(1); }); it('should display project card with name and path', async () => { const nameInput = await browser.$('.card-name-input'); await expect(nameInput).toBeExisting(); const name = await nameInput.getValue() as string; expect(name.length).toBeGreaterThan(0); const cwdInput = await browser.$('.cwd-input'); await expect(cwdInput).toBeExisting(); const cwd = await cwdInput.getValue() as string; expect(cwd.length).toBeGreaterThan(0); }); it('should show project toggle switch', async () => { const toggle = await browser.$('.card-toggle'); await expect(toggle).toBeExisting(); const track = await browser.$('.toggle-track'); await expect(track).toBeDisplayed(); }); it('should show add project form', async () => { // Scroll to add project form (at bottom of Projects section) await browser.execute(() => { const el = document.querySelector('.add-project-form'); if (el) el.scrollIntoView({ behavior: 'instant', block: 'center' }); }); await browser.pause(300); const addForm = await browser.$('.add-project-form'); await expect(addForm).toBeDisplayed(); const addBtn = await browser.$('.add-project-form .btn-primary'); await expect(addBtn).toBeExisting(); }); });