Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186import type { Did } from "@atcute/lexicons/syntax";import { describe, expect, it, vi } from "vitest";import { blameFor, hydrateBlameAuthors } from "$lib/api/blame";import { createBobbinClient } from "$lib/api/client";
const REPO_DID = "did:plc:repo" as Did;
const jsonResponse = (body: unknown): Response => new Response(JSON.stringify(body), { status: 200, headers: { "content-type": "application/json" } });
const errorResponse = (status: number, error: string): Response => new Response(JSON.stringify({ error }), { status, headers: { "content-type": "application/json" } });
const mirrorResponse = (body: { commits: Array<Record<string, unknown>>; runs: Array<Record<string, unknown>>;}): Response => jsonResponse({ commit: "abc123", ...body });
const makeCtx = (fetchMock: typeof globalThis.fetch) => createBobbinClient({ serviceUrl: "https://bobbin.example", fetch: fetchMock });
const blameCall = (ctx: ReturnType<typeof makeCtx>) => blameFor(ctx, REPO_DID, "main", "src/main.rs");
describe("blameFor", () => { it("requests gitmirror getBlame and maps its one-based runs", async () => { const fetchMock = vi.fn<typeof globalThis.fetch>().mockResolvedValue( mirrorResponse({ commits: [ { oid: "abc123", message: "add main\n\nlonger explanation", author: { name: "dawn", email: "did:plc:dawn", when: "2026-06-01T12:30:00Z" } } ], runs: [{ start: 1, count: 3, commit: "abc123" }] }) ); const ctx = makeCtx(fetchMock);
await expect(blameCall(ctx)).resolves.toEqual([ { start: 1, count: 3, commit: { sha: "abc123", subject: "add main", when: "2026-06-01T12:30:00Z", author: { name: "dawn", email: "did:plc:dawn", did: "did:plc:dawn" } } } ]);
const url = new URL(String(fetchMock.mock.calls[0][0])); expect(url.pathname).toBe("/xrpc/sh.tangled.git.temp2.getBlame"); expect(url.searchParams.get("repo")).toBe(REPO_DID); expect(url.searchParams.get("ref")).toBe("main"); expect(url.searchParams.get("path")).toBe("src/main.rs"); });
it("keeps only the subject of the mirror's full commit message", async () => { const fetchMock = vi.fn<typeof globalThis.fetch>().mockResolvedValue( mirrorResponse({ commits: [ { oid: "abc123", message: "subject line\n\nbody", author: { name: "dawn", email: "dawn@example.com", when: "2026-06-01T12:30:00Z" } } ], runs: [{ start: 1, count: 1, commit: "abc123" }] }) ); const ctx = makeCtx(fetchMock);
const runs = await blameCall(ctx); expect(runs[0].commit.subject).toBe("subject line"); expect(runs[0].commit.author.did).toBeUndefined(); });
it("propagates mirror errors that are not a mirror miss", async () => { const fetchMock = vi .fn<typeof globalThis.fetch>() .mockResolvedValue(errorResponse(500, "InternalError")); const ctx = makeCtx(fetchMock);
await expect(blameCall(ctx)).rejects.toThrow("InternalError"); expect(fetchMock).toHaveBeenCalledTimes(1); });
it("rejects duplicate commit metadata", async () => { const commit = { oid: "abc123", message: "add main", author: { name: "dawn", email: "dawn@example.com", when: "2026-06-01T12:30:00Z" } }; const fetchMock = vi.fn<typeof globalThis.fetch>().mockResolvedValue( mirrorResponse({ commits: [commit, commit], runs: [{ start: 1, count: 1, commit: "abc123" }] }) ); const ctx = makeCtx(fetchMock);
await expect(blameCall(ctx)).rejects.toThrow("duplicate blame commit: abc123"); });
it("rejects runs that reference missing commits", async () => { const fetchMock = vi .fn<typeof globalThis.fetch>() .mockResolvedValue( mirrorResponse({ commits: [], runs: [{ start: 1, count: 1, commit: "abc123" }] }) ); const ctx = makeCtx(fetchMock);
await expect(blameCall(ctx)).rejects.toThrow("unknown blame commit: abc123"); });
it("rejects non-contiguous run tables", async () => { const fetchMock = vi.fn<typeof globalThis.fetch>().mockResolvedValue( mirrorResponse({ commits: [ { oid: "abc123", message: "add main", author: { name: "dawn", email: "dawn@example.com", when: "2026-06-01T12:30:00Z" } } ], runs: [{ start: 2, count: 1, commit: "abc123" }] }) ); const ctx = makeCtx(fetchMock);
await expect(blameCall(ctx)).rejects.toThrow("invalid blame run at line 2"); });});
describe("hydrateBlameAuthors", () => { it("bounds identity lookups for large blame results", async () => { const blame = Array.from({ length: 300 }, (_, index) => ({ start: index + 1, count: 1, commit: { sha: `sha-${index}`, subject: `commit ${index}`, when: "2026-06-01T12:30:00Z", author: { name: `author ${index}`, email: `did:plc:blameauthor${index}`, did: `did:plc:blameauthor${index}` } } })); const fetchMock = vi.fn<typeof globalThis.fetch>(async (input) => { const url = new URL(String(input)); const did = url.searchParams.get("identifier")!; return jsonResponse({ did, handle: `${did.slice("did:plc:".length)}.example` }); });
const ctx = createBobbinClient({ serviceUrl: "https://bobbin.example", fetch: fetchMock }); const hydrated = await hydrateBlameAuthors(blame, ctx);
expect(fetchMock).toHaveBeenCalledTimes(250); expect(hydrated[249].commit.author.handle).toBe("blameauthor249.example"); expect(hydrated[250].commit.author.handle).toBeUndefined(); });});