65 lines
4.1 KiB
TypeScript
65 lines
4.1 KiB
TypeScript
// @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(<EnginesControl/>));
|
|
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<HTMLInputElement>('input')];
|
|
expect(checks.map(input => input.checked)).toEqual([true, true, true, true, true, true]);
|
|
expect(checks.map(input => input.disabled)).toEqual([true, false, false, false, false, false]);
|
|
await act(async () => { checks[0].click(); checks[1].click(); checks[4].click(); checks[5].click(); });
|
|
expect(readEnginePreferences()).toEqual({ core: true, context: false, report: true, remediation: true, compliance: false, comparison: false });
|
|
checks[5].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<HTMLInputElement>('.engines-option input')[1].checked).toBe(false);
|
|
await act(async () => document.querySelector<HTMLButtonElement>('[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, comparison: true });
|
|
setEngineEnabled('report', false); setEngineEnabled('core', false);
|
|
resetEnginePreferencesForTests();
|
|
expect(readEnginePreferences()).toEqual({ core: true, context: true, report: false, remediation: true, compliance: true, comparison: true });
|
|
localStorage.setItem(ENGINE_PREFERENCES_KEY, '{"core":false,"context":false}');
|
|
resetEnginePreferencesForTests();
|
|
expect(readEnginePreferences()).toEqual({ core: true, context: false, report: true, remediation: true, compliance: true, comparison: 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, comparison: 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, comparison: true });
|
|
expect(() => setEngineEnabled('context', false)).not.toThrow();
|
|
expect(readEnginePreferences().context).toBe(false);
|
|
});
|