test: guard media provider mock calls

This commit is contained in:
Peter Steinberger
2026-05-11 23:57:18 +01:00
parent 12eb320b71
commit 459c12eda1
5 changed files with 67 additions and 19 deletions

View File

@@ -5,6 +5,14 @@ import {
transcribeElevenLabsAudio,
} from "./media-understanding-provider.js";
function requireFirstFetchCall(fetchMock: ReturnType<typeof vi.fn>): [string, RequestInit] {
const [call] = fetchMock.mock.calls;
if (!call) {
throw new Error("expected ElevenLabs media fetch call");
}
return call as [string, RequestInit];
}
describe("elevenLabsMediaUnderstandingProvider", () => {
let ssrfMock: { mockRestore: () => void } | undefined;
@@ -42,8 +50,8 @@ describe("elevenLabsMediaUnderstandingProvider", () => {
expect(result).toEqual({ text: "hello", model: "scribe_v2" });
expect(fetchMock).toHaveBeenCalledTimes(1);
expect(fetchMock.mock.calls[0]?.[0]).toBe("https://api.elevenlabs.io/v1/speech-to-text");
const init = fetchMock.mock.calls[0]?.[1] as RequestInit;
const [url, init] = requireFirstFetchCall(fetchMock);
expect(url).toBe("https://api.elevenlabs.io/v1/speech-to-text");
expect(init.method).toBe("POST");
const headers = new Headers(init.headers);
expect(headers.get("xi-api-key")).toBe("eleven-key");

View File

@@ -25,16 +25,24 @@ describe("elevenlabs tts diagnostics", () => {
}
function getHeadersFromFirstFetchCall(fetchMock: ReturnType<typeof vi.fn>): Headers {
const init = fetchMock.mock.calls[0]?.[1] as RequestInit | undefined;
return new Headers(init?.headers);
return new Headers(getInitFromFirstFetchCall(fetchMock).headers);
}
function requireFirstFetchCall(fetchMock: ReturnType<typeof vi.fn>): [string | URL, RequestInit] {
const [call] = fetchMock.mock.calls;
if (!call) {
throw new Error("expected ElevenLabs fetch call");
}
return call as [string | URL, RequestInit];
}
function getInitFromFirstFetchCall(fetchMock: ReturnType<typeof vi.fn>): RequestInit {
return (fetchMock.mock.calls[0] as unknown[])[1] as RequestInit;
const [, init] = requireFirstFetchCall(fetchMock);
return init;
}
function getUrlFromFirstFetchCall(fetchMock: ReturnType<typeof vi.fn>): URL {
const url = fetchMock.mock.calls[0]?.[0] as string | URL;
const [url] = requireFirstFetchCall(fetchMock);
return new URL(url.toString());
}

View File

@@ -84,15 +84,28 @@ describe("fal video generation provider", () => {
);
}
function requireFetchGuardCall(callNumber: number): { init?: RequestInit; url?: string } {
const call = fetchGuardMock.mock.calls[callNumber - 1];
if (!call) {
throw new Error(`expected fal fetch guard call ${callNumber}`);
}
const [request] = call;
if (!request || typeof request !== "object" || Array.isArray(request)) {
throw new Error(`expected fal fetch guard request ${callNumber}`);
}
return request as { init?: RequestInit; url?: string };
}
function getSubmitBody(): Record<string, unknown> {
return JSON.parse(String(fetchGuardMock.mock.calls[0]?.[0]?.init?.body ?? "{}")) as Record<
string,
unknown
>;
const body = requireFetchGuardCall(1).init?.body;
if (typeof body !== "string") {
throw new Error("expected fal submit JSON body");
}
return JSON.parse(body) as Record<string, unknown>;
}
function fetchGuardUrl(callNumber: number): string | undefined {
return (fetchGuardMock.mock.calls[callNumber - 1]?.[0] as { url?: string } | undefined)?.url;
return requireFetchGuardCall(callNumber).url;
}
afterEach(() => {
@@ -142,9 +155,7 @@ describe("fal video generation provider", () => {
});
expect(fetchGuardUrl(1)).toBe("https://queue.fal.run/fal-ai/minimax/video-01-live");
const submitBody = JSON.parse(
String(fetchGuardMock.mock.calls[0]?.[0]?.init?.body ?? "{}"),
) as Record<string, unknown>;
const submitBody = getSubmitBody();
expect(submitBody).toEqual({
prompt: "A spaceship emerges from the clouds",
});

View File

@@ -54,6 +54,22 @@ describe("minimax image-generation provider", () => {
expect(init?.method).toBe("POST");
}
function requireFirstPostJsonRequest(mock: ReturnType<typeof vi.fn>): {
body?: unknown;
ssrfPolicy?: unknown;
url?: string;
} {
const [call] = mock.mock.calls;
if (!call) {
throw new Error("expected MiniMax image request");
}
const [request] = call;
if (!request || typeof request !== "object" || Array.isArray(request)) {
throw new Error("expected MiniMax image request");
}
return request as { body?: unknown; url?: string };
}
it("generates PNG buffers through the shared provider HTTP path", async () => {
mockMinimaxApiKey();
const fetchMock = mockSuccessfulMinimaxImageResponse();
@@ -117,10 +133,7 @@ describe("minimax image-generation provider", () => {
});
expect(postJsonRequest).toHaveBeenCalledOnce();
const request = postJsonRequest.mock.calls[0]?.[0];
if (!request) {
throw new Error("expected MiniMax image request");
}
const request = requireFirstPostJsonRequest(postJsonRequest);
expect(request.url).toBe("https://api.minimax.io/v1/image_generation");
expect(request.body).toEqual({
model: "image-01",

View File

@@ -10,6 +10,14 @@ vi.mock("openclaw/plugin-sdk/ssrf-runtime", () => ({
fetchWithSsrFGuard: fetchWithSsrFGuardMock,
}));
function requireFirstGuardedFetchCall(): unknown {
const [call] = fetchWithSsrFGuardMock.mock.calls;
if (!call) {
throw new Error("expected Volcengine guarded fetch call");
}
return call[0];
}
function makeProviderConfig(overrides?: Record<string, unknown>) {
return {
apiKey: "test-api-key",
@@ -148,7 +156,7 @@ describe("Volcengine speech provider", () => {
expect(result.fileExtension).toBe(".opus");
expect(result.voiceCompatible).toBe(true);
const call = fetchWithSsrFGuardMock.mock.calls[0]?.[0];
const call = requireFirstGuardedFetchCall();
expect(call).toEqual({
url: "https://voice.ap-southeast-1.bytepluses.com/api/v3/tts/unidirectional",
init: {