Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/web/__tests__/google.test.ts

Raw
import { 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 &#x1f980;.",
) {
	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&amp;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", "&#999999999; &#xD800;"),
			)[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();
	});
});