import assert from 'node:assert/strict'; import { appendFile, mkdtemp, rm } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { test } from 'node:test'; import { acquireLock, appendCompleted, completedKeyOf, isCancelled, loadCompleted, readRun, releaseLock, requestCancel, writeRun, } from './state'; import type { RunState } from './types'; async function withTempEnv(run: (env: Record) => Promise): Promise { const dir = await mkdtemp(join(tmpdir(), 'image-previews-')); try { await run({ IMAGE_PREVIEWS_STATE_DIR: dir }); } finally { await rm(dir, { recursive: true, force: true }); } } test('appendCompleted + loadCompleted round-trips and resumes', async () => { await withTempEnv(async (env) => { const empty = await loadCompleted(env); assert.equal(empty.size, 0); await appendCompleted({ file_id: 'f1', preset_key: 'system-small-cover', format: 'avif', ts: 1 }, env); await appendCompleted({ file_id: 'f1', preset_key: 'system-small-cover', format: 'webp', ts: 2 }, env); const completed = await loadCompleted(env); assert.equal(completed.size, 2); assert.ok(completed.has(completedKeyOf('f1', 'system-small-cover', 'avif'))); assert.ok(completed.has(completedKeyOf('f1', 'system-small-cover', 'webp'))); }); }); test('loadCompleted tolerates corrupt lines', async () => { await withTempEnv(async (env) => { await appendFile(join(env['IMAGE_PREVIEWS_STATE_DIR'] as string, 'state.jsonl'), 'not-json\n', 'utf8'); await appendCompleted({ file_id: 'f2', preset_key: 'k', format: null, ts: 1 }, env); const completed = await loadCompleted(env); assert.equal(completed.size, 1); }); }); test('run state round-trips', async () => { await withTempEnv(async (env) => { assert.equal(await readRun(env), null); const run: RunState = { running: true, startedAt: 1, finishedAt: null, total: 10, done: 2, generated: 2, hits: 0, failed: 0, rate: 1, eta: 8, cancelled: false, }; await writeRun(run, env); const loaded = await readRun(env); assert.equal(loaded?.done, 2); assert.equal(loaded?.total, 10); }); }); test('lock is exclusive and releasable', async () => { await withTempEnv(async (env) => { assert.equal(await acquireLock(env), true); assert.equal(await acquireLock(env), false); await releaseLock(env); assert.equal(await acquireLock(env), true); await releaseLock(env); }); }); test('cancel flag toggles', async () => { await withTempEnv(async (env) => { assert.equal(await isCancelled(env), false); await requestCancel(env); assert.equal(await isCancelled(env), true); }); });