test(gateway): reuse shared openai timeout e2e helpers

This commit is contained in:
Peter Steinberger
2026-02-21 23:18:55 +00:00
parent 271999d42a
commit 64b9ae8fb1
2 changed files with 44 additions and 76 deletions

View File

@@ -149,12 +149,7 @@ function decodeBodyText(body: unknown): string {
return "";
}
async function buildOpenAIResponsesSse(params: OpenAIResponsesParams): Promise<Response> {
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<Uint8Array>({
@@ -169,6 +164,46 @@ async function buildOpenAIResponsesSse(params: OpenAIResponsesParams): Promise<R
});
}
export function buildOpenAIResponsesTextSse(text: string): Response {
return buildSseResponse([
{
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 },
},
},
]);
}
async function buildOpenAIResponsesSse(params: OpenAIResponsesParams): Promise<Response> {
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";

View File

@@ -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<string, unknown> }
| { type: "response.output_item.done"; item: Record<string, unknown> }
| {
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<Uint8Array>({
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<string, unknown>;
const payloads = Array.isArray(record.payloads) ? record.payloads : [];
const texts = payloads
.map((p) => (p && typeof p === "object" ? (p as Record<string, unknown>).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) {