import { describe, expect, it, vi } from "vitest"; import { createBobbinClient } from "#lib/api/client.ts"; import { listCollaborators } from "#lib/api/collaborators.ts"; const owner = "did:plc:owner"; const repoDid = "did:plc:repo"; const bobbin = (pages: Record) => { const fetch = vi.fn(async (input) => { const asked = new URL(String(input)); const page = pages[asked.pathname]; return new Response(JSON.stringify(page ?? { error: "MethodNotImplemented" }), { status: page ? 200 : 501, headers: { "content-type": "application/json" } }); }); return createBobbinClient({ serviceUrl: "https://bobbin.test", fetch }); }; describe("listCollaborators", () => { it("lists the owner first, then accepted collaborators", async () => { const ctx = bobbin({ "/xrpc/org.tangled.repo.listCollaborators": { items: [ { subject: "did:plc:friend", addedBy: owner, createdAt: "a", effectiveSince: "b" }, { subject: owner, addedBy: owner, createdAt: "a", effectiveSince: "b" } ] }, "/xrpc/blue.microcosm.identity.resolveMiniDoc": { did: "x", handle: "someone.test" } }); await expect(listCollaborators(ctx, { ownerDid: owner, repoDid })).resolves.toEqual([ { did: owner, handle: "someone.test", standing: "owner", since: undefined }, { did: "did:plc:friend", handle: "someone.test", standing: "collaborator", since: "b" } ]); }); it("falls back to the did when the handle will not resolve", async () => { const unresolvable = "did:plc:nohandle"; const ctx = bobbin({ "/xrpc/org.tangled.repo.listCollaborators": { items: [] } }); await expect(listCollaborators(ctx, { ownerDid: unresolvable, repoDid })).resolves.toEqual([ { did: unresolvable, handle: unresolvable, standing: "owner", since: undefined } ]); }); it("shows just the owner for a repo without a DID", async () => { const solo = "did:plc:solo"; const ctx = bobbin({ "/xrpc/blue.microcosm.identity.resolveMiniDoc": { did: solo, handle: "solo.test" } }); await expect(listCollaborators(ctx, { ownerDid: solo })).resolves.toEqual([ { did: solo, handle: "solo.test", standing: "owner", since: undefined } ]); }); });