import { afterEach, describe, expect, it } from "bun:test"; import { DEFAULT_PDS_URL, isResolvableIdentifier, resolveHandleToDid, resolveHandleToPDS, resolvePdsUrlOrDefault, } from "../src/lib/identity"; const realFetch = globalThis.fetch; type FetchHandler = (url: string) => Response | Promise; function mockFetch(handler: FetchHandler): string[] { const calls: string[] = []; globalThis.fetch = (async (input: RequestInfo | URL) => { const url = typeof input === "string" ? input : input.toString(); calls.push(url); return handler(url); }) as typeof fetch; return calls; } function didDocResponse(endpoint: string): Response { return Response.json({ service: [ { id: "#atproto_pds", type: "AtprotoPersonalDataServer", serviceEndpoint: endpoint, }, ], }); } afterEach(() => { globalThis.fetch = realFetch; }); describe("isResolvableIdentifier", () => { it("accepts handles and DIDs", () => { expect(isResolvableIdentifier("alice.example.com")).toBe(true); expect(isResolvableIdentifier("@alice.example.com")).toBe(true); expect(isResolvableIdentifier("did:plc:abc123")).toBe(true); }); it("rejects email addresses and bare names", () => { expect(isResolvableIdentifier("alice@example.com")).toBe(false); expect(isResolvableIdentifier("alice")).toBe(false); }); }); describe("resolveHandleToDid", () => { it("resolves through the appview", async () => { const calls = mockFetch(() => Response.json({ did: "did:plc:abc123" })); expect(await resolveHandleToDid("@Alice.Example.com")).toBe( "did:plc:abc123", ); expect(calls[0]).toContain("handle=alice.example.com"); }); it("returns DIDs untouched without any lookup", async () => { const calls = mockFetch(() => { throw new Error("should not fetch"); }); expect(await resolveHandleToDid("did:plc:abc123")).toBe("did:plc:abc123"); expect(calls).toHaveLength(0); }); it("falls back to the handle's well-known document", async () => { const calls = mockFetch((url) => url.includes("public.api.bsky.app") ? new Response("not found", { status: 400 }) : new Response("did:web:alice.example.com\n"), ); expect(await resolveHandleToDid("alice.example.com")).toBe( "did:web:alice.example.com", ); expect(calls[1]).toBe("https://alice.example.com/.well-known/atproto-did"); }); }); describe("resolveHandleToPDS", () => { it("reads the PDS endpoint from a did:plc document", async () => { mockFetch((url) => url.includes("plc.directory") ? didDocResponse("https://pds.example.com") : Response.json({ did: "did:plc:abc123" }), ); expect(await resolveHandleToPDS("alice.example.com")).toBe( "https://pds.example.com", ); }); it("reads the PDS endpoint from a did:web document", async () => { const calls = mockFetch(() => didDocResponse("https://pds.example.com")); expect(await resolveHandleToPDS("did:web:alice.example.com")).toBe( "https://pds.example.com", ); expect(calls[0]).toBe("https://alice.example.com/.well-known/did.json"); }); it("throws when the DID document has no PDS service", async () => { mockFetch((url) => url.includes("plc.directory") ? Response.json({ service: [] }) : Response.json({ did: "did:plc:abc123" }), ); expect(resolveHandleToPDS("alice.example.com")).rejects.toThrow( "Could not find PDS URL for user", ); }); }); describe("resolvePdsUrlOrDefault", () => { it("returns the resolved PDS", async () => { mockFetch((url) => url.includes("plc.directory") ? didDocResponse("https://pds.example.com") : Response.json({ did: "did:plc:abc123" }), ); expect(await resolvePdsUrlOrDefault("alice.example.com")).toBe( "https://pds.example.com", ); }); it("falls back to the default PDS for an email identifier", async () => { const calls = mockFetch(() => { throw new Error("should not fetch"); }); expect(await resolvePdsUrlOrDefault("alice@example.com")).toBe( DEFAULT_PDS_URL, ); expect(calls).toHaveLength(0); }); it("falls back to the default PDS when resolution fails", async () => { mockFetch(() => new Response("nope", { status: 500 })); expect(await resolvePdsUrlOrDefault("alice.example.com")).toBe( DEFAULT_PDS_URL, ); }); });