import assert from "node:assert/strict"; import { describe, test } from "node:test"; function expect(actual) { return { toBe(expected) { assert.equal(actual, expected); }, toContain(expected) { assert.ok(actual.includes(expected)); }, not: { toContain(expected) { assert.ok(!actual.includes(expected)); } }, toBeGreaterThan(expected) { assert.ok(actual > expected); }, toBeGreaterThanOrEqual(expected) { assert.ok(actual >= expected); }, toBeLessThan(expected) { assert.ok(actual < expected); }, toBeLessThanOrEqual(expected) { assert.ok(actual <= expected); }, }; } import { createTable, drawBox, drawNested } from "./index.mjs"; describe("drawBox", () => { test("simple box with content", () => { const result = drawBox("Hello", { width: 10 }); const lines = result.split("\n"); expect(lines.length).toBe(3); expect(lines[0]).toContain("┌"); expect(lines[0]).toContain("┐"); expect(lines[1]).toContain("│"); expect(lines[2]).toContain("└"); expect(lines[2]).toContain("┘"); }); test("content alignment left", () => { const result = drawBox("Test", { width: 20, alignment: "left" }); const lines = result.split("\n"); const contentLine = lines[1]; const testIndex = contentLine.indexOf("Test"); const pipeIndex = contentLine.indexOf("│"); expect(contentLine[pipeIndex]).toBe("│"); expect(testIndex).toBe(pipeIndex + 2); }); test("content alignment center", () => { const result = drawBox("Hi", { width: 20, alignment: "center" }); const lines = result.split("\n"); expect(lines[1][0]).toBe("│"); }); test("content alignment right", () => { const result = drawBox("X", { width: 10, alignment: "right" }); const lines = result.split("\n"); const contentLine = lines[1]; const rightPipeIndex = contentLine.lastIndexOf("│"); expect(contentLine[rightPipeIndex]).toBe("│"); }); test("double border style", () => { const result = drawBox("Test", { style: "double" }); expect(result).toContain("╔"); expect(result).toContain("╗"); expect(result).toContain("╚"); expect(result).toContain("╝"); expect(result).toContain("║"); expect(result).toContain("═"); expect(result).not.toContain("┌"); expect(result).not.toContain("│"); }); test("bold border style", () => { const result = drawBox("Test", { style: "bold" }); expect(result).toContain("┏"); expect(result).toContain("┓"); expect(result).toContain("┗"); expect(result).toContain("┛"); expect(result).toContain("┃"); expect(result).toContain("━"); }); test("padding", () => { const result = drawBox("X", { width: 10, paddingTop: 2, paddingBottom: 2, paddingLeft: 2, paddingRight: 2, }); const lines = result.split("\n"); expect(lines.length).toBe(7); expect(lines[0]).toContain("┌"); expect(lines[6]).toContain("┘"); expect(lines[1]).toContain("│"); expect(lines[2]).toContain("│"); expect(lines[3]).toContain("X"); expect(lines[4]).toContain("│"); }); test("multi-line content", () => { const result = drawBox(["Line 1", "Line 2", "Line 3"], { width: 20 }); const lines = result.split("\n"); expect(lines.length).toBe(5); expect(result).toContain("Line 1"); expect(result).toContain("Line 2"); expect(result).toContain("Line 3"); }); test("wrap long text", () => { const result = drawBox("This is a very long sentence that needs wrapping", { width: 20, }); const lines = result.split("\n"); expect(lines.length).toBeGreaterThan(3); }); test("array content", () => { const lines = ["Line 1", "Line 2", "Line 3"]; const result = drawBox(lines, { width: 20 }); expect(result).toContain("Line 1"); expect(result).toContain("Line 2"); expect(result).toContain("Line 3"); expect(result.split("\n").length).toBe(5); }); test("alignment right with padding", () => { const result = drawBox("X", { width: 10, alignment: "right", paddingLeft: 2, paddingRight: 2, }); const lines = result.split("\n"); const contentLine = lines[1]; const xIdx = contentLine.indexOf("X"); const rightPipe = contentLine.lastIndexOf("│"); const leftPipe = contentLine.indexOf("│"); expect(xIdx).toBeLessThan(rightPipe); expect(xIdx).toBeGreaterThan(leftPipe); }); test("single character wide", () => { const result = drawBox("X", { width: 1 }); expect(result).toContain("┌───┐"); expect(result).toContain("│ X │"); expect(result).toContain("└───┘"); }); test("zero padding", () => { const result = drawBox("AB", { width: 4, paddingTop: 0, paddingBottom: 0, paddingLeft: 0, paddingRight: 0, }); const lines = result.split("\n"); expect(lines.length).toBe(3); expect(lines[0]).toContain("┌────┐"); expect(lines[1]).toContain("│AB │"); expect(lines[2]).toContain("└────┘"); }); test("long text forces wrap", () => { const result = drawBox("This is a very long line of text", { width: 10 }); const lines = result.split("\n"); expect(lines.length).toBeGreaterThan(3); const contentLines = lines.slice(1, -1); for (const cl of contentLines) { const firstPipe = cl.indexOf("│"); const lastPipe = cl.lastIndexOf("│"); const betweenPipes = cl.slice(firstPipe + 1, lastPipe); expect(betweenPipes.length).toBeLessThanOrEqual(12); } }); }); describe("createTable", () => { test("simple table", () => { const result = createTable( ["Name", "Age"], [ ["Alice", "30"], ["Bob", "25"], ], ); expect(result).toContain("Name"); expect(result).toContain("Age"); expect(result).toContain("Alice"); expect(result).toContain("Bob"); expect(result).toContain("┌"); expect(result).toContain("┐"); expect(result).toContain("└"); expect(result).toContain("┘"); }); test("separator line uses tee", () => { const result = createTable(["H1", "H2"], [["a", "b"]]); const lines = result.split("\n"); expect(lines[2]).toContain("├"); expect(lines[2]).toContain("┤"); expect(lines[2]).toContain("┼"); }); test("double style", () => { const result = createTable(["H"], [["d"]], { style: "double" }); expect(result).toContain("╔"); expect(result).toContain("╗"); expect(result).toContain("╠"); expect(result).toContain("╣"); expect(result).toContain("║"); expect(result).toContain("═"); }); test("padding", () => { const result = createTable(["Name"], [["Alice"]], { padding: 3 }); expect(result).toContain("│ Name"); expect(result).toContain("│ Alice"); }); test("empty rows", () => { const result = createTable(["A", "B"], [], { style: "single" }); expect(result).toContain("A"); expect(result).toContain("B"); expect(result).toContain("├"); expect(result).toContain("┤"); }); test("single column", () => { const result = createTable(["Name"], [["Alice"], ["Bob"]]); expect(result).toContain("Name"); expect(result).toContain("Alice"); expect(result).toContain("Bob"); }); }); describe("drawNested", () => { test("nested boxes", () => { const result = drawNested("Outer", "Inner"); expect(result).toContain("Outer"); expect(result).toContain("Inner"); expect((result.match(/┌/g) || []).length).toBe(2); }); test("with gap", () => { const result = drawNested("O", "I", { gap: 2 }); expect(result).toContain("O"); expect(result).toContain("I"); const innerLine = result.split("\n").findIndex((l) => l.includes("I")); const outerLine = result.split("\n").findIndex((l) => l.includes("O")); expect(Math.abs(innerLine - outerLine)).toBeGreaterThan(2); }); test("zero width content", () => { const result = drawNested("", "", { gap: 0 }); expect(result).toContain("┌"); expect(result).toContain("└"); }); test("different styles", () => { const result = drawNested("O", "I", { styleOuter: "double", styleInner: "bold", gap: 0, }); expect(result.includes("╔") || result.includes("╗")).toBe(true); expect(result.includes("┏") || result.includes("┓")).toBe(true); }); test("gap creates space", () => { const r1 = drawNested("O", "I", { gap: 0 }); const r2 = drawNested("O", "I", { gap: 2 }); expect(r2.split("\n").length).toBeGreaterThanOrEqual( r1.split("\n").length + 2, ); }); }); describe("border styles", () => { test("are consistent", () => { const single = drawBox("T", { style: "single" }); const double = drawBox("T", { style: "double" }); const bold = drawBox("T", { style: "bold" }); expect( single.includes("┌") && single.includes("─") && single.includes("│"), ).toBe(true); expect( double.includes("╔") && double.includes("═") && double.includes("║"), ).toBe(true); expect(bold.includes("┏") && bold.includes("━") && bold.includes("┃")).toBe( true, ); expect(single).not.toContain("╔"); expect(double).not.toContain("┌"); }); }); describe("demo - system status panel", () => { test("renders without errors", () => { const box = drawBox(" System Status ", { style: "bold", width: 30, alignment: "center", paddingTop: 1, paddingBottom: 1, }); const table = createTable( ["Module", "Status"], [ ["Agent Core", "✅"], ["Memory", "45%"], ["Cache", "OK"], ], { padding: 2 }, ); expect(box.length).toBeGreaterThan(0); expect(table.length).toBeGreaterThan(0); expect(box).toContain("┏"); expect(box).toContain("┛"); }); });