import { describe, expect, test } from "bun:test"; import { fastForward } from "./fast-forward"; import type { CommitSummary } from "~/lib/types"; type Graph = Record; function storeFor(graph: Graph) { return { async prefetchHistory() {}, async commit(sha: string): Promise { const parents = graph[sha]; if (!parents) return null; return { sha, shortSha: sha.slice(0, 7), subject: sha, message: sha, authorName: "A", authorEmail: "a@example.com", committerName: "A", authoredAt: 0, committedAt: 0, parents, treeSha: "t", }; }, }; } /** a <- b <- c is indexed with head c. */ const base: Graph = { a: [], b: ["a"], c: ["b"] }; const indexed = (sha: string) => ["a", "b", "c"].includes(sha); const shas = (commits: Array<{ sha: string }> | null) => commits?.map((commit) => commit.sha).sort() ?? null; describe("fastForward", () => { test("linear fast-forward returns only the new commits", async () => { const graph = { ...base, d: ["c"], e: ["d"] }; expect(shas(await fastForward(storeFor(graph), indexed, "c", "e"))).toEqual(["d", "e"]); }); test("a merge that brings in a side branch picks up every new commit", async () => { const graph = { ...base, x: ["a"], y: ["x"], m: ["c", "y"] }; expect(shas(await fastForward(storeFor(graph), indexed, "c", "m"))).toEqual(["m", "x", "y"]); }); test("a force-push that drops the old head needs a rebuild", async () => { const graph = { ...base, c2: ["b"] }; expect(await fastForward(storeFor(graph), indexed, "c", "c2")).toBeNull(); }); test("rewinding to an indexed ancestor needs a rebuild", async () => { expect(await fastForward(storeFor(base), indexed, "c", "b")).toBeNull(); }); test("an unrelated history needs a rebuild", async () => { const graph = { ...base, r: [], s: ["r"] }; expect(await fastForward(storeFor(graph), indexed, "c", "s")).toBeNull(); }); }); describe("coAuthorEmails", () => { test("reads Co-authored-by trailers case-insensitively, skipping the author and duplicates", async () => { const { coAuthorEmails } = await import("./fast-forward"); const message = [ "Fix the thing", "", "Co-authored-by: Bob ", "co-authored-by: Carol Smith ", "Co-Authored-By: Me ", "Co-authored-by: Bob again ", "Co-authored-by: nobody-without-brackets", ].join("\n"); expect(coAuthorEmails(message, "ME@example.com")).toEqual(["bob@example.com", "carol@example.com"]); }); });