import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
configureAzureSession,
extract,
modelVerification,
} from "../server/model";
import { modelLoad, retryAfterMs } from "../server/model-runtime";
import { parseCompactDraft } from "../server/compact";
import { groundedFact } from "../server/guards";
const source = [
{
id: "load",
title: "Synthetic load note",
kind: "Synthetic",
date: "2026-10-23",
text: "Patient: Nora Test\nShe takes Metformin 500 mg twice daily.",
},
];
const good = () =>
new Response(
JSON.stringify({
choices: [
{
finish_reason: "stop",
message: {
content: JSON.stringify({
facts: [
[
2,
"Medication: Metformin; strength: 500 mg; frequency: 2/day",
],
],
}),
},
},
],
}),
{ status: 200 },
);
function configure() {
configureAzureSession({
endpoint:
"https://synthetic.services.ai.azure.com/openai/v1/chat/completions",
key: "synthetic",
model: "test",
auth: "api-key",
});
}
beforeEach(configure);
afterEach(() => {
vi.unstubAllGlobals();
vi.restoreAllMocks();
});
describe("bounded provider work", () => {
it("admits four calls, rejects overflow promptly, and releases capacity", async () => {
const finish: Array<(r: Response) => void> = [];
vi.stubGlobal(
"fetch",
vi.fn(() => new Promise<Response>((resolve) => finish.push(resolve))),
);
const admitted = Array.from({ length: 4 }, () =>
extract(source, true, true),
);
expect(modelLoad().active).toBe(4);
const rejected = await Promise.allSettled(
Array.from({ length: 8 }, () => extract(source, true, true)),
);
expect(
rejected.every(
(r) =>
r.status === "rejected" && /slots are busy/.test(r.reason.message),
),
).toBe(true);
for (const resolve of finish) resolve(good());
await Promise.all(admitted);
expect(modelLoad().active).toBe(0);
});
it("aborts provider work and permits a later successful retry", async () => {
const fetcher = vi.fn(
(_url, options) =>
new Promise((_r, reject) =>
options.signal.addEventListener(
"abort",
() => reject(new Error("private abort")),
{ once: true },
),
),
);
vi.stubGlobal("fetch", fetcher);
const controller = new AbortController();
const pending = extract(source, true, true, controller.signal);
controller.abort();
await expect(pending).rejects.toThrow("cancelled");
expect(fetcher).toHaveBeenCalledTimes(1);
expect(modelLoad().active).toBe(0);
vi.stubGlobal(
"fetch",
vi.fn(async () => good()),
);
expect((await extract(source, true)).strategy).toBe("narrative");
});
it("does not publish or cache an in-flight result after reconfiguration", async () => {
let finish!: (r: Response) => void;
vi.stubGlobal(
"fetch",
vi.fn(
() =>
new Promise<Response>((r) => {
finish = r;
}),
),
);
const pending = extract(source, true, true);
configure();
finish(good());
await expect(pending).rejects.toThrow("cancelled");
expect(modelVerification()).toBeNull();
expect(modelLoad().active).toBe(0);
});
it("honors HTTP-date Retry-After and prevents a subsequent retry storm", async () => {
const date = new Date(Date.now() + 60_000).toUTCString();
const fetcher = vi.fn(
async () =>
new Response("", { status: 429, headers: { "Retry-After": date } }),
);
vi.stubGlobal("fetch", fetcher);
await expect(extract(source, true, true)).rejects.toThrow("busy");
await expect(extract(source, true, true)).rejects.toThrow("rate limited");
expect(fetcher).toHaveBeenCalledTimes(1);
expect(modelLoad().active).toBe(0);
});
it.each([null, [], {}, "invalid"])(
"rejects invalid provider envelope %j with a safe message",
async (body) => {
vi.stubGlobal(
"fetch",
vi.fn(async () => new Response(JSON.stringify(body))),
);
await expect(extract(source, true, true)).rejects.toThrow(
"invalid response",
);
expect(modelLoad().active).toBe(0);
},
);
it("handles numeric, date and invalid retry delay formats", () => {
expect(retryAfterMs("2")).toBe(2000);
expect(retryAfterMs("garbage")).toBe(0);
expect(retryAfterMs(new Date(60000).toUTCString(), 0)).toBe(60000);
});
});
describe("expanded messy source boundaries", () => {
it.each([
["She has a Penicillin allergy.", "Allergies: Penicillin"],
[
"Her eGFR was 38 mL/min/1.73m2 on 2026-10-12.",
"Lab: eGFR; value: 38; unit: mL/min/1.73m2; date: 2026-10-12",
],
])(
"withholds ambiguous pronouns after a relative on a previous line: %s",
(quote, normalized) => {
const sources = [
{
...source[0],
text: "Patient: Nora Test\nHer sister came yesterday.\n" + quote,
},
];
const d = parseCompactDraft(
{ facts: [[3, normalized]] },
sources,
"test",
0,
);
expect(d.facts.at(-1)?.problem).toContain("subject");
},
);
it("retains an explicitly named patient after a relative", () => {
const sources = [
{
...source[0],
text: "Patient: Nora Test\nHer sister has a Penicillin allergy.\nNora has no known drug allergies.",
},
];
expect(
parseCompactDraft(
{ facts: [[3, "Allergies: No known allergies"]] },
sources,
"test",
0,
).facts.at(-1)?.problem,
).toBeNull();
});
it("does not turn a conditional prescription into a current medicine", () => {
expect(
groundedFact(
"Medication: Amlodipine; strength: 5 mg",
"If her pressure rises, Nora may start Amlodipine 5 mg.",
["Nora Test"],
)?.problem,
).toBeTruthy();
});
it.each([
"Nora's eGFR was not 38 mL/min/1.73m2 on 2026-10-12.",
"The old eGFR 38 mL/min/1.73m2 dated 2026-10-12 was entered in error.",
])("withholds negated/erroneous labs: %s", (quote) => {
expect(
groundedFact(
"Lab: eGFR; value: 38; unit: mL/min/1.73m2; date: 2026-10-12",
quote,
["Nora Test"],
)?.problem,
).toBeTruthy();
});
});