// @vitest-environment jsdom import { act } from 'react'; import { createRoot, type Root } from 'react-dom/client'; import { afterEach, beforeEach, expect, it, vi } from 'vitest'; import { EnginesControl } from '../../src/components/EnginesControl'; import { ENGINE_PREFERENCES_KEY, readEnginePreferences, resetEnginePreferencesForTests, setEngineEnabled } from '../../src/app/engine-preferences'; let host: HTMLDivElement; let root: Root; beforeEach(() => { vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true); localStorage.clear(); resetEnginePreferencesForTests(); host = document.createElement('div'); document.body.append(host); root = createRoot(host); }); afterEach(async () => { await act(async () => root.unmount()); host.remove(); vi.restoreAllMocks(); vi.unstubAllGlobals(); resetEnginePreferencesForTests(); }); it.each(['dark', 'light'])('opens engine selection, locks Core and restores keyboard focus in %s', async theme => { document.documentElement.dataset.theme = theme; await act(async () => root.render()); const trigger = host.querySelector('button')!; expect(trigger.textContent).toBe('Engines'); await act(async () => trigger.click()); const dialog = document.querySelector('[role="dialog"]')!; const checks = [...dialog.querySelectorAll('input')]; expect(checks.map(input => input.checked)).toEqual([true, true, true, true, true]); expect(checks.map(input => input.disabled)).toEqual([true, false, false, false, false]); await act(async () => { checks[0].click(); checks[1].click(); checks[4].click(); }); expect(readEnginePreferences()).toEqual({ core: true, context: false, report: true, remediation: true, compliance: false }); checks[4].focus(); await act(async () => document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab', bubbles: true, cancelable: true }))); expect(document.activeElement).toBe(dialog.querySelector('button')); await act(async () => document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))); expect(document.querySelector('[role="dialog"]')).toBeNull(); expect(document.activeElement).toBe(trigger); await act(async () => trigger.click()); expect(document.querySelectorAll('.engines-option input')[1].checked).toBe(false); await act(async () => document.querySelector('[aria-label="Close window"]')!.click()); delete document.documentElement.dataset.theme; }); it('persists independent choices, ignores the obsolete Context preference and cannot disable Core', () => { localStorage.setItem('ASSESSOR.contextLayer', 'off'); expect(readEnginePreferences()).toEqual({ core: true, context: true, report: true, remediation: true, compliance: true }); setEngineEnabled('report', false); setEngineEnabled('core', false); resetEnginePreferencesForTests(); expect(readEnginePreferences()).toEqual({ core: true, context: true, report: false, remediation: true, compliance: true }); localStorage.setItem(ENGINE_PREFERENCES_KEY, '{"core":false,"context":false}'); resetEnginePreferencesForTests(); expect(readEnginePreferences()).toEqual({ core: true, context: false, report: true, remediation: true, compliance: true }); }); it('defaults safely when storage is malformed or blocked and still allows session toggles', () => { localStorage.setItem(ENGINE_PREFERENCES_KEY, 'bad json'); expect(readEnginePreferences()).toEqual({ core: true, context: true, report: true, remediation: true, compliance: true }); resetEnginePreferencesForTests(); vi.spyOn(Storage.prototype, 'getItem').mockImplementation(() => { throw new Error('blocked'); }); vi.spyOn(Storage.prototype, 'setItem').mockImplementation(() => { throw new Error('blocked'); }); expect(readEnginePreferences()).toEqual({ core: true, context: true, report: true, remediation: true, compliance: true }); expect(() => setEngineEnabled('context', false)).not.toThrow(); expect(readEnginePreferences().context).toBe(false); });