import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { loadPanelLayout, savePanelLayout } from './ux-prefs'; const KEY = 'astrolabe:ux-prefs'; /** In-memory localStorage stub (Node's global one is non-functional). */ function makeStorageStub() { const map = new Map(); return { getItem: (k: string) => (map.has(k) ? map.get(k)! : null), setItem: (k: string, v: string) => void map.set(k, String(v)), removeItem: (k: string) => void map.delete(k), clear: () => map.clear(), key: (i: number) => [...map.keys()][i] ?? null, get length() { return map.size; }, }; } describe('ux-prefs ยท panelLayout', () => { beforeEach(() => vi.stubGlobal('localStorage', makeStorageStub())); afterEach(() => vi.unstubAllGlobals()); it('returns empty widths when nothing is stored', () => { expect(loadPanelLayout()).toEqual({ libraryWidth: undefined, previewWidth: undefined }); }); it('round-trips stored widths', () => { savePanelLayout({ libraryWidth: 300, previewWidth: 420 }); expect(loadPanelLayout()).toEqual({ libraryWidth: 300, previewWidth: 420 }); }); it('merges partial writes without dropping the other width', () => { savePanelLayout({ libraryWidth: 300, previewWidth: 420 }); savePanelLayout({ libraryWidth: 250 }); expect(loadPanelLayout()).toEqual({ libraryWidth: 250, previewWidth: 420 }); }); it('rejects non-positive / non-finite junk', () => { localStorage.setItem( KEY, JSON.stringify({ panelLayout: { libraryWidth: -5, previewWidth: 'wide' } }), ); expect(loadPanelLayout()).toEqual({ libraryWidth: undefined, previewWidth: undefined }); }); it('tolerates malformed JSON', () => { localStorage.setItem(KEY, '{ not json'); expect(loadPanelLayout()).toEqual({ libraryWidth: undefined, previewWidth: undefined }); }); it('preserves unrelated keys in the record (forward-compatible merge)', () => { localStorage.setItem(KEY, JSON.stringify({ sort: { sortBy: 'name', sortOrder: 'asc' } })); savePanelLayout({ libraryWidth: 260 }); const stored = JSON.parse(localStorage.getItem(KEY)!) as { sort: { sortBy: string }; panelLayout: { libraryWidth: number }; }; expect(stored.sort.sortBy).toBe('name'); expect(stored.panelLayout.libraryWidth).toBe(260); }); });