import assert from "node:assert/strict"; import { test } from "node:test"; import { ancestors, treeFromPaths, visibleRows, type TreeNode } from "../src/tree/model.ts"; /** The tree as indented labels, branches marked with a trailing `/`. */ const outline = (nodes: readonly TreeNode[], depth = 0): string[] => nodes.flatMap((node) => [ `${" ".repeat(depth)}${node.label}${node.children ? "/" : ""}`, ...(node.children ? outline(node.children, depth + 1) : []), ]); test("branches come from path prefixes and sort before leaves, by label", () => { const tree = treeFromPaths(["README.md", "src/main.ts", "src/lib/greet.ts", "a.txt", "src/lib/b10.ts", "src/lib/b9.ts"]); assert.deepEqual(outline(tree), ["src/", " lib/", " b9.ts", " b10.ts", " greet.ts", " main.ts", "a.txt", "README.md"]); assert.equal(tree[0]!.children![0]!.children![2]!.id, "src/lib/greet.ts", "ids are paths"); }); test("a hidden segment drops every path under it", () => { const hidden = (segment: string) => segment.startsWith("."); assert.deepEqual(outline(treeFromPaths([".agents/c.json", "src/.cache/x", "src/a.ts", ".env"], { hidden })), ["src/", " a.ts"]); }); test("only children of expanded branches are visible, each with its level and sibling position", () => { const tree = treeFromPaths(["src/lib/greet.ts", "src/main.ts", "README.md"]); const rows = (expanded: string[]) => visibleRows(tree, new Set(expanded)).map((r) => `${r.level}:${r.node.id}:${r.position}/${r.siblings}:${r.parent ?? "-"}`); assert.deepEqual(rows([]), ["1:src:1/2:-", "1:README.md:2/2:-"]); assert.deepEqual(rows(["src/lib"]), ["1:src:1/2:-", "1:README.md:2/2:-"], "a collapsed parent hides an expanded child"); assert.deepEqual(rows(["src", "src/lib"]), [ "1:src:1/2:-", "2:src/lib:1/2:src", "3:src/lib/greet.ts:1/1:src/lib", "2:src/main.ts:2/2:src", "1:README.md:2/2:-", ]); }); test("ancestors finds the branches above a node by id, whatever the ids look like", () => { const tree: TreeNode[] = [{ id: "x", label: "X", children: [{ id: "y", label: "Y", children: [{ id: "z", label: "Z" }] }] }]; assert.deepEqual(ancestors(tree, "z"), ["x", "y"]); assert.deepEqual(ancestors(tree, "x"), []); assert.equal(ancestors(tree, "nope"), undefined); }); test("a branch with no children is still a branch", () => { assert.deepEqual(visibleRows([{ id: "empty", label: "empty", children: [] }], new Set(["empty"])).length, 1); });