~james/core

core/web/src/lib/api/markupBlobs.test.ts -rw-r--r-- 2.7 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
import { afterEach, describe, expect, it, vi } from "vitest";
import type { OAuthUserAgent } from "@atcute/oauth-browser-client";
import type { BobbinContext } from "#lib/api/client.ts";
import { didOf } from "#lib/api/syntax.ts";
import type * as MarkupBlobs from "#lib/api/markupBlobs.ts";

const agent = { sub: "did:plc:limpet" } as unknown as OAuthUserAgent;
const repo = didOf("did:plc:barnacle");
const bobbin = {} as BobbinContext;

const load = async () => {
	vi.resetModules();
	const minted: { aud: string; lxm: string }[] = [];
	vi.doMock("#lib/auth/agent.ts", () => ({
		createClient: () => {
			throw new Error("the signed in account's pds shouldn't be used");
		},
		mintServiceAuth: async (_agent: unknown, scope: { aud: string; lxm: string }) => {
			minted.push(scope);
			return "token";
		}
	}));
	vi.doMock("#lib/api/identity.ts", () => ({
		resolveMiniDoc: async () => ({ pds: "https://knot.example.com" })
	}));
	const blobs = (await import("#lib/api/markupBlobs.ts")) as typeof MarkupBlobs;
	const calls: { url: string; init: RequestInit }[] = [];
	const answer = (link: string) =>
		vi.stubGlobal("fetch", async (input: URL | RequestInfo, init?: RequestInit) => {
			calls.push({ url: String(input), init: init ?? {} });
			const blob = { $type: "blob", ref: { $link: link }, mimeType: "image/png", size: 3 };
			return Response.json({ blob });
		});
	return { blobs, minted, calls, answer };
};

const png = (bytes: number[]) =>
	new File([new Uint8Array(bytes)], "seal.png", { type: "image/png" });

afterEach(() => {
	vi.unstubAllGlobals();
});

describe("uploadPending", () => {
	it("uploads what the text still links to the owner's pds, once", async () => {
		const { blobs, minted, calls, answer } = await load();
		const file = png([1, 2, 3]);
		const cid = await blobs.blobCidOf(file);
		const kept = { cid, file, url: "blob:kept" };
		const dropped = { cid: "bafkreidropped", file: png([4]), url: "blob:dropped" };
		answer(cid);

		const uploaded = await blobs.uploadPending(
			agent,
			bobbin,
			repo,
			[kept, kept, dropped],
			`![Image](https://tangled.org/blob/${repo}/${cid})`
		);

		expect(uploaded.map((blob) => blob.ref.$link)).toEqual([cid]);
		expect(calls).toHaveLength(1);
		expect(calls[0].url).toBe("https://knot.example.com/xrpc/com.atproto.repo.uploadBlob");
		expect(minted).toEqual([{ aud: repo, lxm: "com.atproto.repo.uploadBlob" }]);
	});

	it("refuses a blob stored under another cid than the one linked", async () => {
		const { blobs, answer } = await load();
		const file = png([1, 2, 3]);
		const cid = await blobs.blobCidOf(file);
		const other = await blobs.blobCidOf(png([9]));
		answer(other);

		await expect(
			blobs.uploadPending(agent, bobbin, repo, [{ cid, file, url: "blob:x" }], cid)
		).rejects.toThrow(`stored as ${other}`);
	});
});