import { describe, it, afterEach, expect, $, click, type, pressKey, sleep, closeAll } from './runner.js?v=4'; describe('Search', () => { afterEach(() => closeAll()); it('opens with Ctrl+K', async () => { pressKey('k', { ctrlKey: true }); await sleep(150); expect($('#search')).toBeVisible(); }); it('opens with search button', async () => { click('#search-btn'); await sleep(150); expect($('#search')).toBeVisible(); }); it('input is focused on open', async () => { click('#search-btn'); await sleep(150); expect(document.activeElement).toBe($('#search-input')); }); it('has input and results area', async () => { click('#search-btn'); await sleep(100); expect($('#search-input')).toExist(); expect($('#search-results')).toExist(); }); it('typing triggers results render', async () => { click('#search-btn'); await sleep(100); type('#search-input', 'a'); await sleep(250); expect($('#search-results')).toExist(); }); it('closes with ESC', async () => { click('#search-btn'); await sleep(100); pressKey('Escape'); await sleep(150); expect($('#search')).toBeHidden(); }); }); describe('Search: saved searches', () => { const SAVED_KEY = 'hyprcrd-saved-searches'; afterEach(async () => { // Close overlays and restore localStorage to avoid cross-test pollution. document.querySelector('#search-saved-popup')?.classList.add('hidden'); await closeAll(); }); it('bookmark button and popup exist', () => { expect($('#search-saved-btn')).toExist(); expect($('#search-saved-popup')).toExist(); expect($('#search-saved-popup').classList.contains('hidden')).toBe(true); }); it('clicking bookmark opens the popup', async () => { click('#search-btn'); await sleep(100); click('#search-saved-btn'); await sleep(40); expect($('#search-saved-popup').classList.contains('hidden')).toBe(false); }); it('saves and recalls a search', async () => { // Seed localStorage directly to avoid UI coupling for the save path. const before = JSON.parse(localStorage.getItem(SAVED_KEY) || '[]'); const probe = '__test_saved_search_probe__'; try { localStorage.setItem(SAVED_KEY, JSON.stringify([probe, ...before])); click('#search-btn'); await sleep(100); click('#search-saved-btn'); await sleep(60); const popup = $('#search-saved-popup'); const rows = popup.querySelectorAll('.search-saved-row'); expect(rows.length).toBeGreaterThan(0); // First row should be our probe. expect(rows[0].textContent).toContain(probe); // Click the row → fills input. click(rows[0]); await sleep(40); expect($('#search-input').value).toBe(probe); } finally { // Restore original saved searches. localStorage.setItem(SAVED_KEY, JSON.stringify(before)); } }); it('deletes a saved search', async () => { const before = JSON.parse(localStorage.getItem(SAVED_KEY) || '[]'); const probe = '__test_saved_del__'; try { localStorage.setItem(SAVED_KEY, JSON.stringify([probe])); click('#search-btn'); await sleep(100); click('#search-saved-btn'); await sleep(60); const delBtn = $('#search-saved-popup').querySelector('.search-saved-del'); expect(delBtn).toExist(); click(delBtn); await sleep(40); const after = JSON.parse(localStorage.getItem(SAVED_KEY) || '[]'); expect(after.includes(probe)).toBe(false); } finally { localStorage.setItem(SAVED_KEY, JSON.stringify(before)); } }); it('save-current button adds input value', async () => { const before = JSON.parse(localStorage.getItem(SAVED_KEY) || '[]'); const probe = '__test_saved_add_' + Date.now() + '__'; try { click('#search-btn'); await sleep(100); const inp = $('#search-input'); inp.value = probe; inp.dispatchEvent(new Event('input', { bubbles: true })); click('#search-saved-btn'); await sleep(40); click('#search-saved-add'); await sleep(40); const after = JSON.parse(localStorage.getItem(SAVED_KEY) || '[]'); expect(after.includes(probe)).toBe(true); } finally { localStorage.setItem(SAVED_KEY, JSON.stringify(before)); } }); it('does not add duplicates', async () => { const before = JSON.parse(localStorage.getItem(SAVED_KEY) || '[]'); const probe = '__test_saved_dupe__'; try { localStorage.setItem(SAVED_KEY, JSON.stringify([probe])); click('#search-btn'); await sleep(100); const inp = $('#search-input'); inp.value = probe; inp.dispatchEvent(new Event('input', { bubbles: true })); click('#search-saved-btn'); await sleep(40); click('#search-saved-add'); await sleep(40); const after = JSON.parse(localStorage.getItem(SAVED_KEY) || '[]'); const count = after.filter(q => q === probe).length; expect(count).toBe(1); } finally { localStorage.setItem(SAVED_KEY, JSON.stringify(before)); } }); });