// @vitest-environment jsdom import { act, createElement } from 'react'; import { createRoot, type Root } from 'react-dom/client'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { CHAT_SETTINGS_STORAGE_KEY } from '../types'; import { useChatSettings, type UseChatSettingsReturn } from '../useChatSettings'; (globalThis as Record).IS_REACT_ACT_ENVIRONMENT = true; let container: HTMLDivElement; let root: Root; let api: UseChatSettingsReturn | null = null; function Probe() { api = useChatSettings(); return null; } beforeEach(() => { window.localStorage.clear(); container = document.createElement('div'); document.body.appendChild(container); root = createRoot(container); }); afterEach(() => { act(() => root.unmount()); container.remove(); window.localStorage.clear(); api = null; }); async function flush() { await act(async () => { await Promise.resolve(); }); } describe('useChatSettings', () => { it('exposes the default settings before anything is stored', async () => { await act(async () => root.render(createElement(Probe))); expect(api!.settings.pageContext.linked).toBe(false); expect(api!.settings.audio.muted).toBe(false); expect(api!.settings.dock.side).toBe('right'); }); it('updates only the targeted slice, leaving siblings untouched', async () => { await act(async () => root.render(createElement(Probe))); const audioBefore = api!.settings.audio; await act(async () => api!.updateDock({ side: 'left' })); expect(api!.settings.dock.side).toBe('left'); // Audio slice identity is unchanged — a feature never touches another's. expect(api!.settings.audio).toBe(audioBefore); }); it('setPageContextLinked persists the opt-in under the central key', async () => { await act(async () => root.render(createElement(Probe))); await act(async () => api!.setPageContextLinked(true)); await flush(); expect(api!.settings.pageContext.linked).toBe(true); const stored = JSON.parse( window.localStorage.getItem(CHAT_SETTINGS_STORAGE_KEY)!, ); expect(stored.pageContext.linked).toBe(true); }); it('reset restores every slice to defaults', async () => { await act(async () => root.render(createElement(Probe))); await act(async () => { api!.setAudioMuted(true); api!.updateDock({ side: 'left' }); }); await flush(); expect(api!.settings.audio.muted).toBe(true); await act(async () => api!.reset()); expect(api!.settings.audio.muted).toBe(false); expect(api!.settings.dock.side).toBe('right'); }); });