import assert from 'node:assert/strict'; import { AutosaveScheduler } from '../../web/app/src/storage/autosave.ts'; const timers = new Map(); let serial = 0; globalThis.window = { setTimeout(callback) { timers.set(++serial, callback); return serial; }, clearTimeout(id) { timers.delete(id); } }; const fire = async () => { for (const [id, callback] of [...timers]) { timers.delete(id); callback(); } await Promise.resolve(); }; const deferred = () => { let release; const promise = new Promise(resolve => { release = resolve; }); return { promise, release }; }; const scheduler = new AutosaveScheduler(), edit = deferred(); let entered = 0, commits = 0; scheduler.schedule(async isCurrent => { entered++; await edit.promise; if (isCurrent()) commits++; }, 1); await fire(); assert.equal(entered, 1); scheduler.cancel(); edit.release(); await scheduler.whenIdle(); assert.equal(commits, 0, 'new edit cancels waiting checkpoint'); scheduler.schedule(() => { commits++; }, 1); await fire(); await scheduler.whenIdle(); assert.equal(commits, 1, 'recovery reschedules'); scheduler.schedule(() => { commits++; }, 1); scheduler.cancel(); await fire(); assert.equal(commits, 1, 'timer cancellation prevents dispatch'); const write = deferred(); let writing = false, finished = false; scheduler.schedule(async () => { writing = true; await write.promise; finished = true; }, 1); await fire(); assert.equal(writing, true); scheduler.cancel(); assert.equal(finished, false); write.release(); await scheduler.whenIdle(); assert.equal(finished, true, 'active write retains ownership until finished'); scheduler.dispose(); console.log(JSON.stringify({status:'PASS',checks:['waiting callback cancellation','recovery reschedule','timer cancellation','active write completion']}));