@skillsmith/core 2.0.2 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/analytics/AnalyticsRepository.d.ts +4 -0
- package/dist/src/analytics/AnalyticsRepository.d.ts.map +1 -1
- package/dist/src/analytics/AnalyticsRepository.js +26 -44
- package/dist/src/analytics/AnalyticsRepository.js.map +1 -1
- package/dist/src/api/client.d.ts +8 -8
- package/dist/src/api/client.d.ts.map +1 -1
- package/dist/src/api/client.js +2 -2
- package/dist/src/api/client.js.map +1 -1
- package/dist/src/db/schema.d.ts +1 -1
- package/dist/src/db/schema.d.ts.map +1 -1
- package/dist/src/db/schema.js +41 -1
- package/dist/src/db/schema.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/repositories/SyncConfigRepository.d.ts +91 -0
- package/dist/src/repositories/SyncConfigRepository.d.ts.map +1 -0
- package/dist/src/repositories/SyncConfigRepository.js +202 -0
- package/dist/src/repositories/SyncConfigRepository.js.map +1 -0
- package/dist/src/repositories/SyncHistoryRepository.d.ts +104 -0
- package/dist/src/repositories/SyncHistoryRepository.d.ts.map +1 -0
- package/dist/src/repositories/SyncHistoryRepository.js +235 -0
- package/dist/src/repositories/SyncHistoryRepository.js.map +1 -0
- package/dist/src/scripts/github-import/github-client.d.ts +24 -0
- package/dist/src/scripts/github-import/github-client.d.ts.map +1 -1
- package/dist/src/scripts/github-import/github-client.js +103 -0
- package/dist/src/scripts/github-import/github-client.js.map +1 -1
- package/dist/src/scripts/github-import/index.js +3 -10
- package/dist/src/scripts/github-import/index.js.map +1 -1
- package/dist/src/scripts/merge-skills.d.ts +56 -0
- package/dist/src/scripts/merge-skills.d.ts.map +1 -0
- package/dist/src/scripts/merge-skills.js +411 -0
- package/dist/src/scripts/merge-skills.js.map +1 -0
- package/dist/src/scripts/skill-scanner/index.d.ts +9 -2
- package/dist/src/scripts/skill-scanner/index.d.ts.map +1 -1
- package/dist/src/scripts/skill-scanner/index.js +98 -7
- package/dist/src/scripts/skill-scanner/index.js.map +1 -1
- package/dist/src/scripts/skill-scanner/logger.d.ts +51 -0
- package/dist/src/scripts/skill-scanner/logger.d.ts.map +1 -1
- package/dist/src/scripts/skill-scanner/logger.js +255 -1
- package/dist/src/scripts/skill-scanner/logger.js.map +1 -1
- package/dist/src/scripts/skill-scanner/reporter.d.ts +1 -1
- package/dist/src/scripts/skill-scanner/reporter.d.ts.map +1 -1
- package/dist/src/scripts/skill-scanner/reporter.js +67 -15
- package/dist/src/scripts/skill-scanner/reporter.js.map +1 -1
- package/dist/src/scripts/skill-scanner/scanner.d.ts +5 -2
- package/dist/src/scripts/skill-scanner/scanner.d.ts.map +1 -1
- package/dist/src/scripts/skill-scanner/scanner.js +156 -39
- package/dist/src/scripts/skill-scanner/scanner.js.map +1 -1
- package/dist/src/scripts/skill-scanner/types.d.ts +44 -0
- package/dist/src/scripts/skill-scanner/types.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.d.ts +2 -0
- package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.js +51 -2
- package/dist/src/security/scanner/SecurityScanner.js.map +1 -1
- package/dist/src/sync/BackgroundSyncService.d.ts +90 -0
- package/dist/src/sync/BackgroundSyncService.d.ts.map +1 -0
- package/dist/src/sync/BackgroundSyncService.js +214 -0
- package/dist/src/sync/BackgroundSyncService.js.map +1 -0
- package/dist/src/sync/SyncEngine.d.ts +76 -0
- package/dist/src/sync/SyncEngine.d.ts.map +1 -0
- package/dist/src/sync/SyncEngine.js +284 -0
- package/dist/src/sync/SyncEngine.js.map +1 -0
- package/dist/src/sync/index.d.ts +11 -0
- package/dist/src/sync/index.d.ts.map +1 -0
- package/dist/src/sync/index.js +14 -0
- package/dist/src/sync/index.js.map +1 -0
- package/dist/src/types.d.ts +3 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/tests/security/ContinuousSecurity.test.js +10 -12
- package/dist/tests/security/ContinuousSecurity.test.js.map +1 -1
- package/dist/tests/sync/SyncConfigRepository.test.d.ts +7 -0
- package/dist/tests/sync/SyncConfigRepository.test.d.ts.map +1 -0
- package/dist/tests/sync/SyncConfigRepository.test.js +154 -0
- package/dist/tests/sync/SyncConfigRepository.test.js.map +1 -0
- package/dist/tests/sync/SyncEngine.test.d.ts +7 -0
- package/dist/tests/sync/SyncEngine.test.d.ts.map +1 -0
- package/dist/tests/sync/SyncEngine.test.js +300 -0
- package/dist/tests/sync/SyncEngine.test.js.map +1 -0
- package/dist/tests/sync/SyncHistoryRepository.test.d.ts +7 -0
- package/dist/tests/sync/SyncHistoryRepository.test.d.ts.map +1 -0
- package/dist/tests/sync/SyncHistoryRepository.test.js +220 -0
- package/dist/tests/sync/SyncHistoryRepository.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SyncEngine Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for the core sync engine with mocked dependencies.
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
|
|
7
|
+
import { createDatabase, closeDatabase } from '../../src/db/schema.js';
|
|
8
|
+
import { SyncConfigRepository } from '../../src/repositories/SyncConfigRepository.js';
|
|
9
|
+
import { SyncHistoryRepository } from '../../src/repositories/SyncHistoryRepository.js';
|
|
10
|
+
import { SkillRepository } from '../../src/repositories/SkillRepository.js';
|
|
11
|
+
import { SyncEngine } from '../../src/sync/SyncEngine.js';
|
|
12
|
+
/**
|
|
13
|
+
* Create a mock skill for testing
|
|
14
|
+
* Note: quality_score must be between 0 and 1 (database constraint)
|
|
15
|
+
*/
|
|
16
|
+
function createMockSkill(id, updatedAt = new Date().toISOString()) {
|
|
17
|
+
return {
|
|
18
|
+
id,
|
|
19
|
+
name: `Skill ${id}`,
|
|
20
|
+
description: `Description for ${id}`,
|
|
21
|
+
author: 'test-author',
|
|
22
|
+
repo_url: `https://github.com/test/${id}`,
|
|
23
|
+
quality_score: 0.85, // Must be 0-1 range (database constraint)
|
|
24
|
+
trust_tier: 'community',
|
|
25
|
+
tags: ['test'],
|
|
26
|
+
stars: 50,
|
|
27
|
+
installable: true,
|
|
28
|
+
created_at: updatedAt,
|
|
29
|
+
updated_at: updatedAt,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Create a mock API client with customizable behavior
|
|
34
|
+
*/
|
|
35
|
+
function createMockApiClient(config = {}) {
|
|
36
|
+
const { offline = false, healthStatus = 'healthy', skills = [], throwOnSearch } = config;
|
|
37
|
+
const searchMock = vi.fn().mockImplementation(async ({ limit = 100, offset = 0 }) => {
|
|
38
|
+
if (throwOnSearch) {
|
|
39
|
+
throw throwOnSearch;
|
|
40
|
+
}
|
|
41
|
+
const pageSkills = skills.slice(offset, offset + limit);
|
|
42
|
+
return {
|
|
43
|
+
data: pageSkills,
|
|
44
|
+
total: skills.length,
|
|
45
|
+
limit,
|
|
46
|
+
offset,
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
isOffline: vi.fn().mockReturnValue(offline),
|
|
51
|
+
checkHealth: vi.fn().mockResolvedValue({ status: healthStatus }),
|
|
52
|
+
search: searchMock,
|
|
53
|
+
getSkill: vi.fn(),
|
|
54
|
+
getHealthStatus: vi.fn(),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
describe('SyncEngine', () => {
|
|
58
|
+
let db;
|
|
59
|
+
let syncConfigRepo;
|
|
60
|
+
let syncHistoryRepo;
|
|
61
|
+
let skillRepo;
|
|
62
|
+
beforeEach(() => {
|
|
63
|
+
db = createDatabase(':memory:');
|
|
64
|
+
syncConfigRepo = new SyncConfigRepository(db);
|
|
65
|
+
syncHistoryRepo = new SyncHistoryRepository(db);
|
|
66
|
+
skillRepo = new SkillRepository(db);
|
|
67
|
+
});
|
|
68
|
+
afterEach(() => {
|
|
69
|
+
closeDatabase(db);
|
|
70
|
+
});
|
|
71
|
+
describe('constructor', () => {
|
|
72
|
+
it('should create sync engine with all dependencies', () => {
|
|
73
|
+
const apiClient = createMockApiClient();
|
|
74
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
75
|
+
expect(engine).toBeDefined();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
describe('sync - offline and health checks', () => {
|
|
79
|
+
it('should fail when API client is offline', async () => {
|
|
80
|
+
const apiClient = createMockApiClient({ offline: true });
|
|
81
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
82
|
+
const result = await engine.sync();
|
|
83
|
+
expect(result.success).toBe(false);
|
|
84
|
+
expect(result.errors).toContain('API client is in offline mode. Cannot sync.');
|
|
85
|
+
});
|
|
86
|
+
it('should fail when API health check fails', async () => {
|
|
87
|
+
const apiClient = createMockApiClient({ healthStatus: 'unhealthy' });
|
|
88
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
89
|
+
const result = await engine.sync();
|
|
90
|
+
expect(result.success).toBe(false);
|
|
91
|
+
expect(result.errors).toContain('API is unhealthy. Try again later.');
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
describe('sync - basic functionality', () => {
|
|
95
|
+
it('should successfully sync skills from API', async () => {
|
|
96
|
+
const skills = [
|
|
97
|
+
createMockSkill('test/skill-1'),
|
|
98
|
+
createMockSkill('test/skill-2'),
|
|
99
|
+
createMockSkill('test/skill-3'),
|
|
100
|
+
];
|
|
101
|
+
const apiClient = createMockApiClient({ skills });
|
|
102
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
103
|
+
const result = await engine.sync();
|
|
104
|
+
expect(result.success).toBe(true);
|
|
105
|
+
expect(result.skillsAdded).toBe(3);
|
|
106
|
+
expect(result.skillsUpdated).toBe(0);
|
|
107
|
+
expect(result.skillsUnchanged).toBe(0);
|
|
108
|
+
expect(result.totalProcessed).toBe(3);
|
|
109
|
+
expect(result.errors).toHaveLength(0);
|
|
110
|
+
});
|
|
111
|
+
it('should detect updates to existing skills', async () => {
|
|
112
|
+
// Pre-populate database with a skill
|
|
113
|
+
skillRepo.create({
|
|
114
|
+
id: 'test/skill-1',
|
|
115
|
+
name: 'Old Name',
|
|
116
|
+
trustTier: 'community',
|
|
117
|
+
tags: ['old'],
|
|
118
|
+
});
|
|
119
|
+
// API returns updated version with new updated_at
|
|
120
|
+
const skills = [createMockSkill('test/skill-1', new Date(Date.now() + 1000).toISOString())];
|
|
121
|
+
const apiClient = createMockApiClient({ skills });
|
|
122
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
123
|
+
const result = await engine.sync();
|
|
124
|
+
expect(result.success).toBe(true);
|
|
125
|
+
expect(result.skillsAdded).toBe(0);
|
|
126
|
+
expect(result.skillsUpdated).toBe(1);
|
|
127
|
+
});
|
|
128
|
+
it('should skip unchanged skills when timestamps match', async () => {
|
|
129
|
+
const timestamp = new Date().toISOString();
|
|
130
|
+
// Pre-populate database with a skill
|
|
131
|
+
skillRepo.create({
|
|
132
|
+
id: 'test/skill-1',
|
|
133
|
+
name: 'Skill test/skill-1',
|
|
134
|
+
trustTier: 'community',
|
|
135
|
+
tags: ['test'],
|
|
136
|
+
});
|
|
137
|
+
// Manually set the same timestamp as what API will return
|
|
138
|
+
db.prepare('UPDATE skills SET updated_at = ? WHERE id = ?').run(timestamp, 'test/skill-1');
|
|
139
|
+
// API returns skill with same timestamp
|
|
140
|
+
const skills = [createMockSkill('test/skill-1', timestamp)];
|
|
141
|
+
const apiClient = createMockApiClient({ skills });
|
|
142
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
143
|
+
const result = await engine.sync();
|
|
144
|
+
expect(result.success).toBe(true);
|
|
145
|
+
expect(result.skillsUnchanged).toBe(1);
|
|
146
|
+
expect(result.skillsUpdated).toBe(0);
|
|
147
|
+
expect(result.skillsAdded).toBe(0);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
describe('sync - differential sync', () => {
|
|
151
|
+
it('should perform differential sync when lastSyncAt exists', async () => {
|
|
152
|
+
// Set last sync to 1 hour ago
|
|
153
|
+
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000);
|
|
154
|
+
syncConfigRepo.setLastSync(oneHourAgo.toISOString(), 0);
|
|
155
|
+
// Create skills: one old (before lastSync), one new (after lastSync)
|
|
156
|
+
const oldSkill = createMockSkill('test/old-skill', new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString());
|
|
157
|
+
const newSkill = createMockSkill('test/new-skill', new Date().toISOString());
|
|
158
|
+
const apiClient = createMockApiClient({ skills: [oldSkill, newSkill] });
|
|
159
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
160
|
+
const result = await engine.sync();
|
|
161
|
+
expect(result.success).toBe(true);
|
|
162
|
+
// Only the new skill should be added (old one filtered out by differential)
|
|
163
|
+
expect(result.skillsAdded).toBe(1);
|
|
164
|
+
expect(result.totalProcessed).toBe(2); // Both fetched
|
|
165
|
+
});
|
|
166
|
+
it('should perform full sync with force option', async () => {
|
|
167
|
+
// Set last sync recently
|
|
168
|
+
const now = new Date().toISOString();
|
|
169
|
+
syncConfigRepo.setLastSync(now, 0);
|
|
170
|
+
// Create skills with old timestamps that would normally be filtered
|
|
171
|
+
const skills = [
|
|
172
|
+
createMockSkill('test/skill-1', new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString()),
|
|
173
|
+
createMockSkill('test/skill-2', new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString()),
|
|
174
|
+
];
|
|
175
|
+
const apiClient = createMockApiClient({ skills });
|
|
176
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
177
|
+
const result = await engine.sync({ force: true });
|
|
178
|
+
expect(result.success).toBe(true);
|
|
179
|
+
expect(result.skillsAdded).toBe(2); // All skills processed because force=true
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
describe('sync - dry run', () => {
|
|
183
|
+
it('should not modify database in dry run mode', async () => {
|
|
184
|
+
const skills = [createMockSkill('test/skill-1')];
|
|
185
|
+
const apiClient = createMockApiClient({ skills });
|
|
186
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
187
|
+
const result = await engine.sync({ dryRun: true });
|
|
188
|
+
expect(result.success).toBe(true);
|
|
189
|
+
expect(result.dryRun).toBe(true);
|
|
190
|
+
expect(result.skillsAdded).toBe(1);
|
|
191
|
+
// Verify skill was NOT actually added
|
|
192
|
+
const skill = skillRepo.findById('test/skill-1');
|
|
193
|
+
expect(skill).toBeNull();
|
|
194
|
+
// Verify no history entry was created
|
|
195
|
+
const history = syncHistoryRepo.getHistory();
|
|
196
|
+
expect(history).toHaveLength(0);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
describe('sync - progress callback', () => {
|
|
200
|
+
it('should call onProgress callback with phases', async () => {
|
|
201
|
+
const skills = [createMockSkill('test/skill-1')];
|
|
202
|
+
const apiClient = createMockApiClient({ skills });
|
|
203
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
204
|
+
const progressCalls = [];
|
|
205
|
+
const onProgress = vi.fn((progress) => {
|
|
206
|
+
progressCalls.push(progress.phase);
|
|
207
|
+
});
|
|
208
|
+
await engine.sync({ onProgress });
|
|
209
|
+
expect(onProgress).toHaveBeenCalled();
|
|
210
|
+
expect(progressCalls).toContain('connecting');
|
|
211
|
+
expect(progressCalls).toContain('fetching');
|
|
212
|
+
expect(progressCalls).toContain('comparing');
|
|
213
|
+
// upserting and complete should be called for successful sync with skills
|
|
214
|
+
expect(progressCalls.some((p) => p === 'upserting' || p === 'complete')).toBe(true);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
describe('sync - pagination', () => {
|
|
218
|
+
it('should handle pagination correctly', async () => {
|
|
219
|
+
// Create 150 skills (more than one page of 100)
|
|
220
|
+
const skills = Array.from({ length: 150 }, (_, i) => createMockSkill(`test/skill-${i}`));
|
|
221
|
+
const apiClient = createMockApiClient({ skills });
|
|
222
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
223
|
+
const result = await engine.sync({ pageSize: 100 });
|
|
224
|
+
expect(result.success).toBe(true);
|
|
225
|
+
expect(result.skillsAdded).toBe(150);
|
|
226
|
+
expect(result.totalProcessed).toBe(150);
|
|
227
|
+
// SyncEngine uses 8 different search queries to cover more skills
|
|
228
|
+
// Each query paginates through results: 8 queries × 2 pages (100 + 50) = 16 calls
|
|
229
|
+
// Skills are deduplicated across queries
|
|
230
|
+
expect(apiClient.search).toHaveBeenCalledTimes(16);
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
describe('sync - history tracking', () => {
|
|
234
|
+
it('should record sync history on success', async () => {
|
|
235
|
+
const skills = [createMockSkill('test/skill-1')];
|
|
236
|
+
const apiClient = createMockApiClient({ skills });
|
|
237
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
238
|
+
await engine.sync();
|
|
239
|
+
const history = syncHistoryRepo.getHistory();
|
|
240
|
+
expect(history).toHaveLength(1);
|
|
241
|
+
expect(history[0].status).toBe('success');
|
|
242
|
+
expect(history[0].skillsAdded).toBe(1);
|
|
243
|
+
});
|
|
244
|
+
it('should record sync history on failure', async () => {
|
|
245
|
+
const apiClient = createMockApiClient({
|
|
246
|
+
throwOnSearch: new Error('Network failure'),
|
|
247
|
+
});
|
|
248
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
249
|
+
await engine.sync();
|
|
250
|
+
const history = syncHistoryRepo.getHistory();
|
|
251
|
+
expect(history).toHaveLength(1);
|
|
252
|
+
expect(history[0].status).toBe('failed');
|
|
253
|
+
expect(history[0].errorMessage).toContain('Network failure');
|
|
254
|
+
});
|
|
255
|
+
it('should update sync config on success', async () => {
|
|
256
|
+
const skills = [createMockSkill('test/skill-1')];
|
|
257
|
+
const apiClient = createMockApiClient({ skills });
|
|
258
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
259
|
+
await engine.sync();
|
|
260
|
+
const config = syncConfigRepo.getConfig();
|
|
261
|
+
expect(config.lastSyncAt).not.toBeNull();
|
|
262
|
+
expect(config.lastSyncCount).toBe(1);
|
|
263
|
+
expect(config.lastSyncError).toBeNull();
|
|
264
|
+
});
|
|
265
|
+
it('should set error in config on failure', async () => {
|
|
266
|
+
const apiClient = createMockApiClient({ offline: true });
|
|
267
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
268
|
+
await engine.sync();
|
|
269
|
+
const config = syncConfigRepo.getConfig();
|
|
270
|
+
expect(config.lastSyncError).toBe('API client is in offline mode. Cannot sync.');
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
describe('getStatus', () => {
|
|
274
|
+
it('should return sync status summary', () => {
|
|
275
|
+
const apiClient = createMockApiClient();
|
|
276
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
277
|
+
const status = engine.getStatus();
|
|
278
|
+
expect(status).toHaveProperty('config');
|
|
279
|
+
expect(status).toHaveProperty('lastRun');
|
|
280
|
+
expect(status).toHaveProperty('isRunning');
|
|
281
|
+
expect(status).toHaveProperty('isDue');
|
|
282
|
+
});
|
|
283
|
+
it('should show sync is due when never synced', () => {
|
|
284
|
+
const apiClient = createMockApiClient();
|
|
285
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
286
|
+
const status = engine.getStatus();
|
|
287
|
+
expect(status.isDue).toBe(true);
|
|
288
|
+
expect(status.lastRun).toBeNull();
|
|
289
|
+
});
|
|
290
|
+
it('should reflect running state', async () => {
|
|
291
|
+
const apiClient = createMockApiClient();
|
|
292
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
293
|
+
// Start a run manually
|
|
294
|
+
syncHistoryRepo.startRun();
|
|
295
|
+
const status = engine.getStatus();
|
|
296
|
+
expect(status.isRunning).toBe(true);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
//# sourceMappingURL=SyncEngine.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SyncEngine.test.js","sourceRoot":"","sources":["../../../tests/sync/SyncEngine.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SyncHistoryRepository.test.d.ts","sourceRoot":"","sources":["../../../tests/sync/SyncHistoryRepository.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SyncHistoryRepository Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for sync history tracking.
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import { createDatabase, closeDatabase } from '../../src/db/schema.js';
|
|
8
|
+
import { SyncHistoryRepository } from '../../src/repositories/SyncHistoryRepository.js';
|
|
9
|
+
describe('SyncHistoryRepository', () => {
|
|
10
|
+
let db;
|
|
11
|
+
let repo;
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
db = createDatabase(':memory:');
|
|
14
|
+
repo = new SyncHistoryRepository(db);
|
|
15
|
+
});
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
closeDatabase(db);
|
|
18
|
+
});
|
|
19
|
+
describe('startRun', () => {
|
|
20
|
+
it('should create a new run with running status', () => {
|
|
21
|
+
const runId = repo.startRun();
|
|
22
|
+
expect(runId).toMatch(/^sync-\d{14}-[a-z0-9]+$/);
|
|
23
|
+
const entry = repo.getById(runId);
|
|
24
|
+
expect(entry).not.toBeNull();
|
|
25
|
+
expect(entry.status).toBe('running');
|
|
26
|
+
expect(entry.startedAt).toBeTruthy();
|
|
27
|
+
expect(entry.completedAt).toBeNull();
|
|
28
|
+
});
|
|
29
|
+
it('should generate unique IDs', () => {
|
|
30
|
+
const id1 = repo.startRun();
|
|
31
|
+
const id2 = repo.startRun();
|
|
32
|
+
expect(id1).not.toBe(id2);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe('completeRun', () => {
|
|
36
|
+
it('should mark run as success with results', () => {
|
|
37
|
+
const runId = repo.startRun();
|
|
38
|
+
repo.completeRun(runId, {
|
|
39
|
+
skillsAdded: 10,
|
|
40
|
+
skillsUpdated: 5,
|
|
41
|
+
skillsUnchanged: 100,
|
|
42
|
+
});
|
|
43
|
+
const entry = repo.getById(runId);
|
|
44
|
+
expect(entry.status).toBe('success');
|
|
45
|
+
expect(entry.skillsAdded).toBe(10);
|
|
46
|
+
expect(entry.skillsUpdated).toBe(5);
|
|
47
|
+
expect(entry.skillsUnchanged).toBe(100);
|
|
48
|
+
expect(entry.completedAt).toBeTruthy();
|
|
49
|
+
expect(entry.durationMs).toBeGreaterThanOrEqual(0);
|
|
50
|
+
});
|
|
51
|
+
it('should throw if run not found', () => {
|
|
52
|
+
expect(() => {
|
|
53
|
+
repo.completeRun('nonexistent-id', {
|
|
54
|
+
skillsAdded: 0,
|
|
55
|
+
skillsUpdated: 0,
|
|
56
|
+
skillsUnchanged: 0,
|
|
57
|
+
});
|
|
58
|
+
}).toThrow('Sync run not found');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe('completeRunPartial', () => {
|
|
62
|
+
it('should mark run as partial with error message', () => {
|
|
63
|
+
const runId = repo.startRun();
|
|
64
|
+
repo.completeRunPartial(runId, { skillsAdded: 5, skillsUpdated: 2, skillsUnchanged: 50 }, 'Some skills failed to sync');
|
|
65
|
+
const entry = repo.getById(runId);
|
|
66
|
+
expect(entry.status).toBe('partial');
|
|
67
|
+
expect(entry.errorMessage).toBe('Some skills failed to sync');
|
|
68
|
+
expect(entry.skillsAdded).toBe(5);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('failRun', () => {
|
|
72
|
+
it('should mark run as failed with error', () => {
|
|
73
|
+
const runId = repo.startRun();
|
|
74
|
+
repo.failRun(runId, 'Connection timeout');
|
|
75
|
+
const entry = repo.getById(runId);
|
|
76
|
+
expect(entry.status).toBe('failed');
|
|
77
|
+
expect(entry.errorMessage).toBe('Connection timeout');
|
|
78
|
+
expect(entry.completedAt).toBeTruthy();
|
|
79
|
+
});
|
|
80
|
+
it('should throw if run not found', () => {
|
|
81
|
+
expect(() => {
|
|
82
|
+
repo.failRun('nonexistent-id', 'error');
|
|
83
|
+
}).toThrow('Sync run not found');
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe('getById', () => {
|
|
87
|
+
it('should return entry by ID', () => {
|
|
88
|
+
const runId = repo.startRun();
|
|
89
|
+
const entry = repo.getById(runId);
|
|
90
|
+
expect(entry).not.toBeNull();
|
|
91
|
+
expect(entry.id).toBe(runId);
|
|
92
|
+
});
|
|
93
|
+
it('should return null for nonexistent ID', () => {
|
|
94
|
+
const entry = repo.getById('nonexistent');
|
|
95
|
+
expect(entry).toBeNull();
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
describe('getHistory', () => {
|
|
99
|
+
it('should return empty array if no history', () => {
|
|
100
|
+
const history = repo.getHistory();
|
|
101
|
+
expect(history).toEqual([]);
|
|
102
|
+
});
|
|
103
|
+
it('should return entries in reverse chronological order', () => {
|
|
104
|
+
// Create first run with older timestamp
|
|
105
|
+
const id1 = repo.startRun();
|
|
106
|
+
repo.completeRun(id1, { skillsAdded: 1, skillsUpdated: 0, skillsUnchanged: 0 });
|
|
107
|
+
// Manually adjust timestamp to ensure ordering
|
|
108
|
+
const oneSecondAgo = new Date(Date.now() - 1000).toISOString();
|
|
109
|
+
db.prepare('UPDATE sync_history SET started_at = ? WHERE id = ?').run(oneSecondAgo, id1);
|
|
110
|
+
const id2 = repo.startRun();
|
|
111
|
+
repo.completeRun(id2, { skillsAdded: 2, skillsUpdated: 0, skillsUnchanged: 0 });
|
|
112
|
+
const history = repo.getHistory();
|
|
113
|
+
expect(history.length).toBe(2);
|
|
114
|
+
expect(history[0].skillsAdded).toBe(2); // Most recent first
|
|
115
|
+
expect(history[1].skillsAdded).toBe(1);
|
|
116
|
+
});
|
|
117
|
+
it('should respect limit parameter', () => {
|
|
118
|
+
for (let i = 0; i < 5; i++) {
|
|
119
|
+
const id = repo.startRun();
|
|
120
|
+
repo.completeRun(id, { skillsAdded: i, skillsUpdated: 0, skillsUnchanged: 0 });
|
|
121
|
+
}
|
|
122
|
+
const history = repo.getHistory(3);
|
|
123
|
+
expect(history.length).toBe(3);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
describe('getLastSuccessful', () => {
|
|
127
|
+
it('should return null if no successful runs', () => {
|
|
128
|
+
const id = repo.startRun();
|
|
129
|
+
repo.failRun(id, 'error');
|
|
130
|
+
expect(repo.getLastSuccessful()).toBeNull();
|
|
131
|
+
});
|
|
132
|
+
it('should return last successful run', () => {
|
|
133
|
+
const id1 = repo.startRun();
|
|
134
|
+
repo.completeRun(id1, { skillsAdded: 10, skillsUpdated: 0, skillsUnchanged: 0 });
|
|
135
|
+
const id2 = repo.startRun();
|
|
136
|
+
repo.failRun(id2, 'error');
|
|
137
|
+
const last = repo.getLastSuccessful();
|
|
138
|
+
expect(last).not.toBeNull();
|
|
139
|
+
expect(last.id).toBe(id1);
|
|
140
|
+
expect(last.skillsAdded).toBe(10);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
describe('getRunning', () => {
|
|
144
|
+
it('should return empty array if no running', () => {
|
|
145
|
+
expect(repo.getRunning()).toEqual([]);
|
|
146
|
+
});
|
|
147
|
+
it('should return running entries', () => {
|
|
148
|
+
const id1 = repo.startRun();
|
|
149
|
+
const id2 = repo.startRun();
|
|
150
|
+
repo.completeRun(id2, { skillsAdded: 0, skillsUpdated: 0, skillsUnchanged: 0 });
|
|
151
|
+
const running = repo.getRunning();
|
|
152
|
+
expect(running.length).toBe(1);
|
|
153
|
+
expect(running[0].id).toBe(id1);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
describe('isRunning', () => {
|
|
157
|
+
it('should return false if no running syncs', () => {
|
|
158
|
+
expect(repo.isRunning()).toBe(false);
|
|
159
|
+
});
|
|
160
|
+
it('should return true if sync is running', () => {
|
|
161
|
+
repo.startRun();
|
|
162
|
+
expect(repo.isRunning()).toBe(true);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
describe('cleanup', () => {
|
|
166
|
+
it('should remove old entries', () => {
|
|
167
|
+
// Create an entry and manually set old date
|
|
168
|
+
const id = repo.startRun();
|
|
169
|
+
repo.completeRun(id, { skillsAdded: 0, skillsUpdated: 0, skillsUnchanged: 0 });
|
|
170
|
+
// Update started_at to 60 days ago
|
|
171
|
+
const sixtyDaysAgo = new Date();
|
|
172
|
+
sixtyDaysAgo.setDate(sixtyDaysAgo.getDate() - 60);
|
|
173
|
+
db.prepare('UPDATE sync_history SET started_at = ? WHERE id = ?').run(sixtyDaysAgo.toISOString(), id);
|
|
174
|
+
const deleted = repo.cleanup(30);
|
|
175
|
+
expect(deleted).toBe(1);
|
|
176
|
+
expect(repo.getById(id)).toBeNull();
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
describe('count', () => {
|
|
180
|
+
it('should return 0 for empty history', () => {
|
|
181
|
+
expect(repo.count()).toBe(0);
|
|
182
|
+
});
|
|
183
|
+
it('should return correct count', () => {
|
|
184
|
+
repo.startRun();
|
|
185
|
+
repo.startRun();
|
|
186
|
+
repo.startRun();
|
|
187
|
+
expect(repo.count()).toBe(3);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
describe('getStats', () => {
|
|
191
|
+
it('should return zeros for empty history', () => {
|
|
192
|
+
const stats = repo.getStats();
|
|
193
|
+
expect(stats.totalRuns).toBe(0);
|
|
194
|
+
// SQLite SUM returns null for empty sets, which is handled by the implementation
|
|
195
|
+
expect(stats.successfulRuns).toBe(0);
|
|
196
|
+
expect(stats.failedRuns).toBe(0);
|
|
197
|
+
expect(stats.lastSuccessAt).toBeNull();
|
|
198
|
+
expect(stats.averageDurationMs).toBeNull();
|
|
199
|
+
});
|
|
200
|
+
it('should calculate stats correctly', () => {
|
|
201
|
+
// Success
|
|
202
|
+
const id1 = repo.startRun();
|
|
203
|
+
repo.completeRun(id1, { skillsAdded: 10, skillsUpdated: 5, skillsUnchanged: 100 });
|
|
204
|
+
// Success
|
|
205
|
+
const id2 = repo.startRun();
|
|
206
|
+
repo.completeRun(id2, { skillsAdded: 5, skillsUpdated: 2, skillsUnchanged: 50 });
|
|
207
|
+
// Failed
|
|
208
|
+
const id3 = repo.startRun();
|
|
209
|
+
repo.failRun(id3, 'error');
|
|
210
|
+
const stats = repo.getStats();
|
|
211
|
+
expect(stats.totalRuns).toBe(3);
|
|
212
|
+
expect(stats.successfulRuns).toBe(2);
|
|
213
|
+
expect(stats.failedRuns).toBe(1);
|
|
214
|
+
expect(stats.lastSuccessAt).toBeTruthy();
|
|
215
|
+
// averageDurationMs may be 0 or a small positive number
|
|
216
|
+
expect(stats.averageDurationMs === null || stats.averageDurationMs >= 0).toBe(true);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
//# sourceMappingURL=SyncHistoryRepository.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SyncHistoryRepository.test.js","sourceRoot":"","sources":["../../../tests/sync/SyncHistoryRepository.test.ts"],"names":[],"mappings":"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"}
|