68 lines
2.2 KiB
JavaScript
68 lines
2.2 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { mkdtemp, rm } from 'node:fs/promises';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import test from 'node:test';
|
|
import { CardStateDatabase } from '../scripts/lib/card_state_db.mjs';
|
|
|
|
test('card state survives closing and reopening SQLite', async () => {
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), 'stem-card-state-'));
|
|
const file = path.join(directory, 'state.sqlite3');
|
|
const state = {
|
|
schema: 'stem-card-navigation.v2',
|
|
revision: 7,
|
|
selected_at: '2026-07-17T12:00:00.000Z',
|
|
snapshot_ref: 'task04.alloc5.cursor'
|
|
};
|
|
|
|
try {
|
|
const first = new CardStateDatabase(file);
|
|
first.write('navigation', state);
|
|
first.close();
|
|
|
|
const second = new CardStateDatabase(file);
|
|
assert.deepEqual(second.read('navigation'), state);
|
|
assert.equal(second.read('missing'), null);
|
|
second.close();
|
|
} finally {
|
|
await rm(directory, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('audit log is append-only, ordered and keeps navigation timestamps', async () => {
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), 'stem-card-audit-'));
|
|
const file = path.join(directory, 'state.sqlite3');
|
|
try {
|
|
const database = new CardStateDatabase(file);
|
|
const navigation = {
|
|
task: { id: 'task04' },
|
|
block: { id: 'allocator-flow' },
|
|
phase: { id: 'alloc5' },
|
|
step: { id: 'alloc5-commit' },
|
|
snapshot_ref: 'task04.alloc5.commit'
|
|
};
|
|
const first = database.appendEvent({
|
|
eventType: 'navigation.activate',
|
|
actor: 'nvim',
|
|
navigation,
|
|
occurredAt: '2026-07-17T12:00:00.000Z',
|
|
payload: { source: 'F2' }
|
|
});
|
|
const second = database.appendEvent({
|
|
eventType: 'checkpoint.ready',
|
|
actor: 'nvim',
|
|
navigation,
|
|
occurredAt: '2026-07-17T12:00:01.000Z'
|
|
});
|
|
assert.equal(second.id, first.id + 1);
|
|
assert.deepEqual(
|
|
database.listEvents({ afterId: first.id, limit: 10 }).map(event => event.event_type),
|
|
['checkpoint.ready']
|
|
);
|
|
assert.equal(database.listEvents()[0].snapshot_ref, navigation.snapshot_ref);
|
|
database.close();
|
|
} finally {
|
|
await rm(directory, { recursive: true, force: true });
|
|
}
|
|
});
|