test: add fetch mock helper and reaction coverage

This commit is contained in:
Sebastian
2026-02-17 09:01:30 -05:00
parent 0e023e300e
commit cc359d338e
28 changed files with 193 additions and 106 deletions

View File

@@ -4,6 +4,7 @@ import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
import type { ModelDefinitionConfig } from "../../config/types.models.js";
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
import { createOpenClawCodingTools } from "../pi-tools.js";
import { createHostSandboxFsBridge } from "../test-helpers/host-sandbox-fs-bridge.js";
import { __testing, createImageTool, resolveImageModelConfigForTool } from "./image-tool.js";
@@ -47,7 +48,7 @@ function stubMinimaxOkFetch() {
base_resp: { status_code: 0, status_msg: "" },
}),
});
global.fetch = fetch;
global.fetch = withFetchPreconnect(fetch);
vi.stubEnv("MINIMAX_API_KEY", "minimax-test");
return fetch;
}
@@ -414,7 +415,7 @@ describe("image tool implicit imageModel config", () => {
base_resp: { status_code: 0, status_msg: "" },
}),
});
global.fetch = fetch;
global.fetch = withFetchPreconnect(fetch);
vi.stubEnv("MINIMAX_API_KEY", "minimax-test");
const cfg: OpenClawConfig = {
@@ -487,7 +488,7 @@ describe("image tool MiniMax VLM routing", () => {
base_resp: baseResp,
}),
});
global.fetch = fetch;
global.fetch = withFetchPreconnect(fetch);
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-minimax-vlm-"));
vi.stubEnv("MINIMAX_API_KEY", "minimax-test");

View File

@@ -1,5 +1,6 @@
import { describe, expect, it, vi } from "vitest";
import * as logger from "../../logger.js";
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
import {
createBaseWebFetchToolConfig,
installWebFetchSsrfHarness,
@@ -37,7 +38,7 @@ function htmlResponse(body: string): Response {
describe("web_fetch Cloudflare Markdown for Agents", () => {
it("sends Accept header preferring text/markdown", async () => {
const fetchSpy = vi.fn().mockResolvedValue(markdownResponse("# Test Page\n\nHello world."));
global.fetch = fetchSpy;
global.fetch = withFetchPreconnect(fetchSpy);
const tool = createWebFetchTool(baseToolConfig);
@@ -51,7 +52,7 @@ describe("web_fetch Cloudflare Markdown for Agents", () => {
it("uses cf-markdown extractor for text/markdown responses", async () => {
const md = "# CF Markdown\n\nThis is server-rendered markdown.";
const fetchSpy = vi.fn().mockResolvedValue(markdownResponse(md));
global.fetch = fetchSpy;
global.fetch = withFetchPreconnect(fetchSpy);
const tool = createWebFetchTool(baseToolConfig);
@@ -73,7 +74,7 @@ describe("web_fetch Cloudflare Markdown for Agents", () => {
const html =
"<html><body><article><h1>HTML Page</h1><p>Content here.</p></article></body></html>";
const fetchSpy = vi.fn().mockResolvedValue(htmlResponse(html));
global.fetch = fetchSpy;
global.fetch = withFetchPreconnect(fetchSpy);
const tool = createWebFetchTool(baseToolConfig);
@@ -88,7 +89,7 @@ describe("web_fetch Cloudflare Markdown for Agents", () => {
const fetchSpy = vi
.fn()
.mockResolvedValue(markdownResponse("# Tokens Test", { "x-markdown-tokens": "1500" }));
global.fetch = fetchSpy;
global.fetch = withFetchPreconnect(fetchSpy);
const tool = createWebFetchTool(baseToolConfig);
@@ -108,7 +109,7 @@ describe("web_fetch Cloudflare Markdown for Agents", () => {
it("converts markdown to text when extractMode is text", async () => {
const md = "# Heading\n\n**Bold text** and [a link](https://example.com).";
const fetchSpy = vi.fn().mockResolvedValue(markdownResponse(md));
global.fetch = fetchSpy;
global.fetch = withFetchPreconnect(fetchSpy);
const tool = createWebFetchTool(baseToolConfig);
@@ -132,7 +133,7 @@ describe("web_fetch Cloudflare Markdown for Agents", () => {
it("does not log x-markdown-tokens when header is absent", async () => {
const logSpy = vi.spyOn(logger, "logDebug").mockImplementation(() => {});
const fetchSpy = vi.fn().mockResolvedValue(markdownResponse("# No tokens"));
global.fetch = fetchSpy;
global.fetch = withFetchPreconnect(fetchSpy);
const tool = createWebFetchTool(baseToolConfig);

View File

@@ -1,4 +1,5 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
vi.mock("../../infra/net/fetch-guard.js", () => {
return {
@@ -33,7 +34,7 @@ describe("web_fetch firecrawl apiKey normalization", () => {
);
});
global.fetch = fetchSpy;
global.fetch = withFetchPreconnect(fetchSpy);
const { createWebFetchTool } = await import("./web-tools.js");
const tool = createWebFetchTool({

View File

@@ -1,4 +1,5 @@
import { describe, expect, it, vi } from "vitest";
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
import {
createBaseWebFetchToolConfig,
installWebFetchSsrfHarness,
@@ -23,7 +24,7 @@ describe("web_fetch response size limits", () => {
});
const fetchSpy = vi.fn().mockResolvedValue(response);
global.fetch = fetchSpy;
global.fetch = withFetchPreconnect(fetchSpy);
const tool = createWebFetchTool(baseToolConfig);
const result = await tool?.execute?.("call", { url: "https://example.com/stream" });

View File

@@ -1,5 +1,6 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import * as ssrf from "../../infra/net/ssrf.js";
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
const lookupMock = vi.fn();
const resolvePinnedHostname = ssrf.resolvePinnedHostname;
@@ -30,7 +31,7 @@ function textResponse(body: string): Response {
function setMockFetch(impl?: (...args: unknown[]) => unknown) {
const fetchSpy = vi.fn(impl);
global.fetch = fetchSpy as typeof fetch;
global.fetch = withFetchPreconnect(fetchSpy);
return fetchSpy;
}

View File

@@ -1,4 +1,5 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
import { createWebFetchTool, createWebSearchTool } from "./web-tools.js";
function installMockFetch(payload: unknown) {
@@ -8,7 +9,7 @@ function installMockFetch(payload: unknown) {
json: () => Promise.resolve(payload),
} as Response),
);
global.fetch = mockFetch;
global.fetch = withFetchPreconnect(mockFetch);
return mockFetch;
}

View File

@@ -1,5 +1,6 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import * as ssrf from "../../infra/net/ssrf.js";
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
import { createWebFetchTool } from "./web-tools.js";
type MockResponse = {
@@ -92,7 +93,7 @@ function requestUrl(input: RequestInfo | URL): string {
function installMockFetch(impl: (input: RequestInfo | URL) => Promise<Response>) {
const mockFetch = vi.fn(async (input: RequestInfo | URL) => await impl(input));
global.fetch = mockFetch as typeof global.fetch;
global.fetch = withFetchPreconnect(mockFetch);
return mockFetch;
}