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"]);
});
});