Spaces:
Running
Running
| /** | |
| * 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); | |
| }); | |
| }); | |