import { describe, expect, it } from "vitest"; import { emptyLayout, equalizeRatios, leaves, locateSession, openSessions, removeLeaf, splitLeaf, type Tab, } from "./layout.js"; function tabWithOneLeaf(sessionId: string | null = null): Tab { const layout = emptyLayout(); const tab = layout.tabs[0]; splitLeaf(tab, "", sessionId, "row", true); return tab; } describe("splitLeaf", () => { it("seeds an empty tab with a single leaf", () => { const tab = tabWithOneLeaf("s1"); expect(leaves(tab.root)).toHaveLength(1); expect(leaves(tab.root)[0].sessionId).toBe("s1"); }); it("splits a leaf in two and returns the new id", () => { const tab = tabWithOneLeaf("s1"); const target = leaves(tab.root)[0].id; const fresh = splitLeaf(tab, target, "s2", "row", true); const ids = leaves(tab.root).map((l) => l.id); expect(ids).toHaveLength(2); expect(ids).toContain(fresh); }); it("honours the side the caller asked for", () => { const tab = tabWithOneLeaf("s1"); const target = leaves(tab.root)[0].id; const fresh = splitLeaf(tab, target, "s2", "row", false); expect(leaves(tab.root)[0].id).toBe(fresh); }); }); describe("equalizeRatios", () => { it("resets nested splits to equal width, not just the newest one", () => { const tab = tabWithOneLeaf("s1"); const first = leaves(tab.root)[0].id; splitLeaf(tab, first, "s2", "row", true); // A|B, 0.5/0.5 const second = leaves(tab.root)[1].id; splitLeaf(tab, second, "s3", "row", true); // A(0.5) | (B|C, 0.5/0.5) -> B,C at 0.25 each equalizeRatios(tab.root); const root = tab.root as Extract; expect(root.ratio).toBeCloseTo(1 / 3); const inner = root.b as Extract; expect(inner.ratio).toBeCloseTo(1 / 2); }); }); describe("removeLeaf", () => { it("collapses the parent split into the surviving sibling", () => { const tab = tabWithOneLeaf("s1"); const first = leaves(tab.root)[0].id; splitLeaf(tab, first, "s2", "row", true); removeLeaf(tab, first); const remaining = leaves(tab.root); expect(remaining).toHaveLength(1); expect(remaining[0].sessionId).toBe("s2"); expect(tab.root?.kind).toBe("leaf"); }); it("empties the tab when the last leaf goes", () => { const tab = tabWithOneLeaf("s1"); removeLeaf(tab, leaves(tab.root)[0].id); expect(tab.root).toBeNull(); }); }); describe("locateSession / openSessions", () => { it("finds the tab and leaf showing a session", () => { const layout = emptyLayout(); const tab = layout.tabs[0]; splitLeaf(tab, "", "s1", "row", true); const hit = locateSession(layout, "s1"); expect(hit?.tab.id).toBe(tab.id); expect(hit?.leaf.sessionId).toBe("s1"); expect(locateSession(layout, "nope")).toBeNull(); }); it("reports every open session once", () => { const layout = emptyLayout(); const tab = layout.tabs[0]; splitLeaf(tab, "", "s1", "row", true); const first = leaves(tab.root)[0].id; splitLeaf(tab, first, "s2", "row", true); expect(openSessions(layout)).toEqual(new Set(["s1", "s2"])); }); });