File size: 3,977 Bytes
9bd422a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/**
 * 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);
  });
});