test(tui): cover renderBox borders, padding and side-by-side composition

Rescued from the deleted root-level scratch scripts test_box.ts,
test_split_box.ts and test_split_box2.ts, which were never run by bun test
and were never typechecked (tsconfig only includes src/**/*).

Adds onto the existing src/tui/usage/render.test.ts instead of replacing it,
so the npub/client-label/stacked-bar coverage stays intact.
This commit is contained in:
redshift
2026-09-14 14:17:40 +02:00
parent 067ad63312
commit 319585e67b
+78 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test";
import { renderNpubs, renderRecent, renderStackedBar, tokenSegments } from "./render.ts";
import { renderBox, renderNpubs, renderRecent, renderStackedBar, tokenSegments } from "./render.ts";
import { stripAnsi } from "./terminal.ts";
import { COLORS } from "./constants.ts";
import { buildClientNaming, resolveClientLabel, type ClientInfo, type NpubEntry } from "./data.ts";
@@ -254,3 +254,80 @@ describe("renderRecent token bars", () => {
}
});
});
/** Visible column count of a rendered line, ignoring ANSI colour codes. */
function visibleWidths(box: string): number[] {
return box.split("\n").map((line) => stripAnsi(line).length);
}
describe("renderBox", () => {
test("renders every line at the requested width when given a title", () => {
const box = renderBox(["Hello World", "Line 2"], 40, "Title");
expect(box.split("\n")).toHaveLength(4); // top, 2 content rows, bottom
for (const width of visibleWidths(box)) {
expect(width).toBe(40);
}
});
test("renders every line at the requested width without a title", () => {
const box = renderBox(["Hello World", "Line 2"], 40);
for (const width of visibleWidths(box)) {
expect(width).toBe(40);
}
});
test("puts the title in the top border", () => {
const [topBorder] = renderBox(["body"], 40, "Stats of Sats").split("\n");
expect(topBorder).toContain("Stats of Sats");
});
test("pads content rows so ANSI-coloured lines still align", () => {
const colored = "\x1b[32mgreen\x1b[0m";
const box = renderBox([colored, "plain"], 30);
for (const width of visibleWidths(box)) {
expect(width).toBe(30);
}
});
test("composes two half-width boxes into rows of the full width", () => {
const width = 80;
const halfWidth1 = Math.floor(width / 2);
const halfWidth2 = width - halfWidth1;
const left = renderBox(
["Total Spent: 12.78k sats", "Total Requests: 1.0k"],
halfWidth1,
"Stats of Sats",
).split("\n");
const right = renderBox(
["Total Tokens: 25.8M", "Avg Tokens/Req: 25.8K"],
halfWidth2,
"Token Stats",
).split("\n");
expect(left).toHaveLength(right.length);
for (let i = 0; i < left.length; i++) {
expect(stripAnsi(left[i]! + right[i]!).length).toBe(width);
}
});
test("pads the shorter side when the two boxes have unequal heights", () => {
const width = 80;
const halfWidth1 = Math.floor(width / 2);
const halfWidth2 = width - halfWidth1;
const left = renderBox(["a", "b", "c"], halfWidth1, "Left").split("\n");
const right = renderBox(["x"], halfWidth2, "Right").split("\n");
const rows = Math.max(left.length, right.length);
for (let i = 0; i < rows; i++) {
const l = left[i] ?? " ".repeat(halfWidth1);
const r = right[i] ?? " ".repeat(halfWidth2);
expect(stripAnsi(l + r).length).toBe(width);
}
});
});