import { PersistenceShutdownScope, startAdmittedPersistenceEffect, } from '../src/lib/frontendPersistence.ts'; const assertEquals = (actual: T, expected: T, message: string) => { if (actual !== expected) { throw new Error(`${message}: expected ${expected}, got ${actual}`); } }; const deferred = () => { let resolve!: (value: T) => void; let reject!: (reason: unknown) => void; const promise = new Promise((resolvePromise, rejectPromise) => { resolve = resolvePromise; reject = rejectPromise; }); return { promise, resolve, reject }; }; Deno.test('window close drains admitted persistence and rejects later registration', async () => { const first = deferred(); const starts: string[] = []; const scope = new PersistenceShutdownScope(); scope.register(() => { starts.push('first'); return first.promise; }); let drained = false; const drain = scope.closeAndDrain().then(() => { drained = true; }); const lateRegistration = scope.register(() => { starts.push('late'); return Promise.resolve(); }); assertEquals(lateRegistration, undefined, 'closed persistence admission must stay closed'); assertEquals(JSON.stringify(starts), JSON.stringify(['first']), 'late queues must not start'); assertEquals(drained, false, 'close must remain pending while persistence is active'); first.resolve(); await drain; assertEquals(drained, true, 'close should settle after every admitted queue'); }); Deno.test('settings hydration cannot start after close wins before its passive effect', async () => { const scope = new PersistenceShutdownScope(); await scope.closeAndDrain(); let storeLoads = 0; let publications = 0; const cleanup = startAdmittedPersistenceEffect( scope, () => Promise.resolve(), () => { storeLoads += 1; publications += 1; }, ); cleanup(); assertEquals(storeLoads, 0, 'closed admission must prevent the settings store load'); assertEquals(publications, 0, 'closed admission must prevent settings publication'); }); Deno.test('game-directory hydration cannot load or invoke after pre-effect close', async () => { const scope = new PersistenceShutdownScope(); await scope.closeAndDrain(); let storeLoads = 0; let backendInvokes = 0; const cleanup = startAdmittedPersistenceEffect( scope, () => Promise.resolve(), () => { storeLoads += 1; backendInvokes += 1; }, ); cleanup(); assertEquals(storeLoads, 0, 'closed admission must prevent the directory store load'); assertEquals(backendInvokes, 0, 'closed admission must prevent the directory invoke'); }); Deno.test('persistence shutdown rejection is observed without blocking other queues', async () => { const failure = new Error('persistence drain failed'); const reported: unknown[] = []; const scope = new PersistenceShutdownScope(error => reported.push(error)); let secondFinished = false; scope.register(() => Promise.reject(failure)); scope.register(async () => { secondFinished = true; }); await scope.closeAndDrain(); assertEquals(reported.length, 1, 'the failed shutdown should be reported once'); assertEquals(reported[0], failure, 'the original shutdown failure should be reported'); assertEquals(secondFinished, true, 'one failure must not skip another persistence queue'); });