Merge pull request #104 from Routstr/test/tui-render-box-coverage

test(tui): cover renderBox borders, padding and side-by-side composition
This commit is contained in:
redshift
2026-09-14 14:21:54 +02:00
committed by GitHub
+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);
}
});
});