import { describe, expect, it, vi } from "vitest"; import { ClientResponseError } from "@atcute/client"; import type { OAuthUserAgent } from "@atcute/oauth-browser-client"; import * as tranquil from "$lib/api/tranquil"; const jsonResponse = (body: unknown, init: ResponseInit = {}): Response => new Response(JSON.stringify(body), { status: 200, headers: { "content-type": "application/json" }, ...init }); const makeAgent = (handle: OAuthUserAgent["handle"]): OAuthUserAgent => ({ handle }) as unknown as OAuthUserAgent; describe("tranquil.listControllers", () => { it("unwraps the controllers array", async () => { const handle = vi .fn() .mockResolvedValue(jsonResponse({ controllers: [{ did: "did:plc:x", isActive: true }] })); const controllers = await tranquil.listControllers(makeAgent(handle)); expect(handle).toHaveBeenCalledWith("/xrpc/_delegation.listControllers", expect.anything()); expect(controllers).toEqual([{ did: "did:plc:x", isActive: true }]); }); it("preserves custom headers supplied as a Headers object", async () => { const handle = vi .fn() .mockResolvedValue(jsonResponse({ controllers: [] })); await tranquil.listControllers(makeAgent(handle), { headers: new Headers({ accept: "application/vnd.example+json", "x-custom": "value" }) }); const [, init] = handle.mock.calls[0]; const headers = new Headers(init?.headers); expect(headers.get("accept")).toBe("application/vnd.example+json"); expect(headers.get("x-custom")).toBe("value"); }); }); describe("tranquil.addController", () => { it("sends a snake_case body, matching tranquil-pds's un-renamed request struct", async () => { const handle = vi .fn() .mockResolvedValue(jsonResponse({ success: true })); await tranquil.addController(makeAgent(handle), { controllerDid: "did:plc:controller", grantedScopes: "atproto" }); const [pathname, init] = handle.mock.calls[0]; expect(pathname).toBe("/xrpc/_delegation.addController"); expect(JSON.parse(String(init?.body))).toEqual({ controller_did: "did:plc:controller", granted_scopes: "atproto" }); }); it("preserves custom headers supplied as tuples", async () => { const handle = vi .fn() .mockResolvedValue(jsonResponse({ success: true })); await tranquil.addController( makeAgent(handle), { controllerDid: "did:plc:controller", grantedScopes: "atproto" }, { headers: [["x-custom", "value"]] } ); const [, init] = handle.mock.calls[0]; const headers = new Headers(init?.headers); expect(headers.get("x-custom")).toBe("value"); expect(headers.get("accept")).toBe("application/json"); expect(headers.get("content-type")).toBe("application/json"); }); }); describe("tranquil.createDelegatedAccount", () => { it("sends a camelCase body", async () => { const handle = vi .fn() .mockResolvedValue(jsonResponse({ did: "did:plc:new", handle: "new.example.com" })); await tranquil.createDelegatedAccount(makeAgent(handle), { handle: "new.example.com", controllerScopes: "atproto" }); const [path, init] = handle.mock.calls[0]; expect(path).toBe("/xrpc/_delegation.createDelegatedAccount"); expect(JSON.parse(String(init?.body))).toEqual({ handle: "new.example.com", controllerScopes: "atproto" }); }); }); describe("tranquil error handling", () => { it("throws ClientResponseError on a non-2xx response", async () => { const handle = vi .fn() .mockResolvedValue(jsonResponse({ error: "DelegationNotFound" }, { status: 404 })); const err = await tranquil .removeController(makeAgent(handle), "did:plc:controller") .catch((e: unknown) => e); expect(err).toBeInstanceOf(ClientResponseError); expect((err as ClientResponseError).status).toBe(404); expect((err as ClientResponseError).error).toBe("DelegationNotFound"); }); }); it("lists controlled accounts at the Tranquil HTTP route", async () => { const handle = vi .fn() .mockResolvedValue(jsonResponse({ accounts: [] })); await expect(tranquil.listControlledAccounts(makeAgent(handle))).resolves.toEqual([]); expect(handle).toHaveBeenCalledWith( "/xrpc/_delegation.listControlledAccounts", expect.anything() ); });