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"); } });