~james/core

core/web/src/lib/server/indexnow.test.ts -rw-r--r-- 3.2 KiB
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 15 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import { describe, expect, it, vi } from "vitest";
import {
	submitToIndexNow,
	notifyProfileCreated,
	notifyRepoCreated,
	DEFAULT_INDEXNOW_KEY,
	DEFAULT_INDEXNOW_HOST,
	type IndexNowPayload
} from "#lib/server/indexnow.ts";

describe("IndexNow integration", () => {
	it("returns error for empty URLs", async () => {
		const result = await submitToIndexNow([]);
		expect(result.success).toBe(false);
		expect(result.error).toContain("No URLs provided");
	});

	it("submits URLs to IndexNow with correct payload", async () => {
		let capturedUrl = "";
		let capturedInit: RequestInit | undefined;

		const mockFetch = vi.fn(async (input: RequestInfo | URL, init?: RequestInit) => {
			capturedUrl = String(input);
			capturedInit = init;
			return new Response("OK", { status: 200 });
		});

		const urls = ["https://tangled.org/alice", "https://tangled.org/bob"];
		const result = await submitToIndexNow(urls, { fetch: mockFetch });

		expect(result.success).toBe(true);
		expect(result.status).toBe(200);
		expect(capturedUrl).toBe("https://api.indexnow.org/indexnow");
		expect(capturedInit?.method).toBe("POST");

		const body = JSON.parse(capturedInit?.body as string);
		expect(body.host).toBe(DEFAULT_INDEXNOW_HOST);
		expect(body.key).toBe(DEFAULT_INDEXNOW_KEY);
		expect(body.keyLocation).toBe(
			`https://${DEFAULT_INDEXNOW_HOST}/${DEFAULT_INDEXNOW_KEY}.txt`
		);
		expect(body.urlList).toEqual(urls);
	});

	it("handles API errors gracefully without throwing", async () => {
		const mockFetch = vi.fn(async () => {
			return new Response("Forbidden", { status: 403, statusText: "Forbidden" });
		});

		const result = await submitToIndexNow("https://tangled.org/test", {
			fetch: mockFetch
		});

		expect(result.success).toBe(false);
		expect(result.status).toBe(403);
		expect(result.error).toContain("403");
	});

	it("handles fetch network failure silently without throwing", async () => {
		const mockFetch = vi.fn(async () => {
			throw new Error("Network offline");
		});

		const result = await submitToIndexNow("https://tangled.org/test", {
			fetch: mockFetch
		});

		expect(result.success).toBe(false);
		expect(result.error).toBeDefined();
	});

	it("formats notifyProfileCreated URL properly", async () => {
		let capturedBody!: IndexNowPayload;
		const mockFetch = vi.fn(async (_url: RequestInfo | URL, init?: RequestInit) => {
			const body = init?.body;
			if (typeof body !== "string") throw new Error("expected JSON body");
			capturedBody = JSON.parse(body) as IndexNowPayload;
			return new Response("OK", { status: 200 });
		});

		await notifyProfileCreated("alice.tangled.sh", { fetch: mockFetch });
		expect(capturedBody.urlList).toEqual(["https://tangled.org/alice.tangled.sh"]);
	});

	it("formats notifyRepoCreated URL properly", async () => {
		let capturedBody!: IndexNowPayload;
		const mockFetch = vi.fn(async (_url: RequestInfo | URL, init?: RequestInit) => {
			const body = init?.body;
			if (typeof body !== "string") throw new Error("expected JSON body");
			capturedBody = JSON.parse(body) as IndexNowPayload;
			return new Response("OK", { status: 200 });
		});

		await notifyRepoCreated("alice.tangled.sh", "my-repo", { fetch: mockFetch });
		expect(capturedBody.urlList).toEqual(["https://tangled.org/alice.tangled.sh/my-repo"]);
	});
});