repositories / pi-ext
pi-ext
bugabingas pi extensions
owned by admin
extensions/web/__tests__/google.test.ts
Rawimport { afterEach, describe, expect, it, vi } from "vitest";
import { googleSearch, parseGoogleResults } from "../google";
// Reduced Google WML structure: nested result cards, linked titles, snippet spans.
function card(
url: string,
title = "Node & Rust",
snippet = "A <b>nested</b> snippet 🦀.",
) {
return `<div class="zMzFAb"><div><a href="${url}" class="fuLhoc"><span class="CVA68e">${title}</span></a></div><div class="taTFJ"><span class="FrIlee">${snippet}</span></div></div>`;
}
const html = `<?xml version="1.0"?><html><body>${card("/url?q=https%3A%2F%2Fnodejs.org%2Fapi%2Ffs.html&sa=U")}${card("https://rust-lang.org/")}</body></html>`;
afterEach(() => vi.restoreAllMocks());
describe("Google WML", () => {
it("extracts titles, redirects, nested snippets, and entities", () => {
expect(parseGoogleResults(html)).toEqual([
{
title: "Node & Rust",
url: "https://nodejs.org/api/fs.html",
snippet: "A nested snippet 🦀.",
},
{
title: "Node & Rust",
url: "https://rust-lang.org/",
snippet: "A nested snippet 🦀.",
},
]);
});
it("deduplicates and ignores unsafe, malformed, and navigation links", () => {
const text = [
"https://example.com/",
"https://example.com/",
"javascript:alert(1)",
"file:///etc/passwd",
"https://user:pass@example.com/",
"https://www.google.com/preferences",
"/url?q=not-a-url",
]
.map((url) => card(url))
.join("");
expect(parseGoogleResults(text)).toHaveLength(1);
});
it("does not cap snippets", () => {
const snippet = "x".repeat(30_000);
expect(
parseGoogleResults(card("https://example.com", "Title", snippet))[0]
.snippet,
).toBe(snippet);
});
it("handles malformed numeric entities without throwing", () => {
expect(
parseGoogleResults(
card("https://example.com", "� �"),
)[0].title,
).toBe("� �");
});
it.each([
"Our systems have detected unusual traffic",
"<div class='g-recaptcha'></div>",
"Before you continue to Google",
"Please enable JavaScript",
"<html>A new incompatible layout</html>",
])("fails closed for challenges or changed markup: %s", (body) => {
expect(() => parseGoogleResults(body)).toThrow(/Google WML/);
});
it("recognizes genuine no-results pages", () => {
expect(
parseGoogleResults("Your search did not match any documents."),
).toEqual([]);
});
it("uses Nokia WML through the real HTTP path, with manual redirects and count", async () => {
const network = vi
.spyOn(globalThis, "fetch")
.mockResolvedValue(new Response(html));
const result = await googleSearch("Node & Rust", undefined, 1);
expect(result).toHaveLength(1);
const [url, init] = network.mock.calls[0];
expect(new URL(String(url)).pathname).toBe("/wml/search");
expect(new URL(String(url)).searchParams.get("q")).toBe("Node & Rust");
expect(init?.headers).toMatchObject({
"User-Agent": expect.stringContaining("Nokia7610"),
Cookie: "CONSENT=YES+",
});
expect(init?.redirect).toBe("manual");
});
it("aborts without network I/O", async () => {
const network = vi.spyOn(globalThis, "fetch");
await expect(
googleSearch("docs", AbortSignal.abort(new Error("cancelled"))),
).rejects.toThrow("cancelled");
expect(network).not.toHaveBeenCalled();
});
it("enforces deadline while waiting for the throttle", async () => {
const network = vi.spyOn(globalThis, "fetch");
// The previous request reserved a slot; force the clock behind that slot.
vi.spyOn(Date, "now").mockReturnValue(Date.now() - 5000);
await expect(
googleSearch("docs", new AbortController().signal, 5, 10),
).rejects.toThrow(/abort/i);
expect(network).not.toHaveBeenCalled();
});
});