diff options
| author | Igor Soarez <igor@soarez.org> | 2026-11-06 03:33:30 +0000 |
|---|---|---|
| committer | Igor Soarez <igor@soarez.org> | 2026-11-06 03:33:30 +0000 |
| commit | 561f0ee076c684a79fd5671af1bad0894f33e4de (patch) | |
| tree | 7849677412a8b5f80835fa812f2e255f222a2c82 /castle-search/test | |
| parent | 147b3b1507ebcdf5912fbd4c474c9dfb35265148 (diff) | |
The Node-side resolver sent one curl-like request per result with no
cookies, JS or browser; Google answers that with its 'Verifying your
request' countdown after a handful, and the testing itself triggered it.
A click or direct navigation in Chrome redirects at once (measured).
Search now leaves Google links wrapped and prints the breadcrumb Google
shows for each. castle_cdp_resolve follows one wrapped link in a Chrome tab
when the agent picks it, accepts only google.com/goto?url=<token>, and
reports the verification page instead of waiting it out.
Diffstat (limited to 'castle-search/test')
| -rw-r--r-- | castle-search/test/google-links.test.ts | 41 | ||||
| -rw-r--r-- | castle-search/test/resolve.test.ts | 50 |
2 files changed, 41 insertions, 50 deletions
diff --git a/castle-search/test/google-links.test.ts b/castle-search/test/google-links.test.ts new file mode 100644 index 0000000..f31f112 --- /dev/null +++ b/castle-search/test/google-links.test.ts @@ -0,0 +1,41 @@ +import assert from "node:assert/strict"; +import { test } from "node:test"; + +import { formatResults } from "../src/format.ts"; +import { isGoogleGoto } from "../src/google-links.ts"; +import { getEngine } from "../src/engines.ts"; +import { resolveLink } from "../src/search.ts"; + +test("only well-formed google /goto links count", () => { + assert.equal(isGoogleGoto("https://www.google.com/goto?url=CAESabc_-9"), true); + assert.equal(isGoogleGoto("https://www.google.co.uk/goto?url=CAESabc"), true); + assert.equal(isGoogleGoto("https://www.google.com/search?q=x"), false); + assert.equal(isGoogleGoto("https://example.com/goto?url=CAES"), false); + // Not a general navigator: nothing may ride along after the token. + assert.equal(isGoogleGoto("https://www.google.com/goto?url=CAES&x=https://evil.example"), false); + assert.equal(isGoogleGoto("https://www.google.com.evil.example/goto?url=CAES"), false); +}); + +test("the google self-host filter lets /goto through but still blocks google's own pages", () => { + const re = new RegExp(getEngine("google").extraction.selfHostPattern); + assert.equal(re.test("https://www.google.com/goto?url=CAES"), false); + assert.equal(re.test("https://www.google.com/search?q=x"), true); + assert.equal(re.test("https://accounts.google.com/ServiceLogin"), false); +}); + +test("resolveLink refuses anything that is not a google /goto link, before touching the browser", async () => { + await assert.rejects(() => resolveLink("https://example.com/", AbortSignal.timeout(1000)), /only follows Google result links/); + await assert.rejects(() => resolveLink("file:///etc/passwd", AbortSignal.timeout(1000)), /only follows Google result links/); +}); + +test("a wrapped result says so, shows Google's breadcrumb, and names the tool to resolve it", () => { + const text = formatResults({ + query: "q", searchUrl: "u", finalUrl: "u", endpoint: "e", engine: "Google", engineSource: "s", + results: [ + { title: "Wrapped", url: "https://www.google.com/goto?url=CAES", snippet: "snip", display: "GitHub — https://github.com › a › b" }, + { title: "Direct", url: "https://example.com/", snippet: "" }, + ], + }); + assert.match(text, /\[Google-wrapped link, real URL not yet known\. Google shows it as: GitHub — https:\/\/github\.com › a › b\. Pass it to castle_cdp_resolve/); + assert.equal((text.match(/Google-wrapped/g) ?? []).length, 1); +}); diff --git a/castle-search/test/resolve.test.ts b/castle-search/test/resolve.test.ts deleted file mode 100644 index bcd4ef4..0000000 --- a/castle-search/test/resolve.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import assert from "node:assert/strict"; -import { test } from "node:test"; - -import { isGoogleGoto, resolveGoogleLinks } from "../src/resolve.ts"; -import { getEngine } from "../src/engines.ts"; - -test("google /goto links are recognised, other google links are not", () => { - assert.equal(isGoogleGoto("https://www.google.com/goto?url=CAES"), true); - assert.equal(isGoogleGoto("https://www.google.co.uk/goto?url=CAES"), true); - assert.equal(isGoogleGoto("https://www.google.com/search?q=x"), false); - assert.equal(isGoogleGoto("https://example.com/goto?url=x"), false); -}); - -test("the google self-host filter lets /goto through but still blocks google's own pages", () => { - const re = new RegExp(getEngine("google").extraction.selfHostPattern); - assert.equal(re.test("https://www.google.com/goto?url=CAES"), false); - assert.equal(re.test("https://www.google.com/search?q=x"), true); - assert.equal(re.test("https://accounts.google.com/ServiceLogin"), false); -}); - -test("non-google results pass through untouched", async () => { - const input = [{ title: "t", url: "https://example.com/", snippet: "" }]; - assert.deepEqual(await resolveGoogleLinks(input), input); -}); - -test("a link that cannot be resolved keeps the page's breadcrumb in its snippet", async () => { - const wrapped = "https://www.google.com/goto?url=CAES"; - const real = globalThis.fetch; - // Google's interstitial: 200 with no Location header. - globalThis.fetch = (async () => new Response("<html>Verifying your request</html>", { status: 200 })) as typeof fetch; - try { - const [r] = await resolveGoogleLinks([{ title: "t", url: wrapped, snippet: "s", display: "GitHub — https://github.com › a › b" }]); - assert.equal(r?.url, wrapped); - assert.match(r?.snippet ?? "", /^\[link unresolved; Google shows it as: GitHub — https:\/\/github\.com › a › b\] s$/); - } finally { - globalThis.fetch = real; - } -}); - -test("a link that resolves is replaced and the snippet is left alone", async () => { - const real = globalThis.fetch; - globalThis.fetch = (async () => new Response(null, { status: 302, headers: { location: "https://github.com/a/b" } })) as typeof fetch; - try { - const [r] = await resolveGoogleLinks([{ title: "t", url: "https://www.google.com/goto?url=CAES", snippet: "s", display: "x" }]); - assert.equal(r?.url, "https://github.com/a/b"); - assert.equal(r?.snippet, "s"); - } finally { - globalThis.fetch = real; - } -}); |
