mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 23:31:24 +00:00
refactor(test): table-drive web tool defaults checks
This commit is contained in:
@@ -29,6 +29,38 @@ function createPerplexitySearchTool(perplexityConfig?: { apiKey?: string; baseUr
|
||||
});
|
||||
}
|
||||
|
||||
function parseFirstRequestBody(mockFetch: ReturnType<typeof installMockFetch>) {
|
||||
const request = mockFetch.mock.calls[0]?.[1] as RequestInit | undefined;
|
||||
const requestBody = request?.body;
|
||||
return JSON.parse(typeof requestBody === "string" ? requestBody : "{}") as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
}
|
||||
|
||||
function installPerplexitySuccessFetch() {
|
||||
return installMockFetch({
|
||||
choices: [{ message: { content: "ok" } }],
|
||||
citations: [],
|
||||
});
|
||||
}
|
||||
|
||||
async function executePerplexitySearch(
|
||||
query: string,
|
||||
options?: {
|
||||
perplexityConfig?: { apiKey?: string; baseUrl?: string };
|
||||
freshness?: string;
|
||||
},
|
||||
) {
|
||||
const mockFetch = installPerplexitySuccessFetch();
|
||||
const tool = createPerplexitySearchTool(options?.perplexityConfig);
|
||||
await tool?.execute?.(
|
||||
1,
|
||||
options?.freshness ? { query, freshness: options.freshness } : { query },
|
||||
);
|
||||
return mockFetch;
|
||||
}
|
||||
|
||||
describe("web tools defaults", () => {
|
||||
it("enables web_fetch by default (non-sandbox)", () => {
|
||||
const tool = createWebFetchTool({ config: {}, sandboxed: false });
|
||||
@@ -62,43 +94,30 @@ describe("web_search country and language parameters", () => {
|
||||
global.fetch = priorFetch;
|
||||
});
|
||||
|
||||
it("should pass country parameter to Brave API", async () => {
|
||||
async function runBraveSearchAndGetUrl(
|
||||
params: Partial<{
|
||||
country: string;
|
||||
search_lang: string;
|
||||
ui_lang: string;
|
||||
freshness: string;
|
||||
}>,
|
||||
) {
|
||||
const mockFetch = installMockFetch({ web: { results: [] } });
|
||||
const tool = createWebSearchTool({ config: undefined, sandboxed: true });
|
||||
expect(tool).not.toBeNull();
|
||||
|
||||
await tool?.execute?.(1, { query: "test", country: "DE" });
|
||||
|
||||
await tool?.execute?.(1, { query: "test", ...params });
|
||||
expect(mockFetch).toHaveBeenCalled();
|
||||
const url = new URL(mockFetch.mock.calls[0][0] as string);
|
||||
expect(url.searchParams.get("country")).toBe("DE");
|
||||
});
|
||||
return new URL(mockFetch.mock.calls[0][0] as string);
|
||||
}
|
||||
|
||||
it("should pass search_lang parameter to Brave API", async () => {
|
||||
const mockFetch = installMockFetch({ web: { results: [] } });
|
||||
const tool = createWebSearchTool({ config: undefined, sandboxed: true });
|
||||
await tool?.execute?.(1, { query: "test", search_lang: "de" });
|
||||
|
||||
const url = new URL(mockFetch.mock.calls[0][0] as string);
|
||||
expect(url.searchParams.get("search_lang")).toBe("de");
|
||||
});
|
||||
|
||||
it("should pass ui_lang parameter to Brave API", async () => {
|
||||
const mockFetch = installMockFetch({ web: { results: [] } });
|
||||
const tool = createWebSearchTool({ config: undefined, sandboxed: true });
|
||||
await tool?.execute?.(1, { query: "test", ui_lang: "de" });
|
||||
|
||||
const url = new URL(mockFetch.mock.calls[0][0] as string);
|
||||
expect(url.searchParams.get("ui_lang")).toBe("de");
|
||||
});
|
||||
|
||||
it("should pass freshness parameter to Brave API", async () => {
|
||||
const mockFetch = installMockFetch({ web: { results: [] } });
|
||||
const tool = createWebSearchTool({ config: undefined, sandboxed: true });
|
||||
await tool?.execute?.(1, { query: "test", freshness: "pw" });
|
||||
|
||||
const url = new URL(mockFetch.mock.calls[0][0] as string);
|
||||
expect(url.searchParams.get("freshness")).toBe("pw");
|
||||
it.each([
|
||||
{ key: "country", value: "DE" },
|
||||
{ key: "search_lang", value: "de" },
|
||||
{ key: "ui_lang", value: "de" },
|
||||
{ key: "freshness", value: "pw" },
|
||||
])("passes $key parameter to Brave API", async ({ key, value }) => {
|
||||
const url = await runBraveSearchAndGetUrl({ [key]: value });
|
||||
expect(url.searchParams.get(key)).toBe(value);
|
||||
});
|
||||
|
||||
it("rejects invalid freshness values", async () => {
|
||||
@@ -120,108 +139,72 @@ describe("web_search perplexity baseUrl defaults", () => {
|
||||
global.fetch = priorFetch;
|
||||
});
|
||||
|
||||
it("defaults to Perplexity direct when PERPLEXITY_API_KEY is set", async () => {
|
||||
vi.stubEnv("PERPLEXITY_API_KEY", "pplx-test");
|
||||
const mockFetch = installMockFetch({
|
||||
choices: [{ message: { content: "ok" } }],
|
||||
citations: [],
|
||||
});
|
||||
const tool = createPerplexitySearchTool();
|
||||
await tool?.execute?.(1, { query: "test-openrouter" });
|
||||
|
||||
expect(mockFetch).toHaveBeenCalled();
|
||||
expect(mockFetch.mock.calls[0]?.[0]).toBe("https://api.perplexity.ai/chat/completions");
|
||||
const request = mockFetch.mock.calls[0]?.[1] as RequestInit | undefined;
|
||||
const requestBody = request?.body;
|
||||
const body = JSON.parse(typeof requestBody === "string" ? requestBody : "{}") as {
|
||||
model?: string;
|
||||
};
|
||||
expect(body.model).toBe("sonar-pro");
|
||||
});
|
||||
|
||||
it("passes freshness to Perplexity provider as search_recency_filter", async () => {
|
||||
vi.stubEnv("PERPLEXITY_API_KEY", "pplx-test");
|
||||
const mockFetch = installMockFetch({
|
||||
choices: [{ message: { content: "ok" } }],
|
||||
citations: [],
|
||||
const mockFetch = await executePerplexitySearch("perplexity-freshness-test", {
|
||||
freshness: "pw",
|
||||
});
|
||||
const tool = createPerplexitySearchTool();
|
||||
await tool?.execute?.(1, { query: "perplexity-freshness-test", freshness: "pw" });
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledOnce();
|
||||
const body = JSON.parse(mockFetch.mock.calls[0][1].body as string);
|
||||
const body = parseFirstRequestBody(mockFetch);
|
||||
expect(body.search_recency_filter).toBe("week");
|
||||
});
|
||||
|
||||
it("defaults to OpenRouter when OPENROUTER_API_KEY is set", async () => {
|
||||
vi.stubEnv("PERPLEXITY_API_KEY", "");
|
||||
vi.stubEnv("OPENROUTER_API_KEY", "sk-or-test");
|
||||
const mockFetch = installMockFetch({
|
||||
choices: [{ message: { content: "ok" } }],
|
||||
citations: [],
|
||||
});
|
||||
const tool = createPerplexitySearchTool();
|
||||
await tool?.execute?.(1, { query: "test-openrouter-env" });
|
||||
it.each([
|
||||
{
|
||||
name: "defaults to Perplexity direct when PERPLEXITY_API_KEY is set",
|
||||
env: { perplexity: "pplx-test" },
|
||||
query: "test-openrouter",
|
||||
expectedUrl: "https://api.perplexity.ai/chat/completions",
|
||||
expectedModel: "sonar-pro",
|
||||
},
|
||||
{
|
||||
name: "defaults to OpenRouter when OPENROUTER_API_KEY is set",
|
||||
env: { perplexity: "", openrouter: "sk-or-test" },
|
||||
query: "test-openrouter-env",
|
||||
expectedUrl: "https://openrouter.ai/api/v1/chat/completions",
|
||||
expectedModel: "perplexity/sonar-pro",
|
||||
},
|
||||
{
|
||||
name: "prefers PERPLEXITY_API_KEY when both env keys are set",
|
||||
env: { perplexity: "pplx-test", openrouter: "sk-or-test" },
|
||||
query: "test-both-env",
|
||||
expectedUrl: "https://api.perplexity.ai/chat/completions",
|
||||
},
|
||||
{
|
||||
name: "uses configured baseUrl even when PERPLEXITY_API_KEY is set",
|
||||
env: { perplexity: "pplx-test" },
|
||||
query: "test-config-baseurl",
|
||||
perplexityConfig: { baseUrl: "https://example.com/pplx" },
|
||||
expectedUrl: "https://example.com/pplx/chat/completions",
|
||||
},
|
||||
{
|
||||
name: "defaults to Perplexity direct when apiKey looks like Perplexity",
|
||||
query: "test-config-apikey",
|
||||
perplexityConfig: { apiKey: "pplx-config" },
|
||||
expectedUrl: "https://api.perplexity.ai/chat/completions",
|
||||
},
|
||||
{
|
||||
name: "defaults to OpenRouter when apiKey looks like OpenRouter",
|
||||
query: "test-openrouter-config",
|
||||
perplexityConfig: { apiKey: "sk-or-v1-test" },
|
||||
expectedUrl: "https://openrouter.ai/api/v1/chat/completions",
|
||||
},
|
||||
])("$name", async ({ env, query, perplexityConfig, expectedUrl, expectedModel }) => {
|
||||
if (env?.perplexity !== undefined) {
|
||||
vi.stubEnv("PERPLEXITY_API_KEY", env.perplexity);
|
||||
}
|
||||
if (env?.openrouter !== undefined) {
|
||||
vi.stubEnv("OPENROUTER_API_KEY", env.openrouter);
|
||||
}
|
||||
|
||||
const mockFetch = await executePerplexitySearch(query, { perplexityConfig });
|
||||
expect(mockFetch).toHaveBeenCalled();
|
||||
expect(mockFetch.mock.calls[0]?.[0]).toBe("https://openrouter.ai/api/v1/chat/completions");
|
||||
const request = mockFetch.mock.calls[0]?.[1] as RequestInit | undefined;
|
||||
const requestBody = request?.body;
|
||||
const body = JSON.parse(typeof requestBody === "string" ? requestBody : "{}") as {
|
||||
model?: string;
|
||||
};
|
||||
expect(body.model).toBe("perplexity/sonar-pro");
|
||||
});
|
||||
|
||||
it("prefers PERPLEXITY_API_KEY when both env keys are set", async () => {
|
||||
vi.stubEnv("PERPLEXITY_API_KEY", "pplx-test");
|
||||
vi.stubEnv("OPENROUTER_API_KEY", "sk-or-test");
|
||||
const mockFetch = installMockFetch({
|
||||
choices: [{ message: { content: "ok" } }],
|
||||
citations: [],
|
||||
});
|
||||
const tool = createPerplexitySearchTool();
|
||||
await tool?.execute?.(1, { query: "test-both-env" });
|
||||
|
||||
expect(mockFetch).toHaveBeenCalled();
|
||||
expect(mockFetch.mock.calls[0]?.[0]).toBe("https://api.perplexity.ai/chat/completions");
|
||||
});
|
||||
|
||||
it("uses configured baseUrl even when PERPLEXITY_API_KEY is set", async () => {
|
||||
vi.stubEnv("PERPLEXITY_API_KEY", "pplx-test");
|
||||
const mockFetch = installMockFetch({
|
||||
choices: [{ message: { content: "ok" } }],
|
||||
citations: [],
|
||||
});
|
||||
const tool = createPerplexitySearchTool({ baseUrl: "https://example.com/pplx" });
|
||||
await tool?.execute?.(1, { query: "test-config-baseurl" });
|
||||
|
||||
expect(mockFetch).toHaveBeenCalled();
|
||||
expect(mockFetch.mock.calls[0]?.[0]).toBe("https://example.com/pplx/chat/completions");
|
||||
});
|
||||
|
||||
it("defaults to Perplexity direct when apiKey looks like Perplexity", async () => {
|
||||
const mockFetch = installMockFetch({
|
||||
choices: [{ message: { content: "ok" } }],
|
||||
citations: [],
|
||||
});
|
||||
const tool = createPerplexitySearchTool({ apiKey: "pplx-config" });
|
||||
await tool?.execute?.(1, { query: "test-config-apikey" });
|
||||
|
||||
expect(mockFetch).toHaveBeenCalled();
|
||||
expect(mockFetch.mock.calls[0]?.[0]).toBe("https://api.perplexity.ai/chat/completions");
|
||||
});
|
||||
|
||||
it("defaults to OpenRouter when apiKey looks like OpenRouter", async () => {
|
||||
const mockFetch = installMockFetch({
|
||||
choices: [{ message: { content: "ok" } }],
|
||||
citations: [],
|
||||
});
|
||||
const tool = createPerplexitySearchTool({ apiKey: "sk-or-v1-test" });
|
||||
await tool?.execute?.(1, { query: "test-openrouter-config" });
|
||||
|
||||
expect(mockFetch).toHaveBeenCalled();
|
||||
expect(mockFetch.mock.calls[0]?.[0]).toBe("https://openrouter.ai/api/v1/chat/completions");
|
||||
expect(mockFetch.mock.calls[0]?.[0]).toBe(expectedUrl);
|
||||
if (expectedModel) {
|
||||
const body = parseFirstRequestBody(mockFetch);
|
||||
expect(body.model).toBe(expectedModel);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user