import { describe, expect, it, vi } from "vitest"; import { createContractHttpExecutor } from "../../src/adapters/http/http-execution-v3.ts"; import type { InstalledHttpContract } from "../../src/contracts/external-contract-runtime.ts"; import { COMPOSED_CONTRACT_CONTRIBUTIONS } from "../../src/features/installed-contract-contributions.ts"; const installed = (() => { const candidate = COMPOSED_CONTRACT_CONTRIBUTIONS.httpByOperationId.get( "LIST_REFERENCE_RESOURCES", ); if (!candidate) throw new Error("reference list contract is not installed"); return candidate; })(); const scope = Object.freeze({ generation: 1, fingerprint: "scope-1", identities: Object.freeze({}) as never, signal: new AbortController().signal, isCurrent: () => true, }); const createInstalled = (() => { const candidate = COMPOSED_CONTRACT_CONTRIBUTIONS.httpByOperationId.get( "CREATE_REFERENCE_RESOURCE", ); if (!candidate) throw new Error("reference create contract is not installed"); return candidate; })(); function operation( overrides: Readonly<{ deadlineMs?: number; responseBody?: "REQUIRED_JSON" | "OPTIONAL_JSON" | "NONE"; }> = {}, ): InstalledHttpContract { return { ...installed, contract: { ...installed.contract, responseBody: overrides.responseBody ?? installed.contract.responseBody, }, frontend: { ...installed.frontend, totalDeadlineMs: overrides.deadlineMs ?? installed.frontend.totalDeadlineMs, }, }; } async function flushMicrotasks(): Promise { await Promise.resolve(); await Promise.resolve(); await Promise.resolve(); } describe("descriptor-driven HTTP execution lifetime", () => { it.each([ [{}, "limit=20"], [{ limit: "7" }, "limit=7"], ])("projects the canonical validated input %#", async (input, expectedQuery) => { const fetcher = vi.fn(async () => Response.json([])); const executor = createContractHttpExecutor({ baseUrl: "https://api.example/", maxRetryAttempts: 0, attachCredentials: () => ({ kind: "READY", headers: {}, credentials: "omit", }), fetcher, }); await expect(executor.execute(installed, input, { scope })).resolves.toMatchObject({ kind: "SUCCESS", }); expect(String((fetcher.mock.calls as unknown[][])[0]?.[0])).toContain( expectedQuery, ); }); it("contains throwing and malformed external request projections", async () => { const executor = createContractHttpExecutor({ baseUrl: "https://api.example/", maxRetryAttempts: 0, attachCredentials: () => ({ kind: "READY", headers: {}, credentials: "omit", }), fetcher: vi.fn(), }); const throwing = { ...installed, contract: { ...installed.contract, projectRequest: () => { throw new Error("external descriptor defect"); }, }, }; const malformed = { ...installed, contract: { ...installed.contract, projectRequest: () => ({ pathValues: {}, queryEntries: [["limit"]], body: null }), }, } as unknown as typeof installed; await expect(executor.execute(throwing, { limit: 20 }, { scope })).resolves.toMatchObject({ kind: "CONTRACT_VIOLATION", effect: "NOT_APPLICABLE", }); await expect(executor.execute(malformed, { limit: 20 }, { scope })).resolves.toMatchObject({ kind: "CONTRACT_VIOLATION", effect: "NOT_APPLICABLE", }); }); it("preserves MAYBE_APPLIED for a malformed command response after dispatch", async () => { const executor = createContractHttpExecutor({ baseUrl: "https://api.example/", maxRetryAttempts: 0, attachCredentials: () => ({ kind: "READY", headers: {}, credentials: "omit", }), fetcher: vi.fn(async () => Response.json({ malformed: true }, { status: 201 })), }); await expect( executor.execute( createInstalled, { name: "created" }, { scope, intent: { intentId: "intent-1", startedBy: "USER", idempotencyKey: "key-1" }, }, ), ).resolves.toMatchObject({ kind: "CONTRACT_VIOLATION", violation: { kind: "SUCCESS_SCHEMA_INVALID" }, effect: "MAYBE_APPLIED", }); }); it("preserves MAYBE_APPLIED when a command response arrives after its scope fence", async () => { let current = true; const lifetime = new AbortController(); const fencedScope = Object.freeze({ ...scope, signal: lifetime.signal, isCurrent: () => current, }); const executor = createContractHttpExecutor({ baseUrl: "https://api.example/", maxRetryAttempts: 0, attachCredentials: () => ({ kind: "READY", headers: {}, credentials: "omit", }), fetcher: vi.fn(async () => { current = false; lifetime.abort(); return Response.json( { id: "created", name: "Created" }, { status: 201 }, ); }), }); await expect( executor.execute( createInstalled, { name: "created" }, { scope: fencedScope, intent: { intentId: "intent-2", startedBy: "USER", idempotencyKey: "key-2" }, }, ), ).resolves.toMatchObject({ kind: "CONTRACT_VIOLATION", violation: { kind: "SCOPE_FENCED" }, effect: "MAYBE_APPLIED", }); }); it("settles a credential hang at the total operation deadline", async () => { vi.useFakeTimers(); let settled = false; const executor = createContractHttpExecutor({ baseUrl: "https://api.example/", maxRetryAttempts: 0, attachCredentials: () => new Promise(() => {}), }); const result = executor .execute(operation({ deadlineMs: 5 }), { limit: 20 }, { scope }) .then((outcome) => { settled = true; return outcome; }); await vi.advanceTimersByTimeAsync(5); await flushMicrotasks(); expect(settled).toBe(true); await expect(result).resolves.toMatchObject({ kind: "TRANSPORT_FAILURE", failure: { kind: "TIMEOUT" }, }); vi.useRealTimers(); }); it("cancels a non-cooperative retry sleep when the caller aborts", async () => { const caller = new AbortController(); let sleepSignal: AbortSignal | undefined; let settled = false; const executor = createContractHttpExecutor({ baseUrl: "https://api.example/", maxRetryAttempts: 2, attachCredentials: () => ({ kind: "READY", headers: {}, credentials: "omit", }), fetcher: vi.fn(async () => Response.json( { type: "about:blank", title: "temporary", status: 503 }, { status: 503 }, ), ), sleep: (_ms, signal) => { sleepSignal = signal; return new Promise(() => {}); }, random: () => 0, }); const result = executor .execute(installed, { limit: 20 }, { scope, signal: caller.signal }) .then((outcome) => { settled = true; return outcome; }); await vi.waitFor(() => expect(sleepSignal).toBeDefined()); caller.abort(); await flushMicrotasks(); expect(sleepSignal?.aborted).toBe(true); expect(settled).toBe(true); await expect(result).resolves.toMatchObject({ kind: "CANCELLED" }); }); it("treats an unreadable forbidden-body probe as a transport failure", async () => { const body = new ReadableStream({ pull(controller) { controller.error(new TypeError("stream failed")); }, }); const executor = createContractHttpExecutor({ baseUrl: "https://api.example/", maxRetryAttempts: 0, attachCredentials: () => ({ kind: "READY", headers: {}, credentials: "omit", }), fetcher: vi.fn(async () => new Response(body, { status: 200 })), }); await expect( executor.execute( operation({ responseBody: "NONE" }), { limit: 20 }, { scope }, ), ).resolves.toMatchObject({ kind: "TRANSPORT_FAILURE", failure: { kind: "RESPONSE_STREAM_FAILURE" }, }); }); });