diff --git a/extensions/vydra/image-generation-provider.test.ts b/extensions/vydra/image-generation-provider.test.ts index 90ab61df727..2a54090f731 100644 --- a/extensions/vydra/image-generation-provider.test.ts +++ b/extensions/vydra/image-generation-provider.test.ts @@ -1,7 +1,12 @@ -import * as providerAuth from "openclaw/plugin-sdk/provider-auth-runtime"; import { installPinnedHostnameTestHooks } from "openclaw/plugin-sdk/testing"; import { afterEach, describe, expect, it, vi } from "vitest"; import { buildVydraImageGenerationProvider } from "./image-generation-provider.js"; +import { + binaryResponse, + jsonResponse, + stubFetch, + stubVydraApiKey, +} from "./provider-test-helpers.test.js"; describe("vydra image-generation provider", () => { installPinnedHostnameTestHooks(); @@ -12,33 +17,15 @@ describe("vydra image-generation provider", () => { }); it("posts to the www api and downloads the generated image", async () => { - vi.spyOn(providerAuth, "resolveApiKeyForProvider").mockResolvedValue({ - apiKey: "vydra-test-key", - source: "env", - mode: "api-key", - }); - const fetchMock = vi - .fn() - .mockResolvedValueOnce( - new Response( - JSON.stringify({ - jobId: "job-123", - status: "completed", - imageUrl: "https://cdn.vydra.ai/generated/test.png", - }), - { - status: 200, - headers: { "Content-Type": "application/json" }, - }, - ), - ) - .mockResolvedValueOnce( - new Response(Buffer.from("png-data"), { - status: 200, - headers: { "Content-Type": "image/png" }, - }), - ); - vi.stubGlobal("fetch", fetchMock); + stubVydraApiKey(); + const fetchMock = stubFetch( + jsonResponse({ + jobId: "job-123", + status: "completed", + imageUrl: "https://cdn.vydra.ai/generated/test.png", + }), + binaryResponse("png-data", "image/png"), + ); const provider = buildVydraImageGenerationProvider(); const result = await provider.generateImage({ @@ -80,39 +67,16 @@ describe("vydra image-generation provider", () => { }); it("polls jobs when the create response is not completed yet", async () => { - vi.spyOn(providerAuth, "resolveApiKeyForProvider").mockResolvedValue({ - apiKey: "vydra-test-key", - source: "env", - mode: "api-key", - }); - const fetchMock = vi - .fn() - .mockResolvedValueOnce( - new Response(JSON.stringify({ jobId: "job-456", status: "queued" }), { - status: 200, - headers: { "Content-Type": "application/json" }, - }), - ) - .mockResolvedValueOnce( - new Response( - JSON.stringify({ - jobId: "job-456", - status: "completed", - resultUrls: ["https://cdn.vydra.ai/generated/polled.png"], - }), - { - status: 200, - headers: { "Content-Type": "application/json" }, - }, - ), - ) - .mockResolvedValueOnce( - new Response(Buffer.from("png-data"), { - status: 200, - headers: { "Content-Type": "image/png" }, - }), - ); - vi.stubGlobal("fetch", fetchMock); + stubVydraApiKey(); + const fetchMock = stubFetch( + jsonResponse({ jobId: "job-456", status: "queued" }), + jsonResponse({ + jobId: "job-456", + status: "completed", + resultUrls: ["https://cdn.vydra.ai/generated/polled.png"], + }), + binaryResponse("png-data", "image/png"), + ); const provider = buildVydraImageGenerationProvider(); await provider.generateImage({ diff --git a/extensions/vydra/provider-test-helpers.test.ts b/extensions/vydra/provider-test-helpers.test.ts new file mode 100644 index 00000000000..bdf73a8b2c2 --- /dev/null +++ b/extensions/vydra/provider-test-helpers.test.ts @@ -0,0 +1,33 @@ +import * as providerAuth from "openclaw/plugin-sdk/provider-auth-runtime"; +import { vi } from "vitest"; + +export function stubVydraApiKey(): void { + vi.spyOn(providerAuth, "resolveApiKeyForProvider").mockResolvedValue({ + apiKey: "vydra-test-key", + source: "env", + mode: "api-key", + }); +} + +export function jsonResponse(payload: Record): Response { + return new Response(JSON.stringify(payload), { + status: 200, + headers: { "Content-Type": "application/json" }, + }); +} + +export function binaryResponse(data: string, contentType: string): Response { + return new Response(Buffer.from(data), { + status: 200, + headers: { "Content-Type": contentType }, + }); +} + +export function stubFetch(...responses: Response[]): ReturnType { + const fetchMock = vi.fn(); + for (const response of responses) { + fetchMock.mockResolvedValueOnce(response); + } + vi.stubGlobal("fetch", fetchMock); + return fetchMock; +} diff --git a/extensions/vydra/video-generation-provider.test.ts b/extensions/vydra/video-generation-provider.test.ts index d25c4334cd2..de8f54481a2 100644 --- a/extensions/vydra/video-generation-provider.test.ts +++ b/extensions/vydra/video-generation-provider.test.ts @@ -1,7 +1,12 @@ -import * as providerAuth from "openclaw/plugin-sdk/provider-auth-runtime"; import { installPinnedHostnameTestHooks } from "openclaw/plugin-sdk/testing"; import { afterEach, describe, expect, it, vi } from "vitest"; import { expectExplicitVideoGenerationCapabilities } from "../../test/helpers/media-generation/provider-capability-assertions.js"; +import { + binaryResponse, + jsonResponse, + stubFetch, + stubVydraApiKey, +} from "./provider-test-helpers.test.js"; import { buildVydraVideoGenerationProvider } from "./video-generation-provider.js"; describe("vydra video-generation provider", () => { @@ -17,39 +22,16 @@ describe("vydra video-generation provider", () => { }); it("submits veo3 jobs and downloads the completed video", async () => { - vi.spyOn(providerAuth, "resolveApiKeyForProvider").mockResolvedValue({ - apiKey: "vydra-test-key", - source: "env", - mode: "api-key", - }); - const fetchMock = vi - .fn() - .mockResolvedValueOnce( - new Response(JSON.stringify({ jobId: "job-123", status: "processing" }), { - status: 200, - headers: { "Content-Type": "application/json" }, - }), - ) - .mockResolvedValueOnce( - new Response( - JSON.stringify({ - jobId: "job-123", - status: "completed", - videoUrl: "https://cdn.vydra.ai/generated/test.mp4", - }), - { - status: 200, - headers: { "Content-Type": "application/json" }, - }, - ), - ) - .mockResolvedValueOnce( - new Response(Buffer.from("mp4-data"), { - status: 200, - headers: { "Content-Type": "video/mp4" }, - }), - ); - vi.stubGlobal("fetch", fetchMock); + stubVydraApiKey(); + const fetchMock = stubFetch( + jsonResponse({ jobId: "job-123", status: "processing" }), + jsonResponse({ + jobId: "job-123", + status: "completed", + videoUrl: "https://cdn.vydra.ai/generated/test.mp4", + }), + binaryResponse("mp4-data", "video/mp4"), + ); const provider = buildVydraVideoGenerationProvider(); const result = await provider.generateVideo({ @@ -81,11 +63,7 @@ describe("vydra video-generation provider", () => { }); it("requires a remote image url for kling", async () => { - vi.spyOn(providerAuth, "resolveApiKeyForProvider").mockResolvedValue({ - apiKey: "vydra-test-key", - source: "env", - mode: "api-key", - }); + stubVydraApiKey(); vi.stubGlobal("fetch", vi.fn()); const provider = buildVydraVideoGenerationProvider(); @@ -101,39 +79,16 @@ describe("vydra video-generation provider", () => { }); it("submits kling jobs with a remote image url", async () => { - vi.spyOn(providerAuth, "resolveApiKeyForProvider").mockResolvedValue({ - apiKey: "vydra-test-key", - source: "env", - mode: "api-key", - }); - const fetchMock = vi - .fn() - .mockResolvedValueOnce( - new Response(JSON.stringify({ jobId: "job-kling", status: "processing" }), { - status: 200, - headers: { "Content-Type": "application/json" }, - }), - ) - .mockResolvedValueOnce( - new Response( - JSON.stringify({ - jobId: "job-kling", - status: "completed", - videoUrl: "https://cdn.vydra.ai/generated/kling.mp4", - }), - { - status: 200, - headers: { "Content-Type": "application/json" }, - }, - ), - ) - .mockResolvedValueOnce( - new Response(Buffer.from("mp4-data"), { - status: 200, - headers: { "Content-Type": "video/mp4" }, - }), - ); - vi.stubGlobal("fetch", fetchMock); + stubVydraApiKey(); + const fetchMock = stubFetch( + jsonResponse({ jobId: "job-kling", status: "processing" }), + jsonResponse({ + jobId: "job-kling", + status: "completed", + videoUrl: "https://cdn.vydra.ai/generated/kling.mp4", + }), + binaryResponse("mp4-data", "video/mp4"), + ); const provider = buildVydraVideoGenerationProvider(); const result = await provider.generateVideo({