refactor(tavily): test proxy endpoints through the client (#140160)

This commit is contained in:
Peter Steinberger 2026-09-06 07:36:03 -07:00 • committed by GitHub
parent 2dcb6e82e2
commit b5b64a8d51
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 29 additions and 26 deletions

View file

@ -6,6 +6,7 @@ import { createStreamingResponse } from "../../test-support/streaming-error-resp
const postTrustedWebToolsJson = vi.fn();
const writeCache = vi.fn();
const assertPluginCapabilitySecretAvailable = vi.fn();
const resolveTavilyBaseUrl = vi.fn(() => "https://api.tavily.com");
vi.mock("openclaw/plugin-sdk/secret-input-runtime", () => ({
assertPluginCapabilitySecretAvailable,
@ -25,7 +26,7 @@ vi.mock("./config.js", () => ({
DEFAULT_TAVILY_BASE_URL: "https://api.tavily.com",
TAVILY_API_KEY_CONFIG_PATH: "plugins.entries.tavily.config.webSearch.apiKey",
resolveTavilyApiKey: () => "test-key",
resolveTavilyBaseUrl: () => "https://api.tavily.com",
resolveTavilyBaseUrl,
resolveTavilySearchTimeoutSeconds: () => 30,
resolveTavilyExtractTimeoutSeconds: () => 60,
}));
@ -42,6 +43,7 @@ describe("tavily client X-Client-Source header", () => {
assertPluginCapabilitySecretAvailable.mockReset();
postTrustedWebToolsJson.mockReset();
writeCache.mockReset();
resolveTavilyBaseUrl.mockReset().mockReturnValue("https://api.tavily.com");
postTrustedWebToolsJson.mockImplementation(
async (_params: unknown, parse: (r: Response) => Promise<unknown>) =>
parse(Response.json({ results: [] })),
@ -70,6 +72,32 @@ describe("tavily client X-Client-Source header", () => {
},
);
it("appends endpoints to reverse-proxy base urls", async () => {
resolveTavilyBaseUrl.mockReturnValueOnce("https://proxy.example/api/tavily");
await runTavilySearch({ query: "proxy search" });
resolveTavilyBaseUrl.mockReturnValueOnce("https://proxy.example/api/tavily/");
await runTavilyExtract({ urls: ["https://example.com"] });
expect(postTrustedWebToolsJson).toHaveBeenCalledTimes(2);
expect(postTrustedWebToolsJson.mock.calls[0]?.[0]?.url).toBe(
"https://proxy.example/api/tavily/search",
);
expect(postTrustedWebToolsJson.mock.calls[1]?.[0]?.url).toBe(
"https://proxy.example/api/tavily/extract",
);
});
it("falls back to the default host for invalid base urls", async () => {
resolveTavilyBaseUrl.mockReturnValueOnce("not a url");
await runTavilySearch({ query: "invalid base URL" });
resolveTavilyBaseUrl.mockReturnValueOnce("");
await runTavilyExtract({ urls: ["https://example.com"] });
expect(postTrustedWebToolsJson).toHaveBeenCalledTimes(2);
expect(postTrustedWebToolsJson.mock.calls[0]?.[0]?.url).toBe("https://api.tavily.com/search");
expect(postTrustedWebToolsJson.mock.calls[1]?.[0]?.url).toBe("https://api.tavily.com/extract");
});
it("runTavilySearch sends X-Client-Source: openclaw", async () => {
await runTavilySearch({ query: "test query" });

View file

@ -416,7 +416,3 @@ export async function runTavilyExtract(
);
return result;
}
export const testing = {
resolveEndpoint,
};

View file

@ -47,7 +47,6 @@ describe("tavily tools", () => {
let createTavilyContractWebSearchProvider: typeof import("../web-search-contract-api.js").createTavilyWebSearchProvider;
let createTavilySearchTool: typeof import("./tavily-search-tool.js").createTavilySearchTool;
let createTavilyExtractTool: typeof import("./tavily-extract-tool.js").createTavilyExtractTool;
let tavilyClientTesting: typeof import("./tavily-client.js").testing;
let tavilyPlugin: typeof import("../index.js").default;
beforeAll(async () => {
@ -56,8 +55,6 @@ describe("tavily tools", () => {
await import("../web-search-contract-api.js"));
({ createTavilySearchTool } = await import("./tavily-search-tool.js"));
({ createTavilyExtractTool } = await import("./tavily-extract-tool.js"));
({ testing: tavilyClientTesting } =
await vi.importActual<typeof import("./tavily-client.js")>("./tavily-client.js"));
({ default: tavilyPlugin } = await import("../index.js"));
});
@ -507,22 +504,4 @@ describe("tavily tools", () => {
expect(resolveTavilySearchTimeoutSeconds(0)).toBe(30);
expect(resolveTavilyExtractTimeoutSeconds(Number.NaN)).toBe(60);
});
it("appends endpoints to reverse-proxy base urls", () => {
expect(tavilyClientTesting.resolveEndpoint("https://proxy.example/api/tavily", "/search")).toBe(
"https://proxy.example/api/tavily/search",
);
expect(
tavilyClientTesting.resolveEndpoint("https://proxy.example/api/tavily/", "/extract"),
).toBe("https://proxy.example/api/tavily/extract");
});
it("falls back to the default host for invalid base urls", () => {
expect(tavilyClientTesting.resolveEndpoint("not a url", "/search")).toBe(
"https://api.tavily.com/search",
);
expect(tavilyClientTesting.resolveEndpoint("", "/extract")).toBe(
"https://api.tavily.com/extract",
);
});
});