src/sync-reload.test.tsx

import { test } from "node:test";
import assert from "node:assert/strict";
import { coalesceReload } from "./api";

const deferred = () => {
  let resolve!: (value: number) => void;
  let reject!: (error: Error) => void;
  const promise = new Promise<number>((r, j) => { resolve = r; reject = j; });
  return { promise, resolve, reject };
};

test("progress notifications share one active reload and one pending final refresh", async () => {
  const first = deferred(), final = deferred();
  let calls = 0, active = 0, peak = 0;
  const reload = coalesceReload(async () => {
    calls++; peak = Math.max(peak, ++active);
    try { return await (calls === 1 ? first.promise : final.promise); }
    finally { active--; }
  });
  const requests = [reload()];
  await Promise.resolve();
  for (let i = 0; i < 100; i++) requests.push(reload());
  try {
    assert.equal(calls, 1); assert.equal(peak, 1);
    first.resolve(1);
    for (let i = 0; i < 5; i++) await Promise.resolve();
    assert.equal(calls, 2); assert.equal(peak, 1);
    final.resolve(2);
    assert.ok((await Promise.all(requests)).every((value) => value === 2));
    const repeat = reload(); await Promise.resolve();
    assert.equal(calls, 3); assert.equal(await repeat, 2);
  } finally { first.resolve(1); final.resolve(2); await Promise.allSettled(requests); }
});

test("a notification queued during a rejected read still receives one final refresh", async () => {
  const first = deferred(), final = deferred();
  let calls = 0, active = 0, peak = 0;
  const reload = coalesceReload(async () => {
    calls++; peak = Math.max(peak, ++active);
    try { return await (calls === 1 ? first.promise : final.promise); }
    finally { active--; }
  });
  const initial = reload();
  await Promise.resolve();
  const queued = reload();
  const results = Promise.allSettled([initial, queued]);
  first.reject(new Error("Synthetic failure"));
  try {
    for (let i = 0; i < 10; i++) await Promise.resolve();
    assert.equal(calls, 2); assert.equal(peak, 1);
    final.resolve(2);
    assert.deepEqual(await results, [{ status: "fulfilled", value: 2 }, { status: "fulfilled", value: 2 }]);
    await Promise.resolve(); assert.equal(calls, 2, "no retry without another notification");
  } finally { first.resolve(1); final.resolve(2); await results; }
});

test("failed reload releases its slot so a later request can recover", async () => {
  let fail = true, calls = 0;
  const reload = coalesceReload(async () => { calls++; if (fail) throw new Error("Synthetic failure"); return 2; });
  const first = reload(), duplicate = reload();
  await Promise.all([assert.rejects(first, /Synthetic failure/), assert.rejects(duplicate, /Synthetic failure/)]);
  assert.equal(calls, 1);
  fail = false;
  assert.equal(await reload(), 2); assert.equal(calls, 2);
});