/** * Unit tests for RecentModels logic * Validates: Requirements 23.1, 23.2, 23.3, 23.4, 23.5 */ import { describe, it, expect, beforeEach } from 'vitest'; // ─── Pure logic extracted from RecentModels for testability ───────────── const STORAGE_KEY = 'onnx_explorer_recent_models'; const MAX_ITEMS = 5; function loadHistory(storage) { try { const raw = storage.getItem(STORAGE_KEY); if (!raw) return []; const parsed = JSON.parse(raw); return Array.isArray(parsed) ? parsed : []; } catch { return []; } } function saveHistory(storage, entries) { storage.setItem(STORAGE_KEY, JSON.stringify(entries)); } function addEntry(storage, fileName, fileSize) { const entries = loadHistory(storage); const newEntry = { fileName, fileSize: fileSize || 0, uploadTime: Date.now() }; const filtered = entries.filter((e) => e.fileName !== fileName); filtered.unshift(newEntry); const trimmed = filtered.slice(0, MAX_ITEMS); saveHistory(storage, trimmed); return trimmed; } function clearHistory(storage) { storage.removeItem(STORAGE_KEY); } // ─── Simple in-memory localStorage mock ───────────────────────────────── function createMockStorage() { const store = {}; return { getItem(key) { return store[key] ?? null; }, setItem(key, value) { store[key] = String(value); }, removeItem(key) { delete store[key]; }, }; } // ─── Tests ────────────────────────────────────────────────────────────── describe('RecentModels logic', () => { let storage; beforeEach(() => { storage = createMockStorage(); }); it('should return empty array when no history exists', () => { expect(loadHistory(storage)).toEqual([]); }); it('should save and load a single entry', () => { addEntry(storage, 'model.onnx', 1024); const history = loadHistory(storage); expect(history).toHaveLength(1); expect(history[0].fileName).toBe('model.onnx'); expect(history[0].fileSize).toBe(1024); expect(history[0].uploadTime).toBeGreaterThan(0); }); it('should store up to 5 entries maximum', () => { for (let i = 0; i < 7; i++) { addEntry(storage, `model_${i}.onnx`, i * 100); } const history = loadHistory(storage); expect(history).toHaveLength(MAX_ITEMS); // Most recent should be first expect(history[0].fileName).toBe('model_6.onnx'); }); it('should place newest entry first', () => { addEntry(storage, 'first.onnx', 100); addEntry(storage, 'second.onnx', 200); const history = loadHistory(storage); expect(history[0].fileName).toBe('second.onnx'); expect(history[1].fileName).toBe('first.onnx'); }); it('should deduplicate by fileName and move to top', () => { addEntry(storage, 'a.onnx', 100); addEntry(storage, 'b.onnx', 200); addEntry(storage, 'a.onnx', 150); // re-upload same file const history = loadHistory(storage); expect(history).toHaveLength(2); expect(history[0].fileName).toBe('a.onnx'); expect(history[0].fileSize).toBe(150); }); it('should clear all history', () => { addEntry(storage, 'model.onnx', 1024); clearHistory(storage); expect(loadHistory(storage)).toEqual([]); }); it('should handle corrupted localStorage data gracefully', () => { storage.setItem(STORAGE_KEY, 'not-valid-json{{{'); expect(loadHistory(storage)).toEqual([]); }); it('should handle non-array JSON in localStorage', () => { storage.setItem(STORAGE_KEY, JSON.stringify({ foo: 'bar' })); expect(loadHistory(storage)).toEqual([]); }); it('should default fileSize to 0 when not provided', () => { addEntry(storage, 'nosize.onnx', undefined); const history = loadHistory(storage); expect(history[0].fileSize).toBe(0); }); });