import test from "node:test";
import assert from "node:assert/strict";
import { serializeConfigMutation } from "./config-mutation.js";

test("serializes config mutations submitted by independent callers", async () => {
  const events = [];
  let releaseFirst;
  let markFirstStarted;
  const firstGate = new Promise((resolve) => { releaseFirst = resolve; });
  const firstStarted = new Promise((resolve) => { markFirstStarted = resolve; });
  const mutateAccountConfig = (operation) => serializeConfigMutation(operation);
  const mutateWorkspaceConfig = (operation) => serializeConfigMutation(operation);

  const first = mutateAccountConfig(async () => {
    events.push("account:start");
    markFirstStarted();
    await firstGate;
    events.push("account:end");
  });
  await firstStarted;

  const second = mutateWorkspaceConfig(async () => {
    events.push("workspace:start");
    events.push("workspace:end");
  });
  await Promise.resolve();

  assert.deepEqual(events, ["account:start"]);
  releaseFirst();
  await Promise.all([first, second]);
  assert.deepEqual(events, ["account:start", "account:end", "workspace:start", "workspace:end"]);
});

test("a failed config mutation does not poison the shared queue", async () => {
  const events = [];

  const failed = serializeConfigMutation(async () => {
    events.push("failed");
    throw new Error("write failed");
  });
  const recovered = serializeConfigMutation(async () => {
    events.push("recovered");
    return "saved";
  });

  await assert.rejects(failed, /write failed/);
  assert.equal(await recovered, "saved");
  assert.deepEqual(events, ["failed", "recovered"]);
});
