// Comfy tests cover workflow-runtime bounded-read delegation. import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { readJsonResponseForTest, setComfyFetchGuardForTesting } from "./workflow-runtime.js"; describe("readJsonResponse bounded read (readProviderJsonResponse delegation)", () => { const fetchMock = vi.fn(); beforeEach(() => { vi.clearAllMocks(); }); afterEach(() => { setComfyFetchGuardForTesting(null); vi.restoreAllMocks(); }); it("cancels oversized JSON body via the 16 MiB provider cap", async () => { const ONE_MIB = 1024 * 1024; const TOTAL_CHUNKS = 32; const chunk = new Uint8Array(ONE_MIB); let bytesPulled = 0; let canceled = false; const oversizedJson = new Response( new ReadableStream({ pull(controller) { if (bytesPulled >= TOTAL_CHUNKS * ONE_MIB) { controller.close(); return; } bytesPulled += chunk.length; controller.enqueue(chunk); }, cancel() { canceled = true; }, }), { status: 200, headers: { "Content-Type": "application/json" } }, ); const release = vi.fn(async () => {}); fetchMock.mockResolvedValueOnce({ response: oversizedJson, release }); setComfyFetchGuardForTesting(fetchMock); await expect( readJsonResponseForTest({ url: "http://127.0.0.1:9999/test", init: { method: "GET" }, timeoutMs: 10_000, auditContext: "comfy-test", errorPrefix: "Comfy test failed", }), ).rejects.toThrow(/JSON response exceeds 16777216 bytes/); expect(canceled).toBe(true); expect(bytesPulled).toBeLessThan(TOTAL_CHUNKS * ONE_MIB); expect(release).toHaveBeenCalledOnce(); }); it("rejects oversized body with correct error prefix", async () => { const ONE_MIB = 1024 * 1024; const chunk = new Uint8Array(ONE_MIB); let bytesPulled = 0; let canceled = false; const oversizedJson = new Response( new ReadableStream({ pull(controller) { if (bytesPulled >= 32 * ONE_MIB) { controller.close(); return; } bytesPulled += chunk.length; controller.enqueue(chunk); }, cancel() { canceled = true; }, }), { status: 200, headers: { "Content-Type": "application/json" } }, ); const release = vi.fn(async () => {}); fetchMock.mockResolvedValueOnce({ response: oversizedJson, release }); setComfyFetchGuardForTesting(fetchMock); await expect( readJsonResponseForTest({ url: "http://127.0.0.1:9999/test", init: { method: "GET" }, timeoutMs: 10_000, auditContext: "comfy-test", errorPrefix: "Comfy test failed", }), ).rejects.toThrow(/^Comfy test failed: JSON response exceeds 16777216 bytes/); expect(canceled).toBe(true); expect(bytesPulled).toBeLessThan(32 * ONE_MIB); }); it("parses small valid JSON body (negative control)", async () => { const smallBody = { status: "ok" }; const release = vi.fn(async () => {}); fetchMock.mockResolvedValueOnce({ response: new Response(JSON.stringify(smallBody), { status: 200, headers: { "Content-Type": "application/json" }, }), release, }); setComfyFetchGuardForTesting(fetchMock); const result = await readJsonResponseForTest<{ status: string }>({ url: "http://127.0.0.1:9999/test", init: { method: "GET" }, timeoutMs: 10_000, auditContext: "comfy-test", errorPrefix: "Comfy test failed", }); expect(result.status).toBe("ok"); expect(release).toHaveBeenCalledOnce(); }); it("parses valid JSON with expected comfy response shape (happy path)", async () => { const comfyResponse = { prompt_id: "abc-123" }; const release = vi.fn(async () => {}); fetchMock.mockResolvedValueOnce({ response: new Response(JSON.stringify(comfyResponse), { status: 200, headers: { "Content-Type": "application/json" }, }), release, }); setComfyFetchGuardForTesting(fetchMock); const result = await readJsonResponseForTest<{ prompt_id: string }>({ url: "http://127.0.0.1:9999/test", init: { method: "GET" }, timeoutMs: 10_000, auditContext: "comfy-test", errorPrefix: "Comfy test failed", }); expect(result.prompt_id).toBe("abc-123"); expect(release).toHaveBeenCalledOnce(); }); it("propagates HTTP error status before reading body", async () => { const release = vi.fn(async () => {}); fetchMock.mockResolvedValueOnce({ response: new Response(null, { status: 500, statusText: "Internal Server Error" }), release, }); setComfyFetchGuardForTesting(fetchMock); await expect( readJsonResponseForTest({ url: "http://127.0.0.1:9999/test", init: { method: "GET" }, timeoutMs: 10_000, auditContext: "comfy-test", errorPrefix: "Comfy test failed", }), ).rejects.toThrow(/Comfy test failed/); expect(release).toHaveBeenCalledOnce(); }); });