import { describe, expect, it } from "vitest"; import { layout } from "./layout"; const row = (hash: string, ...parents: string[]) => ({ commit: { hash }, parents: parents.map((p) => ({ hash: p.replace("~", ""), dotted: p.startsWith("~") })), }); describe("layout", () => { it("puts a straight line in one column with one color", () => { const r = layout([row("c", "b"), row("b", "a"), row("a")]); expect(r.rows.map((x) => x.col)).toEqual([0, 0, 0]); expect(new Set(r.rows.map((x) => x.color)).size).toBe(1); expect(r.width).toBe(1); }); it("opens a second column for a merged branch and joins it back", () => { const r = layout([row("m", "a", "b"), row("b", "a"), row("a")]); expect(r.rows.map((x) => x.col)).toEqual([0, 1, 0]); expect(r.rows[1].color).not.toBe(r.rows[0].color); expect(r.width).toBe(2); // Below b, its line bends from column 1 back into column 0. expect(r.rows[1].segments).toContainEqual( expect.objectContaining({ x1: 1, y1: 0.5, x2: 0, y2: 1 }), ); }); it("draws a line that passes a row as a straight segment", () => { const r = layout([row("m", "a", "b"), row("b", "a"), row("a")]); // At row b, column 0 is still waiting for a. expect(r.rows[1].segments).toContainEqual( expect.objectContaining({ x1: 0, y1: 0, x2: 0, y2: 1 }), ); }); it("starts a new column for a second branch tip", () => { const r = layout([row("x", "a"), row("y", "a"), row("a")]); expect(r.rows.map((x) => x.col)).toEqual([0, 1, 0]); }); it("carries dotted edges down to the parent", () => { const r = layout([row("m", "a", "~b"), row("z", "q"), row("q"), row("b", "a"), row("a")]); const dotted = r.rows.flatMap((x) => x.segments).filter((s) => s.dotted); expect(dotted.length).toBeGreaterThan(0); expect(r.rows[3].segments.some((s) => s.dotted && s.y2 === 0.5)).toBe(true); }); });