@logtape/pretty
Version:
Beautiful text formatter for LogTape—perfect for local development
111 lines (89 loc) • 4.09 kB
text/typescript
import { suite } from "@alinea/suite";
import { assertEquals } from "@std/assert/equals";
import { assert } from "@std/assert/assert";
import { wrapText } from "./wordwrap.ts";
const test = suite(import.meta);
test("wrapText() should not wrap short text", () => {
const result = wrapText("short text", 80, "short text");
assertEquals(result, "short text");
});
test("wrapText() should wrap long text", () => {
const text =
"This is a very long line that should be wrapped at 40 characters maximum width for testing purposes.";
const result = wrapText(text, 40, "This is a very long line");
const lines = result.split("\n");
assert(lines.length > 1, "Should have multiple lines");
// Each line should be within the limit (with some tolerance for word boundaries)
for (const line of lines) {
assert(line.length <= 45, `Line too long: ${line.length} chars`);
}
});
test("wrapText() should preserve ANSI codes", () => {
const text =
"\x1b[31mThis is a very long red line that should be wrapped while preserving the color codes\x1b[0m";
const result = wrapText(text, 40, "This is a very long red line");
// Should contain ANSI codes
assert(result.includes("\x1b[31m"), "Should preserve opening ANSI code");
assert(result.includes("\x1b[0m"), "Should preserve closing ANSI code");
});
test("wrapText() should handle emojis correctly", () => {
const text =
"✨ info test This is a very long message that should wrap properly with emoji alignment";
const result = wrapText(text, 40, "This is a very long message");
const lines = result.split("\n");
assert(lines.length > 1, "Should have multiple lines");
// Check that continuation lines are indented properly
// The emoji ✨ should be accounted for in width calculation
const firstLine = lines[0];
const continuationLine = lines[1];
assert(firstLine.includes("✨"), "First line should contain emoji");
assert(
continuationLine.startsWith(" "),
"Continuation line should be indented",
);
});
test("wrapText() should handle newlines in interpolated content", () => {
const textWithNewlines =
"Error occurred: Error: Something went wrong\n at line 1\n at line 2";
const result = wrapText(textWithNewlines, 40, "Error occurred");
const lines = result.split("\n");
assert(
lines.length >= 3,
"Should preserve original newlines and add more if needed",
);
});
test("wrapText() should calculate indentation based on display width", () => {
// Test with different emojis that have different string lengths but same display width
const sparklesText = "✨ info test Message content here";
const crossText = "❌ error test Message content here";
const sparklesResult = wrapText(sparklesText, 25, "Message content here");
const crossResult = wrapText(crossText, 25, "Message content here");
const sparklesLines = sparklesResult.split("\n");
const crossLines = crossResult.split("\n");
if (sparklesLines.length > 1 && crossLines.length > 1) {
// Both should have similar indentation for continuation lines
// (accounting for the fact that both emojis are width 2)
const sparklesIndent = sparklesLines[1].search(/\S/);
const crossIndent = crossLines[1].search(/\S/);
// The indentation should be very close (within 1-2 characters)
// since both emojis have width 2
assert(
Math.abs(sparklesIndent - crossIndent) <= 2,
`Indentation should be similar: sparkles=${sparklesIndent}, cross=${crossIndent}`,
);
}
});
test("wrapText() should handle zero width", () => {
const result = wrapText("any text", 0, "any text");
assertEquals(result, "any text");
});
test("wrapText() should break at word boundaries", () => {
const text = "word1 word2 word3 word4 word5";
const result = wrapText(text, 15, "word1 word2 word3");
const lines = result.split("\n");
// Should break at spaces, not in the middle of words
for (const line of lines) {
const words = line.trim().split(" ");
assert(words.every((word) => word.length > 0), "Should not break words");
}
});