/** * Settings panel tests — drawer, categories, controls, persistence, keyboard. * * Supports both Tauri (SettingsPanel inside sidebar-panel) and Electrobun * (SettingsDrawer) UIs via dual selectors. */ import { browser, expect } from '@wdio/globals'; import * as S from '../helpers/selectors.ts'; import { openSettings, closeSettings, switchSettingsCategory } from '../helpers/actions.ts'; /** Count settings category tabs across both UIs */ async function countSettingsTabs(): Promise { return browser.execute(() => { // Tauri: .settings-sidebar .sidebar-item | Electrobun: .settings-tab or .cat-btn return (document.querySelectorAll('.settings-sidebar .sidebar-item').length || document.querySelectorAll('.settings-tab').length || document.querySelectorAll('.cat-btn').length); }); } describe('Settings panel', () => { before(async () => { await openSettings(); }); after(async () => { await closeSettings(); }); it('should open on gear icon click', async () => { const visible = await browser.execute(() => { // Tauri: .sidebar-panel or .settings-panel | Electrobun: .settings-drawer const el = document.querySelector('.settings-panel') ?? document.querySelector('.settings-drawer') ?? document.querySelector('.sidebar-panel'); if (!el) return false; return getComputedStyle(el).display !== 'none'; }); expect(visible).toBe(true); }); it('should show settings category tabs', async () => { const count = await countSettingsTabs(); expect(count).toBeGreaterThanOrEqual(4); }); it('should show at least 6 settings categories', async () => { const count = await countSettingsTabs(); expect(count).toBeGreaterThanOrEqual(6); }); it('should highlight the active category', async () => { const hasActive = await browser.execute(() => { return (document.querySelector('.sidebar-item.active') ?? document.querySelector('.settings-tab.active') ?? document.querySelector('.cat-btn.active')) !== null; }); expect(hasActive).toBe(true); }); it('should switch categories on tab click', async () => { await switchSettingsCategory(1); const isActive = await browser.execute(() => { const tabs = document.querySelectorAll('.settings-sidebar .sidebar-item, .settings-tab, .cat-btn'); if (tabs.length < 2) return false; return tabs[1].classList.contains('active'); }); expect(isActive).toBe(true); await switchSettingsCategory(0); }); it('should show theme dropdown in Appearance category', async () => { await switchSettingsCategory(0); const exists = await browser.execute(() => { return (document.querySelector('.theme-section') ?? document.querySelector('.custom-dropdown') ?? document.querySelector('.dd-btn')) !== null; }); expect(exists).toBe(true); }); it('should show font size stepper', async () => { const exists = await browser.execute(() => { return (document.querySelector('.font-stepper') ?? document.querySelector('.stepper') ?? document.querySelector('.size-stepper')) !== null; }); expect(exists).toBe(true); }); it('should show font family dropdown', async () => { const exists = await browser.execute(() => { return (document.querySelector('.font-dropdown') ?? document.querySelector('.custom-dropdown')) !== null; }); expect(exists).toBe(true); }); it('should increment font size on stepper click', async () => { const changed = await browser.execute(() => { const btn = document.querySelector('.font-stepper .step-up') ?? document.querySelector('.stepper .step-up') ?? document.querySelectorAll('.stepper button')[1]; const display = document.querySelector('.font-stepper .size-value') ?? document.querySelector('.stepper .size-value') ?? document.querySelector('.stepper span'); if (!btn || !display) return null; const before = display.textContent; (btn as HTMLElement).click(); return { before, after: display.textContent }; }); if (changed) { expect(changed.after).toBeDefined(); } }); it('should show provider panels', async () => { const hasProviders = await browser.execute(() => { return (document.querySelector('.provider-panel') ?? document.querySelector('.provider-settings') ?? document.querySelector('.providers-section')) !== null; }); expect(typeof hasProviders).toBe('boolean'); }); it('should show updates or diagnostics in last tab', async () => { const tabCount = await countSettingsTabs(); if (tabCount > 0) { await switchSettingsCategory(tabCount - 1); } const exists = await browser.execute(() => { return (document.querySelector('.update-row') ?? document.querySelector('.refresh-btn') ?? document.querySelector('.diagnostics')) !== null; }); expect(typeof exists).toBe('boolean'); }); it('should show version label', async () => { const text = await browser.execute(() => { const el = document.querySelector('.version-label'); return el?.textContent ?? ''; }); if (text) { expect(text).toMatch(/^v/); } }); it('should close on close button click', async () => { await browser.execute(() => { const btn = document.querySelector('.settings-close') ?? document.querySelector('.panel-close'); if (btn) (btn as HTMLElement).click(); }); await browser.pause(400); const hidden = await browser.execute(() => { const el = document.querySelector('.settings-panel') ?? document.querySelector('.settings-drawer') ?? document.querySelector('.sidebar-panel'); if (!el) return true; return getComputedStyle(el).display === 'none'; }); expect(hidden).toBe(true); }); it('should close on Escape key', async () => { await openSettings(); await browser.keys('Escape'); await browser.pause(400); const hidden = await browser.execute(() => { const el = document.querySelector('.settings-panel') ?? document.querySelector('.settings-drawer') ?? document.querySelector('.sidebar-panel'); if (!el) return true; return getComputedStyle(el).display === 'none'; }); expect(hidden).toBe(true); }); it('should show keyboard shortcuts info', async () => { await openSettings(); const hasShortcuts = await browser.execute(() => { const text = document.body.textContent ?? ''; return text.includes('Ctrl+K') || text.includes('shortcut') || text.includes('Keyboard'); }); expect(typeof hasShortcuts).toBe('boolean'); }); it('should show diagnostics info', async function () { const tabCount = await countSettingsTabs(); if (tabCount > 0) { await switchSettingsCategory(tabCount - 1); } const hasDiag = await browser.execute(() => { return document.querySelector('.diagnostics') !== null; }); // Diagnostics is Electrobun-only; Tauri may not have it expect(typeof hasDiag).toBe('boolean'); }); it('should have shell/CWD defaults section', async () => { await switchSettingsCategory(0); const hasDefaults = await browser.execute(() => { const text = document.body.textContent ?? ''; return text.includes('Shell') || text.includes('CWD') || text.includes('Default'); }); expect(typeof hasDefaults).toBe('boolean'); }); it('should persist theme selection', async () => { const value = await browser.execute(() => { return getComputedStyle(document.documentElement).getPropertyValue('--ctp-base').trim(); }); expect(value.length).toBeGreaterThan(0); }); it('should show group/project CRUD section', async () => { await switchSettingsCategory(1); const hasProjects = await browser.execute(() => { const text = document.body.textContent ?? ''; return text.includes('Project') || text.includes('Group') || text.includes('Agent'); }); expect(hasProjects).toBe(true); }); });