mirror of
https://github.com/abort-retry-ignore/joplock.git
synced 2026-04-28 01:49:30 +00:00
130 lines
4.5 KiB
JavaScript
130 lines
4.5 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const { createHistoryService, hashBody } = require('../app/historyService');
|
|
|
|
const makeDb = (rows = [], queries = []) => ({
|
|
query: async (sql, params) => {
|
|
queries.push({ sql, params });
|
|
if (/SELECT.*joplock_history.*LIMIT 1/.test(sql)) return { rows };
|
|
if (/SELECT.*joplock_history/.test(sql) && sql.includes('ORDER BY saved_time')) return { rows };
|
|
return { rows: [] };
|
|
},
|
|
});
|
|
|
|
test('historyService: hashBody produces consistent hash', () => {
|
|
assert.equal(hashBody('hello'), hashBody('hello'));
|
|
assert.notEqual(hashBody('hello'), hashBody('world'));
|
|
});
|
|
|
|
test('historyService: saveSnapshot skips when table unavailable', async () => {
|
|
const service = createHistoryService({
|
|
query: async () => { throw new Error('permission denied'); },
|
|
});
|
|
// should not throw
|
|
await service.saveSnapshot('u1', 'n1', 'Title', 'Body');
|
|
});
|
|
|
|
test('historyService: saveSnapshot inserts first snapshot', async () => {
|
|
const queries = [];
|
|
const service = createHistoryService({
|
|
query: async (sql, params) => {
|
|
queries.push({ sql, params });
|
|
// Most-recent check returns no previous snapshot
|
|
if (sql.includes('SELECT') && sql.includes('LIMIT 1')) return { rows: [] };
|
|
return { rows: [] };
|
|
},
|
|
});
|
|
await service.saveSnapshot('u1', 'n1', 'Title', 'Body text');
|
|
const insert = queries.find(q => q.sql.includes('INSERT INTO joplock_history'));
|
|
assert.ok(insert, 'should insert');
|
|
assert.equal(insert.params[0], 'n1');
|
|
assert.equal(insert.params[1], 'u1');
|
|
assert.equal(insert.params[2], 'Title');
|
|
assert.equal(insert.params[3], 'Body text');
|
|
});
|
|
|
|
test('historyService: saveSnapshot skips identical hash', async () => {
|
|
const queries = [];
|
|
const hash = hashBody('Same body');
|
|
const service = createHistoryService({
|
|
query: async (sql, params) => {
|
|
queries.push({ sql, params });
|
|
if (sql.includes('SELECT') && sql.includes('LIMIT 1')) {
|
|
return { rows: [{ body_hash: hash, saved_time: Date.now() - 60000 }] };
|
|
}
|
|
return { rows: [] };
|
|
},
|
|
});
|
|
await service.saveSnapshot('u1', 'n1', 'Title', 'Same body');
|
|
const insert = queries.find(q => q.sql.includes('INSERT INTO joplock_history'));
|
|
assert.ok(!insert, 'should skip insert when hash identical');
|
|
});
|
|
|
|
test('historyService: saveSnapshot skips when too recent', async () => {
|
|
const queries = [];
|
|
const service = createHistoryService({
|
|
query: async (sql) => {
|
|
queries.push({ sql });
|
|
if (sql.includes('SELECT') && sql.includes('LIMIT 1')) {
|
|
return { rows: [{ body_hash: hashBody('Old body'), saved_time: Date.now() - 5000 }] };
|
|
}
|
|
return { rows: [] };
|
|
},
|
|
});
|
|
await service.saveSnapshot('u1', 'n1', 'Title', 'New body');
|
|
const insert = queries.find(q => q.sql.includes('INSERT INTO joplock_history'));
|
|
assert.ok(!insert, 'should skip when last snapshot was < 30s ago');
|
|
});
|
|
|
|
test('historyService: listSnapshots returns empty array when table unavailable', async () => {
|
|
const service = createHistoryService({
|
|
query: async () => { throw new Error('nope'); },
|
|
});
|
|
const list = await service.listSnapshots('n1');
|
|
assert.deepEqual(list, []);
|
|
});
|
|
|
|
test('historyService: listSnapshots maps rows correctly', async () => {
|
|
const rows = [
|
|
{ id: '5', title: 'My note', saved_time: '1700000000000' },
|
|
{ id: '3', title: 'Earlier', saved_time: '1699000000000' },
|
|
];
|
|
const service = createHistoryService({
|
|
query: async (sql) => {
|
|
if (sql.includes('CREATE')) return { rows: [] };
|
|
if (sql.includes('CREATE INDEX')) return { rows: [] };
|
|
return { rows };
|
|
},
|
|
});
|
|
const list = await service.listSnapshots('n1');
|
|
assert.equal(list.length, 2);
|
|
assert.equal(list[0].id, '5');
|
|
assert.equal(list[0].title, 'My note');
|
|
assert.equal(list[0].savedTime, 1700000000000);
|
|
});
|
|
|
|
test('historyService: getSnapshot returns null when not found', async () => {
|
|
const service = createHistoryService({
|
|
query: async (sql) => {
|
|
if (sql.includes('CREATE')) return { rows: [] };
|
|
return { rows: [] };
|
|
},
|
|
});
|
|
const snap = await service.getSnapshot('999');
|
|
assert.equal(snap, null);
|
|
});
|
|
|
|
test('historyService: getSnapshot returns snapshot with body', async () => {
|
|
const service = createHistoryService({
|
|
query: async (sql) => {
|
|
if (sql.includes('CREATE')) return { rows: [] };
|
|
return { rows: [{ id: '7', note_id: 'note-abc', title: 'Hi', body: 'Hello world', saved_time: '1700000000000' }] };
|
|
},
|
|
});
|
|
const snap = await service.getSnapshot('7');
|
|
assert.ok(snap);
|
|
assert.equal(snap.id, '7');
|
|
assert.equal(snap.noteId, 'note-abc');
|
|
assert.equal(snap.body, 'Hello world');
|
|
assert.equal(snap.savedTime, 1700000000000);
|
|
});
|