import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { readPersistedQueue, writePersistedQueue, clearPersistedQueue } from './persisted'; import type { TrackRef } from '$lib/api/types'; const sampleTrack: TrackRef = { id: 't1', title: 'Foo', album_id: 'al1', album_title: 'Baz', artist_id: 'ar1', artist_name: 'Bar', duration_sec: 200, stream_url: '/stream/t1' }; describe('persisted queue', () => { beforeEach(() => { localStorage.clear(); }); afterEach(() => { localStorage.clear(); vi.restoreAllMocks(); }); it('write-then-read round-trips queue / index / position', () => { writePersistedQueue('user-1', { queue: [sampleTrack], index: 0, position: 42.5 }); const out = readPersistedQueue('user-1'); expect(out).not.toBeNull(); expect(out!.v).toBe(1); expect(out!.queue).toEqual([sampleTrack]); expect(out!.index).toBe(0); expect(out!.position).toBe(42.5); expect(typeof out!.savedAt).toBe('number'); }); it('read returns null when no entry is set', () => { expect(readPersistedQueue('user-1')).toBeNull(); }); it('read returns null on malformed JSON', () => { localStorage.setItem('minstrel.queue.user-1', '{not-json'); expect(readPersistedQueue('user-1')).toBeNull(); }); it('read returns null when version is not 1', () => { localStorage.setItem( 'minstrel.queue.user-1', JSON.stringify({ v: 2, queue: [], index: 0, position: 0, savedAt: 0 }) ); expect(readPersistedQueue('user-1')).toBeNull(); }); it('clearPersistedQueue removes only the named user key', () => { writePersistedQueue('user-a', { queue: [sampleTrack], index: 0, position: 0 }); writePersistedQueue('user-b', { queue: [sampleTrack], index: 0, position: 0 }); clearPersistedQueue('user-a'); expect(readPersistedQueue('user-a')).toBeNull(); expect(readPersistedQueue('user-b')).not.toBeNull(); }); it('write swallows QuotaExceededError without throwing', () => { const setItem = vi.spyOn(Storage.prototype, 'setItem').mockImplementation(() => { throw new Error('QuotaExceededError'); }); expect(() => writePersistedQueue('user-1', { queue: [sampleTrack], index: 0, position: 0 }) ).not.toThrow(); setItem.mockRestore(); }); });