/** * Tests for the localStorage-backed model selection persistence helper. * jsdom provides a real (per-test-class) localStorage. */ import { clearModelSelection, loadModelSelection, saveModelSelection } from '../components/model_selection'; describe('loadModelSelection', () => { beforeEach(() => { localStorage.clear(); }); it('returns null when no entry exists', () => { expect(loadModelSelection('foo.ipynb')).toBeNull(); }); it('returns null for an empty notebookPath (defensive)', () => { expect(loadModelSelection('')).toBeNull(); }); it('returns the parsed entry when storage is valid', () => { localStorage.setItem( 'opencode_bridge:model-selection:foo.ipynb', JSON.stringify({ providerId: 'anthropic', modelId: 'claude-sonnet-4-20250514' }) ); expect(loadModelSelection('foo.ipynb')).toEqual({ providerId: 'anthropic', modelId: 'claude-sonnet-4-20250514' }); }); it('returns null for malformed JSON (does not throw)', () => { localStorage.setItem( 'opencode_bridge:model-selection:foo.ipynb', '{not json' ); expect(loadModelSelection('foo.ipynb')).toBeNull(); }); it('returns null when the entry is missing required fields', () => { localStorage.setItem( 'opencode_bridge:model-selection:foo.ipynb', JSON.stringify({ providerId: 'anthropic' }) ); expect(loadModelSelection('foo.ipynb')).toBeNull(); }); it('keys entries independently per notebookPath', () => { saveModelSelection('a.ipynb', { providerId: 'p1', modelId: 'm1' }); saveModelSelection('b.ipynb', { providerId: 'p2', modelId: 'm2' }); expect(loadModelSelection('a.ipynb')).toEqual({ providerId: 'p1', modelId: 'm1' }); expect(loadModelSelection('b.ipynb')).toEqual({ providerId: 'p2', modelId: 'm2' }); }); }); describe('saveModelSelection + clearModelSelection', () => { beforeEach(() => { localStorage.clear(); }); it('writes a JSON entry that can be re-read', () => { saveModelSelection('foo.ipynb', { providerId: 'p1', modelId: 'm1' }); expect(loadModelSelection('foo.ipynb')).toEqual({ providerId: 'p1', modelId: 'm1' }); }); it('overwrites an existing entry', () => { saveModelSelection('foo.ipynb', { providerId: 'p1', modelId: 'm1' }); saveModelSelection('foo.ipynb', { providerId: 'p2', modelId: 'm2' }); expect(loadModelSelection('foo.ipynb')).toEqual({ providerId: 'p2', modelId: 'm2' }); }); it('clearModelSelection removes the entry', () => { saveModelSelection('foo.ipynb', { providerId: 'p1', modelId: 'm1' }); clearModelSelection('foo.ipynb'); expect(loadModelSelection('foo.ipynb')).toBeNull(); }); it('no-op for an empty notebookPath (defensive)', () => { expect(() => saveModelSelection('', { providerId: 'p1', modelId: 'm1' }) ).not.toThrow(); expect(() => clearModelSelection('')).not.toThrow(); }); });