import { describe, it, expect, vi, beforeEach } from 'vitest'; // Mock $app/environment vi.mock('$app/environment', () => ({ browser: true })); describe('gradePreferences', () => { beforeEach(() => { localStorage.clear(); vi.resetModules(); }); async function loadModule() { return await import('$lib/features/grades/stores/gradePreferences.svelte'); } // ========================================================================== // Reveal mode (discover vs immediate) // ========================================================================== describe('reveal mode', () => { it('defaults to immediate mode', async () => { const prefs = await loadModule(); expect(prefs.getRevealMode()).toBe('immediate'); expect(prefs.isDiscoverMode()).toBe(false); }); it('switches to discover mode', async () => { const prefs = await loadModule(); prefs.setRevealMode('discover'); expect(prefs.getRevealMode()).toBe('discover'); expect(prefs.isDiscoverMode()).toBe(true); }); it('switches back to immediate mode', async () => { const prefs = await loadModule(); prefs.setRevealMode('discover'); prefs.setRevealMode('immediate'); expect(prefs.getRevealMode()).toBe('immediate'); expect(prefs.isDiscoverMode()).toBe(false); }); it('persists reveal mode to localStorage', async () => { const prefs = await loadModule(); prefs.setRevealMode('discover'); const stored = JSON.parse(localStorage.getItem('classeo_grade_preferences')!); expect(stored.revealMode).toBe('discover'); }); it('restores reveal mode from localStorage on init', async () => { localStorage.setItem( 'classeo_grade_preferences', JSON.stringify({ revealMode: 'discover' }) ); const prefs = await loadModule(); expect(prefs.getRevealMode()).toBe('discover'); expect(prefs.isDiscoverMode()).toBe(true); }); it('handles corrupted localStorage gracefully', async () => { localStorage.setItem('classeo_grade_preferences', 'not-json'); const prefs = await loadModule(); expect(prefs.getRevealMode()).toBe('immediate'); }); }); // ========================================================================== // Grade reveal state (per-grade reveal tracking) // ========================================================================== describe('grade reveal state', () => { it('reports grades as not revealed by default', async () => { const prefs = await loadModule(); expect(prefs.isGradeRevealed('grade-1')).toBe(false); }); it('reveals a grade individually', async () => { const prefs = await loadModule(); prefs.revealGrade('grade-1'); expect(prefs.isGradeRevealed('grade-1')).toBe(true); expect(prefs.isGradeRevealed('grade-2')).toBe(false); }); it('persists revealed grades to localStorage', async () => { const prefs = await loadModule(); prefs.revealGrade('grade-1'); prefs.revealGrade('grade-2'); const stored = JSON.parse(localStorage.getItem('classeo_grades_revealed')!); expect(stored).toContain('grade-1'); expect(stored).toContain('grade-2'); }); it('restores revealed grades from localStorage on init', async () => { localStorage.setItem( 'classeo_grades_revealed', JSON.stringify(['grade-1', 'grade-3']) ); const prefs = await loadModule(); expect(prefs.isGradeRevealed('grade-1')).toBe(true); expect(prefs.isGradeRevealed('grade-3')).toBe(true); expect(prefs.isGradeRevealed('grade-2')).toBe(false); }); it('handles corrupted revealed localStorage gracefully', async () => { localStorage.setItem('classeo_grades_revealed', '{invalid}'); const prefs = await loadModule(); expect(prefs.isGradeRevealed('grade-1')).toBe(false); }); }); // ========================================================================== // Grade "new" badge (seen tracking) // ========================================================================== describe('grade new badge', () => { it('reports unseen grades as new', async () => { const prefs = await loadModule(); expect(prefs.isGradeNew('grade-1')).toBe(true); }); it('marks grades as seen', async () => { const prefs = await loadModule(); prefs.markGradesSeen(['grade-1', 'grade-2']); expect(prefs.isGradeNew('grade-1')).toBe(false); expect(prefs.isGradeNew('grade-2')).toBe(false); expect(prefs.isGradeNew('grade-3')).toBe(true); }); it('persists seen grades to localStorage', async () => { const prefs = await loadModule(); prefs.markGradesSeen(['grade-1']); const stored = JSON.parse(localStorage.getItem('classeo_grades_seen')!); expect(stored).toContain('grade-1'); }); it('restores seen grades from localStorage on init', async () => { localStorage.setItem( 'classeo_grades_seen', JSON.stringify(['grade-1']) ); const prefs = await loadModule(); expect(prefs.isGradeNew('grade-1')).toBe(false); expect(prefs.isGradeNew('grade-2')).toBe(true); }); it('accumulates seen grades across multiple calls', async () => { const prefs = await loadModule(); prefs.markGradesSeen(['grade-1']); prefs.markGradesSeen(['grade-2']); expect(prefs.isGradeNew('grade-1')).toBe(false); expect(prefs.isGradeNew('grade-2')).toBe(false); }); it('handles corrupted seen localStorage gracefully', async () => { localStorage.setItem('classeo_grades_seen', 'broken'); const prefs = await loadModule(); expect(prefs.isGradeNew('grade-1')).toBe(true); }); }); });