From 010beffae042a039daa273c3bae41643ad3c04ef Mon Sep 17 00:00:00 2001 From: Phil Scott Date: Mon, 10 Feb 2025 20:57:38 -0500 Subject: [PATCH 1/3] Normalizes paths when writing exceptions to the console for tests. The verified output for Should_Write_GenericException was outputting ProjectDirectory}Data\Exceptions.cs on my Windows machine, but the Verified version wasProjectDirectory}Data/Exceptions.cs Wasn't causing a build issue because we run those on Ubuntu, but locally it was giving me an error. --- .../TestConsoleExtensions.Exceptions.cs | 59 ------------------- .../Utilities/TestConsoleExtensions.cs | 41 +++++++++++++ 2 files changed, 41 insertions(+), 59 deletions(-) delete mode 100644 src/Spectre.Console.Testing/Extensions/TestConsoleExtensions.Exceptions.cs create mode 100644 src/Tests/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs diff --git a/src/Spectre.Console.Testing/Extensions/TestConsoleExtensions.Exceptions.cs b/src/Spectre.Console.Testing/Extensions/TestConsoleExtensions.Exceptions.cs deleted file mode 100644 index 582ddf182..000000000 --- a/src/Spectre.Console.Testing/Extensions/TestConsoleExtensions.Exceptions.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace Spectre.Console.Testing; - -/// -/// Provides extension methods for working with in a testing context, -/// including stack trace normalization for consistent and deterministic test output. -/// -public static partial class TestConsoleExtensions -{ - private static readonly Regex _lineNumberRegex = new Regex(":\\d+", RegexOptions.Singleline); - private static readonly Regex _filenameRegex = new Regex("\\sin\\s.*cs:nn", RegexOptions.Multiline); - - /// - /// Writes the given exception to the and returns a normalized string - /// representation of the exception, with file paths and line numbers sanitized. - /// - /// The to write to. - /// The exception to write and normalize. - /// Optional formatting options for exception output. - /// A normalized string of the exception's output, safe for snapshot testing. - /// - /// Thrown if the console's output buffer is not empty before writing the exception. - /// - public static string WriteNormalizedException(this TestConsole console, Exception ex, ExceptionFormats formats = ExceptionFormats.Default) - { - if (!string.IsNullOrWhiteSpace(console.Output)) - { - throw new InvalidOperationException("Output buffer is not empty."); - } - - console.WriteException(ex, formats); - return string.Join("\n", NormalizeStackTrace(console.Output) - .NormalizeLineEndings() - .Split(new char[] { '\n' }) - .Select(line => line.TrimEnd())); - } - - /// - /// Normalizes a stack trace string by replacing line numbers with ":nn" - /// and converting full file paths to a fixed placeholder path ("/xyz/filename.cs"). - /// - /// The stack trace text to normalize. - /// A sanitized stack trace suitable for stable testing output. - public static string NormalizeStackTrace(string text) - { - text = _lineNumberRegex.Replace(text, match => - { - return ":nn"; - }); - - return _filenameRegex.Replace(text, match => - { - var value = match.Value; - var index = value.LastIndexOfAny(new[] { '\\', '/' }); - var filename = value.Substring(index + 1, value.Length - index - 1); - - return $" in /xyz/{filename}"; - }); - } -} diff --git a/src/Tests/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs b/src/Tests/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs new file mode 100644 index 000000000..8617ebca2 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Utilities/TestConsoleExtensions.cs @@ -0,0 +1,41 @@ +namespace Spectre.Console.Tests; + +public static class TestConsoleExtensions +{ + private static readonly Regex _lineNumberRegex = new Regex(":\\d+", RegexOptions.Singleline); + private static readonly Regex _filenameRegex = new Regex("\\sin\\s.*cs:nn", RegexOptions.Multiline); + private static readonly Regex _pathSeparatorRegex = new Regex(@"[/\\]+"); + + public static string WriteNormalizedException(this TestConsole console, Exception ex, ExceptionFormats formats = ExceptionFormats.Default) + { + if (!string.IsNullOrWhiteSpace(console.Output)) + { + throw new InvalidOperationException("Output buffer is not empty."); + } + + console.WriteException(ex, formats); + return string.Join("\n", NormalizeStackTrace(console.Output) + .NormalizeLineEndings() + .Split(new char[] { '\n' }) + .Select(line => line.TrimEnd())); + } + + public static string NormalizeStackTrace(string text) + { + // First normalize line numbers + text = _lineNumberRegex.Replace(text, ":nn"); + + // Then normalize paths and filenames + text = _filenameRegex.Replace(text, match => + { + var value = match.Value; + var index = value.LastIndexOfAny(new[] { '\\', '/' }); + var filename = value.Substring(index + 1, value.Length - index - 1); + + return $" in /xyz/{filename}"; + }); + + // Finally normalize any remaining path separators + return _pathSeparatorRegex.Replace(text, "/"); + } +} From 1ec7b8ae8f756e59ec65048ba8e7b11bda6c053b Mon Sep 17 00:00:00 2001 From: Phil Scott Date: Fri, 31 Oct 2025 10:53:57 -0400 Subject: [PATCH 2/3] Fixes issue with Panel not applying overflow to children Add tests for widget content overflow scenarios in Panel, Table, and Grid widgets. --- src/Spectre.Console/Widgets/Panel.cs | 13 +- ...r_Cell_Markup_Overflow.Output.verified.txt | 3 + ...der_Cell_Overflow_Crop.Output.verified.txt | 3 + ...Cell_Overflow_Ellipsis.Output.verified.txt | 3 + ...der_Cell_Overflow_Fold.Output.verified.txt | 5 + ...l_Overflow_With_NoWrap.Output.verified.txt | 3 + ...rkup_Overflow_Ellipsis.Output.verified.txt | 5 + ...ed_Panel_With_Overflow.Output.verified.txt | 7 + ...der_Text_Overflow_Crop.Output.verified.txt | 5 + ...Text_Overflow_Ellipsis.Output.verified.txt | 5 + ...der_Text_Overflow_Fold.Output.verified.txt | 7 + ..._Overflow_With_Padding.Output.verified.txt | 5 + ...r_Cell_Markup_Overflow.Output.verified.txt | 7 + ...der_Cell_Overflow_Crop.Output.verified.txt | 7 + ...Cell_Overflow_Ellipsis.Output.verified.txt | 7 + ...der_Cell_Overflow_Fold.Output.verified.txt | 9 ++ ...Overflow_Multiple_Rows.Output.verified.txt | 11 ++ ...l_Overflow_With_NoWrap.Output.verified.txt | 7 + .../Unit/Widgets/GridTests.cs | 100 ++++++++++++++ .../Unit/Widgets/PanelTests.cs | 125 +++++++++++++++++ .../Unit/Widgets/Table/TableTests.cs | 126 ++++++++++++++++++ 21 files changed, 457 insertions(+), 6 deletions(-) create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Markup_Overflow.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Crop.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Ellipsis.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Fold.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_With_NoWrap.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Markup_Overflow_Ellipsis.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Nested_Panel_With_Overflow.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Crop.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Ellipsis.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Fold.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_With_Padding.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Markup_Overflow.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Crop.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Ellipsis.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Fold.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Multiple_Rows.Output.verified.txt create mode 100644 src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_With_NoWrap.Output.verified.txt diff --git a/src/Spectre.Console/Widgets/Panel.cs b/src/Spectre.Console/Widgets/Panel.cs index 7a34d9592..7fd0620b8 100644 --- a/src/Spectre.Console/Widgets/Panel.cs +++ b/src/Spectre.Console/Widgets/Panel.cs @@ -83,12 +83,13 @@ private Measurement Measure(RenderOptions options, int maxWidth, IRenderable chi if (Width != null) { var width = Width.Value - edgeWidth; - if (width > childWidth.Max) - { - childWidth = new Measurement( - childWidth.Min, - width); - } + + // If Width is specified, constrain or expand the measurement + // to exactly the specified width (clamped by maxWidth) + var constrainedWidth = Math.Min(width, maxWidth - edgeWidth); + childWidth = new Measurement( + Math.Min(childWidth.Min, constrainedWidth), + constrainedWidth); } return new Measurement( diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Markup_Overflow.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Markup_Overflow.Output.verified.txt new file mode 100644 index 000000000..5cc383515 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Markup_Overflow.Output.verified.txt @@ -0,0 +1,3 @@ +foo Short text +pneumonoultramicr… +bar diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Crop.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Crop.Output.verified.txt new file mode 100644 index 000000000..f1f82d196 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Crop.Output.verified.txt @@ -0,0 +1,3 @@ +foo Short text +pneumonoultrami +bar diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Ellipsis.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Ellipsis.Output.verified.txt new file mode 100644 index 000000000..127535510 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Ellipsis.Output.verified.txt @@ -0,0 +1,3 @@ +foo Short text +pneumonoultram… +bar diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Fold.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Fold.Output.verified.txt new file mode 100644 index 000000000..b04f31311 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_Fold.Output.verified.txt @@ -0,0 +1,5 @@ +foo Short text +pneumonoultrami +croscopicsilico +volcanoconiosis +bar diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_With_NoWrap.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_With_NoWrap.Output.verified.txt new file mode 100644 index 000000000..127535510 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Grid/Render_Cell_Overflow_With_NoWrap.Output.verified.txt @@ -0,0 +1,3 @@ +foo Short text +pneumonoultram… +bar diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Markup_Overflow_Ellipsis.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Markup_Overflow_Ellipsis.Output.verified.txt new file mode 100644 index 000000000..b73f65d10 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Markup_Overflow_Ellipsis.Output.verified.txt @@ -0,0 +1,5 @@ +┌──────────────────┐ +│ foo │ +│ pneumonoultrami… │ +│ bar qux │ +└──────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Nested_Panel_With_Overflow.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Nested_Panel_With_Overflow.Output.verified.txt new file mode 100644 index 000000000..3a6e9b27a --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Nested_Panel_With_Overflow.Output.verified.txt @@ -0,0 +1,7 @@ +┌───────────────────────┐ +│ ┌─────────────┐ │ +│ │ foo │ │ +│ │ pneumonoult │ │ +│ │ bar qux │ │ +│ └─────────────┘ │ +└───────────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Crop.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Crop.Output.verified.txt new file mode 100644 index 000000000..079270650 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Crop.Output.verified.txt @@ -0,0 +1,5 @@ +┌──────────────────┐ +│ foo │ +│ pneumonoultramic │ +│ bar qux │ +└──────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Ellipsis.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Ellipsis.Output.verified.txt new file mode 100644 index 000000000..b73f65d10 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Ellipsis.Output.verified.txt @@ -0,0 +1,5 @@ +┌──────────────────┐ +│ foo │ +│ pneumonoultrami… │ +│ bar qux │ +└──────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Fold.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Fold.Output.verified.txt new file mode 100644 index 000000000..8f0c51fb0 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_Fold.Output.verified.txt @@ -0,0 +1,7 @@ +┌──────────────────┐ +│ foo │ +│ pneumonoultramic │ +│ roscopicsilicovo │ +│ lcanoconiosis │ +│ bar qux │ +└──────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_With_Padding.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_With_Padding.Output.verified.txt new file mode 100644 index 000000000..6f4fa4d96 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Panel/Render_Text_Overflow_With_Padding.Output.verified.txt @@ -0,0 +1,5 @@ +┌───────────────────────┐ +│ foo │ +│ pneumonoultramicro… │ +│ bar qux │ +└───────────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Markup_Overflow.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Markup_Overflow.Output.verified.txt new file mode 100644 index 000000000..1fb1ad3f6 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Markup_Overflow.Output.verified.txt @@ -0,0 +1,7 @@ +┌────────────────────┬─────────────────┐ +│ Column1 │ Column2 │ +├────────────────────┼─────────────────┤ +│ foo │ Short text │ +│ pneumonoultramicr… │ │ +│ bar │ │ +└────────────────────┴─────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Crop.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Crop.Output.verified.txt new file mode 100644 index 000000000..d73678d37 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Crop.Output.verified.txt @@ -0,0 +1,7 @@ +┌─────────────────┬─────────────────┐ +│ Column1 │ Column2 │ +├─────────────────┼─────────────────┤ +│ foo │ Short text │ +│ pneumonoultrami │ │ +│ bar │ │ +└─────────────────┴─────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Ellipsis.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Ellipsis.Output.verified.txt new file mode 100644 index 000000000..69623fbbe --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Ellipsis.Output.verified.txt @@ -0,0 +1,7 @@ +┌─────────────────┬─────────────────┐ +│ Column1 │ Column2 │ +├─────────────────┼─────────────────┤ +│ foo │ Short text │ +│ pneumonoultram… │ │ +│ bar │ │ +└─────────────────┴─────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Fold.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Fold.Output.verified.txt new file mode 100644 index 000000000..a20cf4889 --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Fold.Output.verified.txt @@ -0,0 +1,9 @@ +┌─────────────────┬─────────────────┐ +│ Column1 │ Column2 │ +├─────────────────┼─────────────────┤ +│ foo │ Short text │ +│ pneumonoultrami │ │ +│ croscopicsilico │ │ +│ volcanoconiosis │ │ +│ bar │ │ +└─────────────────┴─────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Multiple_Rows.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Multiple_Rows.Output.verified.txt new file mode 100644 index 000000000..65711330e --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_Multiple_Rows.Output.verified.txt @@ -0,0 +1,11 @@ +┌─────────────────┬─────────────────┐ +│ Column1 │ Column2 │ +├─────────────────┼─────────────────┤ +│ foo │ First row │ +│ pneumonoultrami │ │ +│ bar │ Second row │ +│ supercalifragi… │ │ +│ qux │ Third row │ +│ antidisestablis │ │ +│ hmentarianism │ │ +└─────────────────┴─────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_With_NoWrap.Output.verified.txt b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_With_NoWrap.Output.verified.txt new file mode 100644 index 000000000..69623fbbe --- /dev/null +++ b/src/Tests/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Cell_Overflow_With_NoWrap.Output.verified.txt @@ -0,0 +1,7 @@ +┌─────────────────┬─────────────────┐ +│ Column1 │ Column2 │ +├─────────────────┼─────────────────┤ +│ foo │ Short text │ +│ pneumonoultram… │ │ +│ bar │ │ +└─────────────────┴─────────────────┘ diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/GridTests.cs b/src/Tests/Spectre.Console.Tests/Unit/Widgets/GridTests.cs index 4644790c8..3a25db3f7 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/GridTests.cs +++ b/src/Tests/Spectre.Console.Tests/Unit/Widgets/GridTests.cs @@ -192,4 +192,104 @@ public Task Should_Render_Explicit_Grid_Column_Padding_Correctly() // Then return Verifier.Verify(console.Output); } + + [Fact] + [Expectation("Render_Cell_Overflow_Crop")] + public Task Should_Respect_Cell_Content_Overflow_Crop() + { + // Given + var console = new TestConsole().Width(40); + var grid = new Grid(); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Crop), + new Text("Short text")); + + // When + console.Write(grid); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_Ellipsis")] + public Task Should_Respect_Cell_Content_Overflow_Ellipsis() + { + // Given + var console = new TestConsole().Width(40); + var grid = new Grid(); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Ellipsis), + new Text("Short text")); + + // When + console.Write(grid); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_Fold")] + public Task Should_Respect_Cell_Content_Overflow_Fold() + { + // Given + var console = new TestConsole().Width(40); + var grid = new Grid(); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Fold), + new Text("Short text")); + + // When + console.Write(grid); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Markup_Overflow")] + public Task Should_Respect_Markup_Content_Overflow_In_Cell() + { + // Given + var console = new TestConsole().Width(40); + var grid = new Grid(); + grid.AddColumn(new GridColumn { Width = 18 }); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddRow( + new Markup("[yellow]foo[/] [red]pneumonoultramicroscopicsilicovolcanoconiosis[/] [blue]bar[/]").Overflow(Overflow.Ellipsis), + new Markup("[green]Short text[/]")); + + // When + console.Write(grid); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_With_NoWrap")] + public Task Should_Respect_Cell_Content_Overflow_With_NoWrap_Column() + { + // Given + var console = new TestConsole().Width(40); + var grid = new Grid(); + grid.AddColumn(new GridColumn { Width = 15, NoWrap = true }); + grid.AddColumn(new GridColumn { Width = 15 }); + grid.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Ellipsis), + new Text("Short text")); + + // When + console.Write(grid); + + // Then + return Verifier.Verify(console.Output); + } } diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs b/src/Tests/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs index 3d042fae4..e698aecb2 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs +++ b/src/Tests/Spectre.Console.Tests/Unit/Widgets/PanelTests.cs @@ -366,4 +366,129 @@ public Task Should_Wrap_Table_With_CJK_Tables_In_Panel_Correctly() // Then return Verifier.Verify(console.Output); } + + [Fact] + [Expectation("Render_Text_Overflow_Crop")] + public Task Should_Respect_Text_Overflow_Crop_In_Panel() + { + // Given + var console = new TestConsole(); + var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux") + .Overflow(Overflow.Crop); + var panel = new Panel(text) + { + Width = 20, + }; + + // When + console.Write(panel); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Text_Overflow_Ellipsis")] + public Task Should_Respect_Text_Overflow_Ellipsis_In_Panel() + { + // Given + var console = new TestConsole(); + var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux") + .Overflow(Overflow.Ellipsis); + var panel = new Panel(text) + { + Width = 20, + }; + + // When + console.Write(panel); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Text_Overflow_Fold")] + public Task Should_Respect_Text_Overflow_Fold_In_Panel() + { + // Given + var console = new TestConsole(); + var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux") + .Overflow(Overflow.Fold); + var panel = new Panel(text) + { + Width = 20, + }; + + // When + console.Write(panel); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Markup_Overflow_Ellipsis")] + public Task Should_Respect_Markup_Overflow_Ellipsis_In_Panel() + { + // Given + var console = new TestConsole(); + var markup = new Markup("[yellow]foo[/] [red]pneumonoultramicroscopicsilicovolcanoconiosis[/] [blue]bar qux[/]") + .Overflow(Overflow.Ellipsis); + var panel = new Panel(markup) + { + Width = 20, + }; + + // When + console.Write(panel); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Text_Overflow_With_Padding")] + public Task Should_Respect_Text_Overflow_In_Panel_With_Padding() + { + // Given + var console = new TestConsole(); + var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux") + .Overflow(Overflow.Ellipsis); + var panel = new Panel(text) + { + Width = 25, + Padding = new Padding(2, 0, 2, 0), + }; + + // When + console.Write(panel); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Nested_Panel_With_Overflow")] + public Task Should_Respect_Text_Overflow_In_Nested_Panel() + { + // Given + var console = new TestConsole(); + var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux") + .Overflow(Overflow.Crop); + var innerPanel = new Panel(text) + { + Width = 15, + }; + var outerPanel = new Panel(innerPanel) + { + Width = 25, + }; + + // When + console.Write(outerPanel); + + // Then + return Verifier.Verify(console.Output); + } } diff --git a/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs b/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs index 18379bdcd..4c26b7aa0 100644 --- a/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs +++ b/src/Tests/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs @@ -631,4 +631,130 @@ public Task Should_Render_Empty_Column_Correctly() // Then return Verifier.Verify(console.Output); } + + [Fact] + [Expectation("Render_Cell_Overflow_Crop")] + public Task Should_Respect_Cell_Content_Overflow_Crop() + { + // Given + var console = new TestConsole(); + var table = new Table(); + table.AddColumn(new TableColumn("Column1").Width(15)); + table.AddColumn(new TableColumn("Column2").Width(15)); + table.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Crop), + new Text("Short text")); + + // When + console.Write(table); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_Ellipsis")] + public Task Should_Respect_Cell_Content_Overflow_Ellipsis() + { + // Given + var console = new TestConsole(); + var table = new Table(); + table.AddColumn(new TableColumn("Column1").Width(15)); + table.AddColumn(new TableColumn("Column2").Width(15)); + table.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Ellipsis), + new Text("Short text")); + + // When + console.Write(table); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_Fold")] + public Task Should_Respect_Cell_Content_Overflow_Fold() + { + // Given + var console = new TestConsole(); + var table = new Table(); + table.AddColumn(new TableColumn("Column1").Width(15)); + table.AddColumn(new TableColumn("Column2").Width(15)); + table.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Fold), + new Text("Short text")); + + // When + console.Write(table); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Markup_Overflow")] + public Task Should_Respect_Markup_Content_Overflow_In_Cell() + { + // Given + var console = new TestConsole(); + var table = new Table(); + table.AddColumn(new TableColumn("Column1").Width(18)); + table.AddColumn(new TableColumn("Column2").Width(15)); + table.AddRow( + new Markup("[yellow]foo[/] [red]pneumonoultramicroscopicsilicovolcanoconiosis[/] [blue]bar[/]").Overflow(Overflow.Ellipsis), + new Markup("[green]Short text[/]")); + + // When + console.Write(table); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_Multiple_Rows")] + public Task Should_Respect_Cell_Content_Overflow_In_Multiple_Rows() + { + // Given + var console = new TestConsole(); + var table = new Table(); + table.AddColumn(new TableColumn("Column1").Width(15)); + table.AddColumn(new TableColumn("Column2").Width(15)); + table.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis").Overflow(Overflow.Crop), + new Text("First row")); + table.AddRow( + new Text("bar supercalifragilisticexpialidocious").Overflow(Overflow.Ellipsis), + new Text("Second row")); + table.AddRow( + new Text("qux antidisestablishmentarianism").Overflow(Overflow.Fold), + new Text("Third row")); + + // When + console.Write(table); + + // Then + return Verifier.Verify(console.Output); + } + + [Fact] + [Expectation("Render_Cell_Overflow_With_NoWrap")] + public Task Should_Respect_Cell_Content_Overflow_With_NoWrap_Column() + { + // Given + var console = new TestConsole(); + var table = new Table(); + table.AddColumn(new TableColumn("Column1").Width(15).NoWrap()); + table.AddColumn(new TableColumn("Column2").Width(15)); + table.AddRow( + new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar").Overflow(Overflow.Ellipsis), + new Text("Short text")); + + // When + console.Write(table); + + // Then + return Verifier.Verify(console.Output); + } } From d61788d6c681745c8d1158ceeb4545ba37a99522 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Tue, 25 Nov 2025 21:47:14 +0100 Subject: [PATCH 3/3] Ensure OpenCli.Sources are not a dependency of the CLI package --- src/Spectre.Console.Cli/Spectre.Console.Cli.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Spectre.Console.Cli/Spectre.Console.Cli.csproj b/src/Spectre.Console.Cli/Spectre.Console.Cli.csproj index 3fcd0e083..bd18222d3 100644 --- a/src/Spectre.Console.Cli/Spectre.Console.Cli.csproj +++ b/src/Spectre.Console.Cli/Spectre.Console.Cli.csproj @@ -18,7 +18,7 @@ - + all runtime; build; native; contentfiles; analyzers