From bd1c6efca516048f3dbb268d50ed723ae7feb2ef Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 22 Mar 2026 16:01:56 -0700 Subject: [PATCH] test(extensions): cover web search provider helpers --- .../src/brave-web-search-provider.test.ts | 52 +++++++++++++++++++ .../src/gemini-web-search-provider.test.ts | 18 +++++++ .../src/kimi-web-search-provider.test.ts | 40 ++++++++++++++ .../perplexity-web-search-provider.test.ts | 42 +++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 extensions/brave/src/brave-web-search-provider.test.ts create mode 100644 extensions/google/src/gemini-web-search-provider.test.ts create mode 100644 extensions/moonshot/src/kimi-web-search-provider.test.ts create mode 100644 extensions/perplexity/src/perplexity-web-search-provider.test.ts diff --git a/extensions/brave/src/brave-web-search-provider.test.ts b/extensions/brave/src/brave-web-search-provider.test.ts new file mode 100644 index 00000000000..ce82bc5a42e --- /dev/null +++ b/extensions/brave/src/brave-web-search-provider.test.ts @@ -0,0 +1,52 @@ +import { describe, expect, it } from "vitest"; +import { __testing } from "./brave-web-search-provider.js"; + +describe("brave web search provider", () => { + it("normalizes brave language parameters and swaps reversed ui/search inputs", () => { + expect( + __testing.normalizeBraveLanguageParams({ + search_lang: "en-US", + ui_lang: "ja", + }), + ).toEqual({ + search_lang: "jp", + ui_lang: "en-US", + }); + }); + + it("flags invalid brave language fields", () => { + expect( + __testing.normalizeBraveLanguageParams({ + search_lang: "xx", + }), + ).toEqual({ invalidField: "search_lang" }); + }); + + it("defaults brave mode to web unless llm-context is explicitly selected", () => { + expect(__testing.resolveBraveMode()).toBe("web"); + expect(__testing.resolveBraveMode({ mode: "llm-context" })).toBe("llm-context"); + }); + + it("maps llm-context results into wrapped source entries", () => { + expect( + __testing.mapBraveLlmContextResults({ + grounding: { + generic: [ + { + url: "https://example.com/post", + title: "Example", + snippets: ["a", "", "b"], + }, + ], + }, + }), + ).toEqual([ + { + url: "https://example.com/post", + title: "Example", + snippets: ["a", "b"], + siteName: "example.com", + }, + ]); + }); +}); diff --git a/extensions/google/src/gemini-web-search-provider.test.ts b/extensions/google/src/gemini-web-search-provider.test.ts new file mode 100644 index 00000000000..42ba5676510 --- /dev/null +++ b/extensions/google/src/gemini-web-search-provider.test.ts @@ -0,0 +1,18 @@ +import { describe, expect, it } from "vitest"; +import { __testing } from "./gemini-web-search-provider.js"; + +describe("gemini web search provider", () => { + it("prefers scoped configured api keys over environment fallbacks", () => { + expect( + __testing.resolveGeminiApiKey({ + apiKey: "gemini-secret", + }), + ).toBe("gemini-secret"); + }); + + it("falls back to the default Gemini model when unset or blank", () => { + expect(__testing.resolveGeminiModel()).toBe("gemini-2.5-flash"); + expect(__testing.resolveGeminiModel({ model: " " })).toBe("gemini-2.5-flash"); + expect(__testing.resolveGeminiModel({ model: "gemini-2.5-pro" })).toBe("gemini-2.5-pro"); + }); +}); diff --git a/extensions/moonshot/src/kimi-web-search-provider.test.ts b/extensions/moonshot/src/kimi-web-search-provider.test.ts new file mode 100644 index 00000000000..a8ded8b6886 --- /dev/null +++ b/extensions/moonshot/src/kimi-web-search-provider.test.ts @@ -0,0 +1,40 @@ +import { describe, expect, it } from "vitest"; +import { __testing } from "./kimi-web-search-provider.js"; + +describe("kimi web search provider", () => { + it("uses configured model and base url overrides with sane defaults", () => { + expect(__testing.resolveKimiModel()).toBe("moonshot-v1-128k"); + expect(__testing.resolveKimiModel({ model: "kimi-k2" })).toBe("kimi-k2"); + expect(__testing.resolveKimiBaseUrl()).toBe("https://api.moonshot.ai/v1"); + expect(__testing.resolveKimiBaseUrl({ baseUrl: "https://kimi.example/v1" })).toBe( + "https://kimi.example/v1", + ); + }); + + it("extracts unique citations from search results and tool call arguments", () => { + expect( + __testing.extractKimiCitations({ + search_results: [ + { url: "https://a.test" }, + { url: "https://b.test" }, + ], + choices: [ + { + message: { + tool_calls: [ + { + function: { + arguments: JSON.stringify({ + url: "https://a.test", + search_results: [{ url: "https://c.test" }], + }), + }, + }, + ], + }, + }, + ], + }), + ).toEqual(["https://a.test", "https://b.test", "https://c.test"]); + }); +}); diff --git a/extensions/perplexity/src/perplexity-web-search-provider.test.ts b/extensions/perplexity/src/perplexity-web-search-provider.test.ts new file mode 100644 index 00000000000..c154255f560 --- /dev/null +++ b/extensions/perplexity/src/perplexity-web-search-provider.test.ts @@ -0,0 +1,42 @@ +import { describe, expect, it } from "vitest"; +import { __testing } from "./perplexity-web-search-provider.js"; + +describe("perplexity web search provider", () => { + it("infers provider routing from api key prefixes", () => { + expect(__testing.inferPerplexityBaseUrlFromApiKey("pplx-abc")).toBe("direct"); + expect(__testing.inferPerplexityBaseUrlFromApiKey("sk-or-v1-abc")).toBe("openrouter"); + expect(__testing.inferPerplexityBaseUrlFromApiKey("unknown")).toBeUndefined(); + }); + + it("resolves base url from auth source and request model by transport", () => { + expect(__testing.resolvePerplexityBaseUrl(undefined, "perplexity_env")).toBe( + "https://api.perplexity.ai", + ); + expect(__testing.resolvePerplexityBaseUrl(undefined, "openrouter_env")).toBe( + "https://openrouter.ai/api/v1", + ); + expect(__testing.resolvePerplexityRequestModel("https://api.perplexity.ai", "perplexity/sonar-pro")).toBe( + "sonar-pro", + ); + expect( + __testing.resolvePerplexityRequestModel( + "https://openrouter.ai/api/v1", + "perplexity/sonar-pro", + ), + ).toBe("perplexity/sonar-pro"); + }); + + it("chooses direct search_api transport only for direct base urls without legacy overrides", () => { + expect( + __testing.resolvePerplexityTransport({ + baseUrl: "https://api.perplexity.ai", + }).transport, + ).toBe("chat_completions"); + + expect( + __testing.resolvePerplexityTransport({ + apiKey: "pplx-secret", + }).transport, + ).toBe("search_api"); + }); +});