From e9845d1ce892ffe62d1c1696ef1d8ffac68b0871 Mon Sep 17 00:00:00 2001 From: Sam Smith Date: Thu, 31 Jul 2025 13:00:07 -0400 Subject: [PATCH] Add tests for MaxWidth and improve truncation logic Implemented unit tests in `ConsoleTableTest.cs` to validate the behavior of the `MaxWidth` property, ensuring that setting it to zero disables truncation and that positive values truncate long text correctly. Updated `ConsoleTable.cs` to skip truncation when `MaxWidth` is zero or negative, refining the logic to respect word boundaries during text truncation. --- src/ConsoleTables.Tests/ConsoleTableTest.cs | 38 ++++++++++++++++++++ src/ConsoleTables/ConsoleTable.cs | 39 +++++++++++---------- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/ConsoleTables.Tests/ConsoleTableTest.cs b/src/ConsoleTables.Tests/ConsoleTableTest.cs index 99db7e7..86c46aa 100644 --- a/src/ConsoleTables.Tests/ConsoleTableTest.cs +++ b/src/ConsoleTables.Tests/ConsoleTableTest.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Data; using System.IO; +using System.Linq; using Xunit; namespace ConsoleTables.Tests @@ -280,6 +281,43 @@ this line should be longer 哈哈哈哈 yes it is oh """, table); } + [Fact] + public void MaxWidthZeroShouldDisableTruncation() + { + var table = new ConsoleTable("Column1", "Column2"); + table.MaxWidth = 0; // Should disable truncation completely + table.AddRow("This is a very long text that should not be truncated when MaxWidth is 0", "Short"); + + var result = table.ToString(); + + // Should contain the full text without truncation + Assert.Contains("This is a very long text that should not be truncated when MaxWidth is 0", result); + Assert.Contains("Short", result); + + // Should only have one data row (no extra rows from word wrapping) + var lines = result.Split('\n'); + var dataLines = lines.Where(line => line.Contains("This is a very long") || line.Contains("Short")).ToArray(); + Assert.Single(dataLines); + } + + [Fact] + public void MaxWidthPositiveValueShouldTruncate() + { + var table = new ConsoleTable("Column1", "Column2"); + table.MaxWidth = 10; // Should truncate at 10 characters + table.AddRow("This is a very long text that should be truncated", "Short"); + + var result = table.ToString(); + + // Should not contain the full original text in a single line + Assert.DoesNotContain("This is a very long text that should be truncated", result); + + // Should have multiple rows due to word wrapping + var lines = result.Split('\n'); + var dataLines = lines.Where(line => line.Contains("|") && !line.All(c => c == ' ' || c == '-' || c == '|')).ToArray(); + Assert.True(dataLines.Length > 2); // Header + at least 2 data rows due to wrapping + } + class User { public string Name { get; set; } diff --git a/src/ConsoleTables/ConsoleTable.cs b/src/ConsoleTables/ConsoleTable.cs index 629815f..1513d1d 100644 --- a/src/ConsoleTables/ConsoleTable.cs +++ b/src/ConsoleTables/ConsoleTable.cs @@ -217,31 +217,34 @@ private void SetFormats(List columnLengths, List columnAlignment, s { var row = Rows[i]; - if (row.Any(o => o != null && o.ToString().Length > MaxWidth)) //checks if any column exceeds the MaxWidth + // Skip truncation entirely if MaxWidth is 0 or negative + if (MaxWidth <= 0 || !row.Any(o => o != null && o.ToString().Length > MaxWidth)) //checks if any column exceeds the MaxWidth { - var newRow = new object[row.Length]; - for (var j = 0; j < row.Length; j++) //loop through cells + continue; + } + + var newRow = new object[row.Length]; + for (var j = 0; j < row.Length; j++) //loop through cells + { + var cellStr = row[j]?.ToString() ?? ""; + if (cellStr.Length > MaxWidth) //if cell exceeds MaxWidth { - var cellStr = row[j]?.ToString() ?? ""; - if (cellStr.Length > MaxWidth) //if cell exceeds MaxWidth + var cutCell = cellStr[..MaxWidth]; //cut the cell + var leftOver = cellStr[MaxWidth..]; //into two parts + if (cutCell.Length > 0 && cutCell[^1] != ' ' && cutCell[0] != ' ') //if the cut is in the middle of a word { - var cutCell = cellStr[..MaxWidth]; //cut the cell - var leftOver = cellStr[MaxWidth..]; //into two parts - if (cutCell[^1] != ' ' && cutCell[0] != ' ') //if the cut is in the middle of a word + var lastSpace = cutCell.LastIndexOf(WordBreakDelimiter); //find the last WordBreak Delimiter of the first cell + if (lastSpace > 0) //if there is a space { - var lastSpace = cutCell.LastIndexOf(WordBreakDelimiter); //find the last WordBreak Delimiter of the first cell - if (lastSpace > 0) //if there is a space - { - cutCell = cellStr[..lastSpace]; //cut the cell at the last space - leftOver = cellStr[lastSpace..]; //the leftover is the rest of the cell - }//if there is no space, the cell will be cut at MaxWidth - } - newRow[j] = leftOver.Trim(); - Rows[i][j] = cutCell.Trim(); + cutCell = cellStr[..lastSpace]; //cut the cell at the last space + leftOver = cellStr[lastSpace..]; //the leftover is the rest of the cell + }//if there is no space, the cell will be cut at MaxWidth } + newRow[j] = leftOver.Trim(); + Rows[i][j] = cutCell.Trim(); } - Rows.Insert(i + 1, newRow); } + Rows.Insert(i + 1, newRow); } allLines.AddRange(Rows);