From 64b9ae8fb1df565d085b355821e7099d259eb23e Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 21 Feb 2026 23:18:55 +0000 Subject: [PATCH] test(gateway): reuse shared openai timeout e2e helpers --- src/gateway/test-helpers.openai-mock.ts | 47 ++++++++++++++-- test/provider-timeout.e2e.test.ts | 73 +------------------------ 2 files changed, 44 insertions(+), 76 deletions(-) diff --git a/src/gateway/test-helpers.openai-mock.ts b/src/gateway/test-helpers.openai-mock.ts index 77e7abb1f14..163b2638181 100644 --- a/src/gateway/test-helpers.openai-mock.ts +++ b/src/gateway/test-helpers.openai-mock.ts @@ -149,12 +149,7 @@ function decodeBodyText(body: unknown): string { return ""; } -async function buildOpenAIResponsesSse(params: OpenAIResponsesParams): Promise { - const events: OpenAIResponseStreamEvent[] = []; - for await (const event of fakeOpenAIResponsesStream(params)) { - events.push(event); - } - +function buildSseResponse(events: unknown[]): Response { const sse = `${events.map((e) => `data: ${JSON.stringify(e)}\n\n`).join("")}data: [DONE]\n\n`; const encoder = new TextEncoder(); const body = new ReadableStream({ @@ -169,6 +164,46 @@ async function buildOpenAIResponsesSse(params: OpenAIResponsesParams): Promise { + const events: OpenAIResponseStreamEvent[] = []; + for await (const event of fakeOpenAIResponsesStream(params)) { + events.push(event); + } + return buildSseResponse(events); +} + export function installOpenAiResponsesMock(params?: { baseUrl?: string }) { const originalFetch = globalThis.fetch; const baseUrl = params?.baseUrl ?? "https://api.openai.com/v1"; diff --git a/test/provider-timeout.e2e.test.ts b/test/provider-timeout.e2e.test.ts index 6bb5ba25739..c2be09ce7a0 100644 --- a/test/provider-timeout.e2e.test.ts +++ b/test/provider-timeout.e2e.test.ts @@ -3,78 +3,11 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { describe, expect, it } from "vitest"; +import { extractPayloadText } from "../src/gateway/test-helpers.agent-results.js"; import { startGatewayWithClient } from "../src/gateway/test-helpers.e2e.js"; +import { buildOpenAIResponsesTextSse } from "../src/gateway/test-helpers.openai-mock.js"; import { buildOpenAiResponsesProviderConfig } from "../src/gateway/test-openai-responses-model.js"; -type OpenAIResponseStreamEvent = - | { type: "response.output_item.added"; item: Record } - | { type: "response.output_item.done"; item: Record } - | { - type: "response.completed"; - response: { - status: "completed"; - usage: { - input_tokens: number; - output_tokens: number; - total_tokens: number; - }; - }; - }; - -function buildOpenAIResponsesSse(text: string): Response { - const events: OpenAIResponseStreamEvent[] = [ - { - type: "response.output_item.added", - item: { - type: "message", - id: "msg_test_1", - role: "assistant", - content: [], - status: "in_progress", - }, - }, - { - type: "response.output_item.done", - item: { - type: "message", - id: "msg_test_1", - role: "assistant", - status: "completed", - content: [{ type: "output_text", text, annotations: [] }], - }, - }, - { - type: "response.completed", - response: { - status: "completed", - usage: { input_tokens: 10, output_tokens: 10, total_tokens: 20 }, - }, - }, - ]; - - const sse = `${events.map((e) => `data: ${JSON.stringify(e)}\n\n`).join("")}data: [DONE]\n\n`; - const encoder = new TextEncoder(); - const body = new ReadableStream({ - start(controller) { - controller.enqueue(encoder.encode(sse)); - controller.close(); - }, - }); - return new Response(body, { - status: 200, - headers: { "content-type": "text/event-stream" }, - }); -} - -function extractPayloadText(result: unknown): string { - const record = result as Record; - const payloads = Array.isArray(record.payloads) ? record.payloads : []; - const texts = payloads - .map((p) => (p && typeof p === "object" ? (p as Record).text : undefined)) - .filter((t): t is string => typeof t === "string" && t.trim().length > 0); - return texts.join("\n").trim(); -} - describe("provider timeouts (e2e)", () => { it( "falls back when the primary provider aborts with a timeout-like AbortError", @@ -107,7 +40,7 @@ describe("provider timeouts (e2e)", () => { if (url.startsWith(`${fallbackBaseUrl}/responses`)) { counts.fallback += 1; - return buildOpenAIResponsesSse("fallback-ok"); + return buildOpenAIResponsesTextSse("fallback-ok"); } if (!originalFetch) {