import { importModuleWithRetry } from "../src/platform/moduleLoading"; import { createModuleRefresh } from "../src/platform/moduleRefresh"; function assert(condition: unknown, message: string): asserts condition { if (!condition) throw new Error(message); } async function verifyModuleImportRetry() { let attempts = 0; let pauses = 0; const module = { id: "files", uiCapabilities: { "files.fileExplorer": {} } }; const imported = await importModuleWithRetry(async () => { attempts += 1; if (attempts === 1) throw new TypeError("Synthetic transient import failure"); return module; }, async () => { pauses += 1; }); assert(imported === module, "a second successful import preserves the real module descriptor"); assert(attempts === 2 && pauses === 1, "a transient failure gets exactly one bounded retry"); attempts = 0; pauses = 0; const terminal = new TypeError("Synthetic final import failure"); let observed: unknown; try { await importModuleWithRetry(async () => { attempts += 1; throw terminal; }, async () => { pauses += 1; }); } catch (error) { observed = error; } assert(observed === terminal, "a final failure must be reported, never replaced by an empty or fake module"); assert(attempts === 2 && pauses === 1, "permanent failure cannot start an unbounded retry loop"); attempts = 0; pauses = 0; await importModuleWithRetry(async () => { attempts += 1; return module; }, async () => { pauses += 1; }); assert(attempts === 1 && pauses === 0, "healthy imports do not pause or repeat"); console.log("Module import retry tests passed."); } void verifyModuleImportRetry().catch((error) => { throw error; }); async function verifyModuleRefresh() { const requests: Array<{ resolve: (value: number) => void; reject: (error: unknown) => void }> = []; const accepted: number[] = []; const errors: unknown[] = []; let time = 0; const refresh = createModuleRefresh({ load: () => new Promise((resolve, reject) => requests.push({ resolve, reject })), accept: (value) => accepted.push(value), reject: (error) => errors.push(error), now: () => time }); const settle = async () => { await Promise.resolve(); await Promise.resolve(); }; refresh.invalidate(); refresh.invalidate(); refresh.invalidate(); assert(requests.length === 1, "mutation bursts cannot start overlapping requests"); requests[0].resolve(0); await settle(); assert(accepted.length === 0 && Number(requests.length) === 2, "obsolete success is ignored and invalidation gets one trailing read"); refresh.invalidate(); requests[1].reject(new Error("obsolete")); await settle(); assert(errors.length === 0 && Number(requests.length) === 3, "obsolete error cannot clear the current catalogue or drop invalidation"); requests[2].resolve(2); await settle(); assert(accepted.join() === "2", "only the current generation publishes"); refresh.refreshVisible(true); time = 6_000; refresh.refreshVisible(false); assert(Number(requests.length) === 3, "focus throttle and hidden-document checks remain"); refresh.refreshVisible(true); assert(Number(requests.length) === 4, "visible focus refresh remains available after the throttle"); requests[3].reject("current failure"); await settle(); assert(errors.join() === "current failure", "current errors retain fail-closed handling without automatic retries"); refresh.invalidate(); refresh.invalidate(); refresh.dispose(); requests[4].resolve(4); await settle(); refresh.invalidate(); assert(Number(requests.length) === 5 && accepted.join() === "2", "authority change/unmount discards both old response and queued work"); console.log("Module refresh coalescing and generation tests passed."); } void verifyModuleRefresh().catch((error) => { throw error; });