mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
refactor(plugins): remove media test globals (#122636)
This commit is contained in:
committed by
GitHub
parent
85230cf76c
commit
c5ba4efbd7
@@ -5,7 +5,6 @@ import { createTestPluginApi } from "openclaw/plugin-sdk/plugin-test-api";
|
||||
import { isLiveTestEnabled, readLiveTestConfig } from "openclaw/plugin-sdk/test-live";
|
||||
import { beforeAll, describe, expect, it } from "vitest";
|
||||
import plugin from "./index.js";
|
||||
import { getComfyConfigForTesting } from "./test-support.js";
|
||||
import { isComfyCapabilityConfigured } from "./workflow-runtime.js";
|
||||
|
||||
const LIVE =
|
||||
@@ -123,9 +122,4 @@ describeLive("comfy live", () => {
|
||||
expect(result.tracks[0]?.mimeType.startsWith("audio/")).toBe(true);
|
||||
expect(result.tracks[0]?.buffer.byteLength).toBeGreaterThan(512);
|
||||
}, 180_000);
|
||||
|
||||
it("documents the effective comfy config shape for live debugging", () => {
|
||||
const comfyConfig = getComfyConfigForTesting(cfg as never);
|
||||
expect(typeof comfyConfig).toBe("object");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Comfy tests cover image generation provider plugin behavior.
|
||||
import type { LookupAddress } from "node:dns";
|
||||
import { MAX_TIMER_TIMEOUT_MS } from "openclaw/plugin-sdk/number-runtime";
|
||||
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { buildComfyImageGenerationProvider } from "./image-generation-provider.js";
|
||||
import {
|
||||
@@ -11,12 +10,23 @@ import {
|
||||
mockComfyProviderApiKey,
|
||||
parseComfyJsonBody,
|
||||
} from "./test-helpers.js";
|
||||
import { setComfyFetchGuardForTesting } from "./test-support.js";
|
||||
|
||||
const { fetchWithSsrFGuardMock } = vi.hoisted(() => ({
|
||||
type FetchWithSsrFGuard = (typeof import("openclaw/plugin-sdk/ssrf-runtime"))["fetchWithSsrFGuard"];
|
||||
|
||||
const { fetchWithSsrFGuardMock, ssrfGuardState } = vi.hoisted(() => ({
|
||||
fetchWithSsrFGuardMock: vi.fn(),
|
||||
ssrfGuardState: {} as { actual?: FetchWithSsrFGuard },
|
||||
}));
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/ssrf-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/ssrf-runtime")>();
|
||||
ssrfGuardState.actual = actual.fetchWithSsrFGuard;
|
||||
return {
|
||||
...actual,
|
||||
fetchWithSsrFGuard: fetchWithSsrFGuardMock,
|
||||
};
|
||||
});
|
||||
|
||||
type FetchGuardRequest = {
|
||||
url?: unknown;
|
||||
auditContext?: unknown;
|
||||
@@ -28,7 +38,7 @@ type FetchGuardRequest = {
|
||||
body?: BodyInit | null;
|
||||
};
|
||||
};
|
||||
type RealGuardParams = Parameters<typeof fetchWithSsrFGuard>[0];
|
||||
type RealGuardParams = Parameters<FetchWithSsrFGuard>[0];
|
||||
type RealGuardFetchImpl = NonNullable<RealGuardParams["fetchImpl"]>;
|
||||
type RealGuardLookupFn = NonNullable<RealGuardParams["lookupFn"]>;
|
||||
type RealGuardHarness = {
|
||||
@@ -206,9 +216,13 @@ function installRealComfyFetchGuard(options: RealComfyFetchOptions): RealGuardHa
|
||||
});
|
||||
};
|
||||
|
||||
setComfyFetchGuardForTesting(async (params) => {
|
||||
const actualFetchWithSsrFGuard = ssrfGuardState.actual;
|
||||
if (!actualFetchWithSsrFGuard) {
|
||||
throw new Error("expected actual SSRF guard");
|
||||
}
|
||||
fetchWithSsrFGuardMock.mockImplementation(async (params) => {
|
||||
guardCalls.push(params);
|
||||
return await fetchWithSsrFGuard({
|
||||
return await actualFetchWithSsrFGuard({
|
||||
...params,
|
||||
fetchImpl,
|
||||
lookupFn,
|
||||
@@ -219,11 +233,12 @@ function installRealComfyFetchGuard(options: RealComfyFetchOptions): RealGuardHa
|
||||
|
||||
describe("comfy image-generation provider", () => {
|
||||
beforeEach(() => {
|
||||
fetchWithSsrFGuardMock.mockReset();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
setComfyFetchGuardForTesting(null);
|
||||
fetchWithSsrFGuardMock.mockReset();
|
||||
vi.unstubAllEnvs();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
@@ -353,7 +368,6 @@ describe("comfy image-generation provider", () => {
|
||||
});
|
||||
|
||||
it("submits a local workflow, waits for history, and downloads images", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
fetchWithSsrFGuardMock
|
||||
.mockResolvedValueOnce({
|
||||
response: new Response(JSON.stringify({ prompt_id: "local-prompt-1" }), {
|
||||
@@ -441,7 +455,6 @@ describe("comfy image-generation provider", () => {
|
||||
});
|
||||
|
||||
it("honors local private-network access for service-discovery hostnames", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
mockLocalImageResponses("compose-prompt-1");
|
||||
|
||||
const provider = buildComfyImageGenerationProvider();
|
||||
@@ -468,7 +481,6 @@ describe("comfy image-generation provider", () => {
|
||||
});
|
||||
|
||||
it("keeps local public-looking hostnames strict without explicit private-network access", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
mockLocalImageResponses("public-host-prompt-1");
|
||||
|
||||
const provider = buildComfyImageGenerationProvider();
|
||||
@@ -492,7 +504,6 @@ describe("comfy image-generation provider", () => {
|
||||
});
|
||||
|
||||
it("keeps cloud service-discovery hostnames strict without explicit private-network access", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
mockComfyCloudJobResponses(fetchWithSsrFGuardMock, {
|
||||
body: Buffer.from("cloud-data"),
|
||||
contentType: "image/png",
|
||||
@@ -525,7 +536,6 @@ describe("comfy image-generation provider", () => {
|
||||
});
|
||||
|
||||
it("honors explicit cloud private-network access for service-discovery hostnames", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
mockComfyCloudJobResponses(fetchWithSsrFGuardMock, {
|
||||
body: Buffer.from("cloud-data"),
|
||||
contentType: "image/png",
|
||||
@@ -787,7 +797,6 @@ describe("comfy image-generation provider", () => {
|
||||
});
|
||||
|
||||
it("caps oversized local workflow timeouts", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
const nowSpy = vi.spyOn(Date, "now");
|
||||
nowSpy
|
||||
.mockReturnValueOnce(0)
|
||||
@@ -836,7 +845,6 @@ describe("comfy image-generation provider", () => {
|
||||
});
|
||||
|
||||
it("rejects generated image downloads that exceed the configured media cap", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
fetchWithSsrFGuardMock
|
||||
.mockResolvedValueOnce({
|
||||
response: new Response(JSON.stringify({ prompt_id: "local-prompt-1" }), {
|
||||
@@ -893,7 +901,6 @@ describe("comfy image-generation provider", () => {
|
||||
});
|
||||
|
||||
it("reports malformed local workflow submit JSON as a provider error", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
const release = vi.fn(async () => {});
|
||||
fetchWithSsrFGuardMock.mockResolvedValueOnce({
|
||||
response: new Response("{ nope", {
|
||||
@@ -923,7 +930,6 @@ describe("comfy image-generation provider", () => {
|
||||
});
|
||||
|
||||
it("bounds oversized local workflow submit responses and releases the request", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
const chunk = new Uint8Array(1024 * 1024);
|
||||
const totalBytes = 32 * chunk.length;
|
||||
let bytesPulled = 0;
|
||||
@@ -971,7 +977,6 @@ describe("comfy image-generation provider", () => {
|
||||
});
|
||||
|
||||
it("uploads reference images for local edit workflows", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
fetchWithSsrFGuardMock
|
||||
.mockResolvedValueOnce({
|
||||
response: new Response(JSON.stringify({ name: "upload.png" }), {
|
||||
@@ -1059,7 +1064,6 @@ describe("comfy image-generation provider", () => {
|
||||
|
||||
it("uses cloud endpoints, auth headers, and partner-node extra_data", async () => {
|
||||
mockComfyProviderApiKey();
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
mockComfyCloudJobResponses(fetchWithSsrFGuardMock, {
|
||||
body: Buffer.from("cloud-data"),
|
||||
contentType: "image/png",
|
||||
@@ -1120,7 +1124,6 @@ describe("comfy image-generation provider", () => {
|
||||
|
||||
it("uses plugin config env SecretRef auth for cloud workflows", async () => {
|
||||
vi.stubEnv("COMFY_TEST_API_KEY", "comfy-secret-ref-key");
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
mockComfyCloudJobResponses(fetchWithSsrFGuardMock, {
|
||||
body: Buffer.from("cloud-data"),
|
||||
contentType: "image/png",
|
||||
@@ -1158,7 +1161,6 @@ describe("comfy image-generation provider", () => {
|
||||
it("uses provider auth fallback for cloud workflows without plugin config API keys", async () => {
|
||||
vi.stubEnv("COMFY_API_KEY", "stale-env-key");
|
||||
mockComfyProviderApiKey("profile-key");
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
mockComfyCloudJobResponses(fetchWithSsrFGuardMock, {
|
||||
body: Buffer.from("cloud-data"),
|
||||
contentType: "image/png",
|
||||
|
||||
@@ -2,15 +2,19 @@
|
||||
import { expectExplicitMusicGenerationCapabilities } from "openclaw/plugin-sdk/provider-test-contracts";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { buildComfyMusicGenerationProvider } from "./music-generation-provider.js";
|
||||
import { setComfyFetchGuardForTesting } from "./test-support.js";
|
||||
|
||||
const { fetchWithSsrFGuardMock } = vi.hoisted(() => ({
|
||||
fetchWithSsrFGuardMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/ssrf-runtime", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("openclaw/plugin-sdk/ssrf-runtime")>()),
|
||||
fetchWithSsrFGuard: fetchWithSsrFGuardMock,
|
||||
}));
|
||||
|
||||
describe("comfy music-generation provider", () => {
|
||||
afterEach(() => {
|
||||
setComfyFetchGuardForTesting(null);
|
||||
fetchWithSsrFGuardMock.mockReset();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
@@ -23,7 +27,6 @@ describe("comfy music-generation provider", () => {
|
||||
});
|
||||
|
||||
it("runs a music workflow and returns audio outputs", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
fetchWithSsrFGuardMock
|
||||
.mockResolvedValueOnce({
|
||||
response: new Response(JSON.stringify({ prompt_id: "music-job-1" }), {
|
||||
@@ -101,7 +104,6 @@ describe("comfy music-generation provider", () => {
|
||||
});
|
||||
|
||||
it("rejects generated music downloads that exceed the configured media cap", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
fetchWithSsrFGuardMock
|
||||
.mockResolvedValueOnce({
|
||||
response: new Response(JSON.stringify({ prompt_id: "music-job-1" }), {
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import type { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
|
||||
type ComfyTestApi = {
|
||||
getConfig: (cfg?: unknown) => Record<string, unknown>;
|
||||
setFetchGuard: (impl: typeof fetchWithSsrFGuard | null) => void;
|
||||
};
|
||||
|
||||
function getComfyTestApi(): ComfyTestApi {
|
||||
const api = Reflect.get(globalThis, Symbol.for("openclaw.comfyTestApi"));
|
||||
if (!api) {
|
||||
throw new Error("Comfy test API is unavailable");
|
||||
}
|
||||
return api as ComfyTestApi;
|
||||
}
|
||||
|
||||
export function setComfyFetchGuardForTesting(impl: typeof fetchWithSsrFGuard | null): void {
|
||||
getComfyTestApi().setFetchGuard(impl);
|
||||
}
|
||||
|
||||
export function getComfyConfigForTesting(cfg?: unknown): Record<string, unknown> {
|
||||
return getComfyTestApi().getConfig(cfg);
|
||||
}
|
||||
@@ -7,13 +7,17 @@ import {
|
||||
mockComfyProviderApiKey,
|
||||
parseComfyJsonBody,
|
||||
} from "./test-helpers.js";
|
||||
import { setComfyFetchGuardForTesting } from "./test-support.js";
|
||||
import { buildComfyVideoGenerationProvider } from "./video-generation-provider.js";
|
||||
|
||||
const { fetchWithSsrFGuardMock } = vi.hoisted(() => ({
|
||||
fetchWithSsrFGuardMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/ssrf-runtime", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("openclaw/plugin-sdk/ssrf-runtime")>()),
|
||||
fetchWithSsrFGuard: fetchWithSsrFGuardMock,
|
||||
}));
|
||||
|
||||
function parseJsonBody(call: number): Record<string, unknown> {
|
||||
return parseComfyJsonBody(fetchWithSsrFGuardMock, call);
|
||||
}
|
||||
@@ -89,11 +93,12 @@ function generateLocalVideo(outputNodeId?: string) {
|
||||
|
||||
describe("comfy video-generation provider", () => {
|
||||
beforeEach(() => {
|
||||
fetchWithSsrFGuardMock.mockReset();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
setComfyFetchGuardForTesting(null);
|
||||
fetchWithSsrFGuardMock.mockReset();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
@@ -118,7 +123,6 @@ describe("comfy video-generation provider", () => {
|
||||
});
|
||||
|
||||
it("submits a local workflow, waits for history, and downloads videos", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
fetchWithSsrFGuardMock
|
||||
.mockResolvedValueOnce({
|
||||
response: new Response(JSON.stringify({ prompt_id: "local-video-1" }), {
|
||||
@@ -205,7 +209,6 @@ describe("comfy video-generation provider", () => {
|
||||
});
|
||||
|
||||
it("returns only MP4 video entries from mixed images buckets", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
mockLocalVideoResponses({
|
||||
promptId: "local-video-mixed",
|
||||
outputs: {
|
||||
@@ -243,7 +246,6 @@ describe("comfy video-generation provider", () => {
|
||||
});
|
||||
|
||||
it("accepts uppercase WEBM names from the images bucket", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
mockLocalVideoResponses({
|
||||
promptId: "local-video-webm",
|
||||
outputs: {
|
||||
@@ -272,7 +274,6 @@ describe("comfy video-generation provider", () => {
|
||||
});
|
||||
|
||||
it("rejects images-only workflow output for video generation", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
mockLocalVideoResponses({
|
||||
promptId: "local-video-images-only",
|
||||
outputs: {
|
||||
@@ -292,7 +293,6 @@ describe("comfy video-generation provider", () => {
|
||||
});
|
||||
|
||||
it("preserves legacy videos bucket output without filename filtering", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
mockLocalVideoResponses({
|
||||
promptId: "local-video-legacy",
|
||||
outputs: {
|
||||
@@ -318,7 +318,6 @@ describe("comfy video-generation provider", () => {
|
||||
});
|
||||
|
||||
it("rejects generated video downloads that exceed the configured media cap", async () => {
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
fetchWithSsrFGuardMock
|
||||
.mockResolvedValueOnce({
|
||||
response: new Response(JSON.stringify({ prompt_id: "local-video-1" }), {
|
||||
@@ -378,7 +377,6 @@ describe("comfy video-generation provider", () => {
|
||||
|
||||
it("uses cloud endpoints for video workflows", async () => {
|
||||
mockComfyProviderApiKey();
|
||||
setComfyFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
mockComfyCloudJobResponses(fetchWithSsrFGuardMock, {
|
||||
body: Buffer.from("cloud-video-data"),
|
||||
contentType: "video/mp4",
|
||||
|
||||
@@ -111,19 +111,6 @@ type ComfyWorkflowResult = {
|
||||
outputNodeIds: string[];
|
||||
};
|
||||
|
||||
let comfyFetchGuard = fetchWithSsrFGuard;
|
||||
|
||||
function setComfyFetchGuardForTesting(impl: typeof fetchWithSsrFGuard | null): void {
|
||||
comfyFetchGuard = impl ?? fetchWithSsrFGuard;
|
||||
}
|
||||
|
||||
if (process.env.VITEST === "true") {
|
||||
Reflect.set(globalThis, Symbol.for("openclaw.comfyTestApi"), {
|
||||
getConfig: getComfyConfig,
|
||||
setFetchGuard: setComfyFetchGuardForTesting,
|
||||
});
|
||||
}
|
||||
|
||||
function readConfigInteger(config: ComfyProviderConfig, key: string): number | undefined {
|
||||
const value = config[key];
|
||||
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : undefined;
|
||||
@@ -327,7 +314,7 @@ async function readJsonResponse<T>(params: {
|
||||
auditContext: string;
|
||||
errorPrefix: string;
|
||||
}): Promise<T> {
|
||||
const { response, release } = await comfyFetchGuard({
|
||||
const { response, release } = await fetchWithSsrFGuard({
|
||||
url: params.url,
|
||||
init: params.init,
|
||||
timeoutMs: params.timeoutMs,
|
||||
@@ -581,7 +568,7 @@ async function downloadOutputFile(params: {
|
||||
const viewPath = params.mode === "cloud" ? "/api/view" : "/view";
|
||||
const auditContext = `comfy-${params.capability}-download`;
|
||||
|
||||
const firstResponse = await comfyFetchGuard({
|
||||
const firstResponse = await fetchWithSsrFGuard({
|
||||
url: `${params.baseUrl}${viewPath}?${query.toString()}`,
|
||||
init: {
|
||||
method: "GET",
|
||||
|
||||
@@ -8,8 +8,12 @@ const { fetchWithSsrFGuardMock } = vi.hoisted(() => ({
|
||||
fetchWithSsrFGuardMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/ssrf-runtime", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("openclaw/plugin-sdk/ssrf-runtime")>()),
|
||||
fetchWithSsrFGuard: fetchWithSsrFGuardMock,
|
||||
}));
|
||||
|
||||
import { buildFalImageGenerationProvider } from "./image-generation-provider.js";
|
||||
import { setFalFetchGuardForTesting } from "./test-support.js";
|
||||
|
||||
const falApiKey = { apiKey: "fal-test-key", source: "env", mode: "api-key" } as const;
|
||||
|
||||
@@ -75,14 +79,14 @@ describe("fal image-generation provider", () => {
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
fetchWithSsrFGuardMock.mockReset();
|
||||
vi.clearAllMocks();
|
||||
vi.spyOn(providerAuth, "resolveApiKeyForProvider").mockResolvedValue(falApiKey);
|
||||
setFalFetchGuardForTesting(fetchWithSsrFGuardMock);
|
||||
provider = buildFalImageGenerationProvider();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
setFalFetchGuardForTesting(null);
|
||||
fetchWithSsrFGuardMock.mockReset();
|
||||
vi.useRealTimers();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
@@ -154,18 +154,6 @@ type FalNetworkPolicy = {
|
||||
trustedDownloadPolicy?: SsrFPolicy;
|
||||
};
|
||||
|
||||
let falFetchGuard = fetchWithSsrFGuard;
|
||||
|
||||
function setFalFetchGuardForTesting(impl: typeof fetchWithSsrFGuard | null): void {
|
||||
falFetchGuard = impl ?? fetchWithSsrFGuard;
|
||||
}
|
||||
|
||||
if (process.env.VITEST === "true") {
|
||||
const key = Symbol.for("openclaw.falTestApi");
|
||||
const api = (Reflect.get(globalThis, key) as Record<string, unknown> | undefined) ?? {};
|
||||
Reflect.set(globalThis, key, { ...api, setImageFetchGuard: setFalFetchGuardForTesting });
|
||||
}
|
||||
|
||||
function matchesTrustedHostSuffix(hostname: string, trustedSuffix: string): boolean {
|
||||
const normalizedHost = normalizeLowercaseStringOrEmpty(hostname);
|
||||
const normalizedSuffix = normalizeLowercaseStringOrEmpty(trustedSuffix);
|
||||
@@ -609,7 +597,7 @@ async function fetchImageBuffer(
|
||||
return undefined;
|
||||
}
|
||||
})();
|
||||
const { response, release } = await falFetchGuard({
|
||||
const { response, release } = await fetchWithSsrFGuard({
|
||||
url,
|
||||
timeoutMs: resolveProviderOperationTimeoutMs({
|
||||
deadline,
|
||||
@@ -782,7 +770,7 @@ export function buildFalImageGenerationProvider(): ImageGenerationProvider {
|
||||
inputImages: req.inputImages ?? [],
|
||||
});
|
||||
}
|
||||
const { response, release } = await falFetchGuard({
|
||||
const { response, release } = await fetchWithSsrFGuard({
|
||||
url: `${baseUrl}/${model}`,
|
||||
init: {
|
||||
method: "POST",
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import type { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
|
||||
type FalTestApi = {
|
||||
setImageFetchGuard: (impl: typeof fetchWithSsrFGuard | null) => void;
|
||||
setVideoFetchGuard: (impl: typeof fetchWithSsrFGuard | null) => void;
|
||||
};
|
||||
|
||||
function getFalTestApi(): FalTestApi {
|
||||
const api = Reflect.get(globalThis, Symbol.for("openclaw.falTestApi"));
|
||||
if (!api) {
|
||||
throw new Error("Fal test API is unavailable");
|
||||
}
|
||||
return api as FalTestApi;
|
||||
}
|
||||
|
||||
export function setFalFetchGuardForTesting(impl: typeof fetchWithSsrFGuard | null): void {
|
||||
getFalTestApi().setImageFetchGuard(impl);
|
||||
}
|
||||
|
||||
export function setFalVideoFetchGuardForTesting(impl: typeof fetchWithSsrFGuard | null): void {
|
||||
getFalTestApi().setVideoFetchGuard(impl);
|
||||
}
|
||||
@@ -4,15 +4,21 @@ import * as providerAuth from "openclaw/plugin-sdk/provider-auth-runtime";
|
||||
import * as providerHttp from "openclaw/plugin-sdk/provider-http";
|
||||
import { expectExplicitVideoGenerationCapabilities } from "openclaw/plugin-sdk/provider-test-contracts";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { setFalVideoFetchGuardForTesting } from "./test-support.js";
|
||||
import { buildFalVideoGenerationProvider } from "./video-generation-provider.js";
|
||||
|
||||
const { fetchGuardMock } = vi.hoisted(() => ({
|
||||
fetchGuardMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/ssrf-runtime", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("openclaw/plugin-sdk/ssrf-runtime")>()),
|
||||
fetchWithSsrFGuard: fetchGuardMock,
|
||||
}));
|
||||
|
||||
function createMockRequestConfig() {
|
||||
return {} as ReturnType<typeof providerHttp.resolveProviderHttpRequestConfig>["requestConfig"];
|
||||
}
|
||||
describe("fal video generation provider", () => {
|
||||
const fetchGuardMock = vi.fn();
|
||||
|
||||
function mockFalProviderRuntime() {
|
||||
vi.spyOn(providerAuth, "resolveApiKeyForProvider").mockResolvedValue({
|
||||
apiKey: "fal-key",
|
||||
@@ -30,7 +36,6 @@ describe("fal video generation provider", () => {
|
||||
requestConfig: createMockRequestConfig(),
|
||||
});
|
||||
vi.spyOn(providerHttp, "assertOkOrThrowHttpError").mockResolvedValue(undefined);
|
||||
setFalVideoFetchGuardForTesting(fetchGuardMock as never);
|
||||
}
|
||||
|
||||
function releasedJson(value: unknown) {
|
||||
@@ -109,7 +114,6 @@ describe("fal video generation provider", () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
fetchGuardMock.mockReset();
|
||||
setFalVideoFetchGuardForTesting(null);
|
||||
});
|
||||
|
||||
it("declares explicit mode capabilities", () => {
|
||||
|
||||
@@ -97,18 +97,6 @@ type FalQueueResponse = {
|
||||
};
|
||||
};
|
||||
|
||||
let falFetchGuard = fetchWithSsrFGuard;
|
||||
|
||||
function setFalVideoFetchGuardForTesting(impl: typeof fetchWithSsrFGuard | null): void {
|
||||
falFetchGuard = impl ?? fetchWithSsrFGuard;
|
||||
}
|
||||
|
||||
if (process.env.VITEST === "true") {
|
||||
const key = Symbol.for("openclaw.falTestApi");
|
||||
const api = (Reflect.get(globalThis, key) as Record<string, unknown> | undefined) ?? {};
|
||||
Reflect.set(globalThis, key, { ...api, setVideoFetchGuard: setFalVideoFetchGuardForTesting });
|
||||
}
|
||||
|
||||
function normalizeFalVideoUrl(value: unknown): string | undefined {
|
||||
const normalized = normalizeOptionalString(value);
|
||||
if (!normalized && value !== undefined && value !== null) {
|
||||
@@ -208,7 +196,7 @@ async function downloadFalVideo(
|
||||
policy: SsrFPolicy | undefined,
|
||||
maxBytes: number,
|
||||
): Promise<GeneratedVideoAsset> {
|
||||
const { response, release } = await falFetchGuard({
|
||||
const { response, release } = await fetchWithSsrFGuard({
|
||||
url,
|
||||
timeoutMs: DEFAULT_HTTP_TIMEOUT_MS,
|
||||
policy,
|
||||
@@ -468,7 +456,7 @@ async function fetchFalJson(params: {
|
||||
auditContext: string;
|
||||
errorContext: string;
|
||||
}): Promise<unknown> {
|
||||
const { response, release } = await falFetchGuard({
|
||||
const { response, release } = await fetchWithSsrFGuard({
|
||||
url: params.url,
|
||||
init: params.init,
|
||||
timeoutMs: params.timeoutMs,
|
||||
|
||||
Reference in New Issue
Block a user