~james/core

core/web/src/lib/api/tranquil.test.ts -rw-r--r-- 4.3 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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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.ts";

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<OAuthUserAgent["handle"]>()
			.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<OAuthUserAgent["handle"]>()
			.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<OAuthUserAgent["handle"]>()
			.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<OAuthUserAgent["handle"]>()
			.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<OAuthUserAgent["handle"]>()
			.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<OAuthUserAgent["handle"]>()
			.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<OAuthUserAgent["handle"]>()
		.mockResolvedValue(jsonResponse({ accounts: [] }));
	await expect(tranquil.listControlledAccounts(makeAgent(handle))).resolves.toEqual([]);
	expect(handle).toHaveBeenCalledWith(
		"/xrpc/_delegation.listControlledAccounts",
		expect.anything()
	);
});