test: execute the HTTP scenario catalog

This commit is contained in:
DongHyeonka
2026-08-02 11:17:28 +09:00
parent 76bf9f1aa3
commit abdd90ad5d
21 changed files with 2255 additions and 157 deletions
+85
View File
@@ -65,6 +65,30 @@ async function flushMicrotasks(): Promise<void> {
}
describe("descriptor-driven HTTP execution lifetime", () => {
it("normalizes a read-side 429 to the non-applicable effect vocabulary", async () => {
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 0,
attachCredentials: () => ({
kind: "READY",
headers: {},
credentials: "omit",
}),
fetcher: async () =>
Response.json(
{ type: "about:blank", title: "limited", status: 429 },
{ status: 429 },
),
});
await expect(
executor.execute(installed, { limit: 20 }, { scope }),
).resolves.toMatchObject({
kind: "RATE_LIMITED",
effect: "NOT_APPLICABLE",
});
});
it.each([
["absent intent", () => undefined],
["empty key", () => mutationIntent({ idempotencyKey: "" })],
@@ -471,6 +495,67 @@ describe("descriptor-driven HTTP execution lifetime", () => {
vi.useRealTimers();
});
it("never retries a deadline-owned abort while the monotonic clock still has a sub-tick budget", async () => {
vi.useFakeTimers();
try {
const iterationCount = 100;
const sleep = vi.fn(async () => {
throw new Error("a deadline-owned abort must not enter retry sleep");
});
const fetcher = vi.fn(
(_input: RequestInfo | URL, init?: RequestInit) =>
new Promise<Response>((_resolve, reject) => {
init?.signal?.addEventListener(
"abort",
() => reject(new DOMException("Aborted", "AbortError")),
{ once: true },
);
}),
);
const observe = vi.fn();
const executor = createContractHttpExecutor({
baseUrl: "https://api.example/",
maxRetryAttempts: 2,
attachCredentials: () => ({
kind: "READY",
headers: {},
credentials: "omit",
}),
fetcher,
monotonicNow: () => 0,
random: () => 0,
sleep,
observe,
});
for (let iteration = 0; iteration < iterationCount; iteration += 1) {
const result = executor.execute(
operation({ deadlineMs: 5 }),
{ limit: 20 },
{ scope },
);
await vi.advanceTimersByTimeAsync(5);
await flushMicrotasks();
await expect(result).resolves.toMatchObject({
kind: "TRANSPORT_FAILURE",
failure: { kind: "TIMEOUT" },
});
}
expect(fetcher).toHaveBeenCalledTimes(iterationCount);
expect(sleep).not.toHaveBeenCalled();
expect(observe).toHaveBeenCalledTimes(iterationCount);
for (const [observation] of observe.mock.calls) {
expect(observation).toEqual(
expect.objectContaining({ attempts: 1, certainty: "TIMEOUT" }),
);
}
} finally {
vi.useRealTimers();
}
});
it("cancels a non-cooperative retry sleep when the caller aborts", async () => {
const caller = new AbortController();
let sleepSignal: AbortSignal | undefined;