{"version":3,"file":"web-search.test.d.ts","sourceRoot":"","sources":["../../../src/core/tools/web-search.test.ts"],"names":[],"mappings":"","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { parseArgs } from \"../../cli/args.js\";\nimport { allTools } from \"./index.js\";\nimport { createWebSearchTool, type WebSearchToolDetails } from \"./web-search.js\";\n\nconst SEARCH_RESULTS_HTML = `<!DOCTYPE html>\n<html>\n  <body>\n    <table>\n      <tr>\n        <td>1.&nbsp;</td>\n        <td>\n          <a rel=\"nofollow\" href=\"//duckduckgo.com/l/?uddg=https%3A%2F%2Fgithub.com%2Fapholdings%2Fjensen-code\" class='result-link'>Jensen Code &amp; GitHub</a>\n        </td>\n      </tr>\n      <tr>\n        <td>&nbsp;&nbsp;&nbsp;</td>\n        <td class='result-snippet'>Official <b>Jensen Code</b> repository with releases &amp; docs.</td>\n      </tr>\n      <tr>\n        <td>&nbsp;&nbsp;&nbsp;</td>\n        <td><span class='link-text'>github.com/apholdings/jensen-code</span></td>\n      </tr>\n      <tr><td>&nbsp;</td><td>&nbsp;</td></tr>\n      <tr>\n        <td>2.&nbsp;</td>\n        <td>\n          <a rel=\"nofollow\" href=\"//duckduckgo.com/l/?uddg=https%3A%2F%2Fjensen.dev%2Fdocs\" class='result-link'>Jensen Docs</a>\n        </td>\n      </tr>\n      <tr>\n        <td>&nbsp;&nbsp;&nbsp;</td>\n        <td class='result-snippet'>Browse the latest Jensen documentation.</td>\n      </tr>\n      <tr>\n        <td>&nbsp;&nbsp;&nbsp;</td>\n        <td><span class='link-text'>jensen.dev/docs</span></td>\n      </tr>\n    </table>\n  </body>\n</html>`;\n\nconst EMPTY_RESULTS_HTML = `<!DOCTYPE html><html><body><table></table></body></html>`;\n\ndescribe(\"web_search tool\", () => {\n\tit(\"registers through the built-in tool path and CLI tool parsing\", () => {\n\t\texpect(allTools.web_search.name).toBe(\"web_search\");\n\t\texpect(parseArgs([\"--tools\", \"web_search\"]).tools).toEqual([\"web_search\"]);\n\t});\n\n\tit(\"returns bounded structured DuckDuckGo Lite results\", async () => {\n\t\tconst tool = createWebSearchTool({\n\t\t\tfetch: async () => new Response(SEARCH_RESULTS_HTML, { status: 200 }),\n\t\t});\n\n\t\tconst result = await tool.execute(\"call-1\", { query: \"jensen code\", limit: 2 });\n\t\tconst details = result.details as WebSearchToolDetails;\n\n\t\texpect(details).toMatchObject({\n\t\t\tprovider: \"duckduckgo-lite\",\n\t\t\tquery: \"jensen code\",\n\t\t\tresultCount: 2,\n\t\t\tresults: [\n\t\t\t\t{\n\t\t\t\t\ttitle: \"Jensen Code & GitHub\",\n\t\t\t\t\turl: \"https://github.com/apholdings/jensen-code\",\n\t\t\t\t\tsnippet: \"Official Jensen Code repository with releases & docs.\",\n\t\t\t\t\tsource: \"github.com\",\n\t\t\t\t\tprovider: \"duckduckgo-lite\",\n\t\t\t\t\trank: 1,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttitle: \"Jensen Docs\",\n\t\t\t\t\turl: \"https://jensen.dev/docs\",\n\t\t\t\t\tsnippet: \"Browse the latest Jensen documentation.\",\n\t\t\t\t\tsource: \"jensen.dev\",\n\t\t\t\t\tprovider: \"duckduckgo-lite\",\n\t\t\t\t\trank: 2,\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t\texpect(details).toMatchObject({ rawResultCount: 2, deduplicatedCount: 0, untrusted: true });\n\t\texpect(result.content).toEqual([\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: expect.stringContaining('<external-web-search provider=\"duckduckgo-lite\" trust=\"untrusted\">'),\n\t\t\t},\n\t\t]);\n\t});\n\n\tit(\"rejects empty queries honestly\", async () => {\n\t\tconst tool = createWebSearchTool({\n\t\t\tfetch: async () => new Response(SEARCH_RESULTS_HTML, { status: 200 }),\n\t\t});\n\n\t\tawait expect(tool.execute(\"call-2\", { query: \"   \" })).rejects.toThrow(\"Query must not be empty\");\n\t});\n\n\tit(\"returns no-results output without inventing content\", async () => {\n\t\tconst tool = createWebSearchTool({\n\t\t\tfetch: async () => new Response(EMPTY_RESULTS_HTML, { status: 200 }),\n\t\t});\n\n\t\tconst result = await tool.execute(\"call-3\", { query: \"no matches here\" });\n\t\tconst details = result.details as WebSearchToolDetails;\n\n\t\texpect(details.resultCount).toBe(0);\n\t\texpect(details.results).toEqual([]);\n\t\texpect(result.content).toEqual([{ type: \"text\", text: 'No web results found for \"no matches here\".' }]);\n\t});\n\n\tit(\"surfaces provider failures honestly\", async () => {\n\t\tconst tool = createWebSearchTool({\n\t\t\tfetch: async () => new Response(\"temporarily unavailable\", { status: 503 }),\n\t\t});\n\n\t\tawait expect(tool.execute(\"call-4\", { query: \"jensen code\" })).rejects.toThrow(\n\t\t\t\"DuckDuckGo Lite search failed: 503\",\n\t\t);\n\t});\n});\n"]}