using System; using Shouldly; using Xunit; namespace Spectre.Console.Tests.Unit { public sealed class TableTests { public sealed class TheAddColumnMethod { [Fact] public void Should_Throw_If_Column_Is_Null() { // Given var table = new Table(); // When var result = Record.Exception(() => table.AddColumn((string)null)); // Then result.ShouldBeOfType() .ParamName.ShouldBe("column"); } [Fact] public void Should_Throw_If_Rows_Are_Not_Empty() { // Given var grid = new Table(); grid.AddColumn("Foo"); grid.AddRow("Hello World"); // When var result = Record.Exception(() => grid.AddColumn("Bar")); // Then result.ShouldBeOfType() .Message.ShouldBe("Cannot add new columns to table with existing rows."); } } public sealed class TheAddColumnsMethod { [Fact] public void Should_Throw_If_Columns_Are_Null() { // Given var table = new Table(); // When var result = Record.Exception(() => table.AddColumns((string[])null)); // Then result.ShouldBeOfType() .ParamName.ShouldBe("columns"); } } public sealed class TheAddRowMethod { [Fact] public void Should_Throw_If_String_Rows_Are_Null() { // Given var table = new Table(); // When var result = Record.Exception(() => table.AddRow((string[])null)); // Then result.ShouldBeOfType() .ParamName.ShouldBe("columns"); } [Fact] public void Should_Throw_If_Renderable_Rows_Are_Null() { // Given var table = new Table(); // When var result = Record.Exception(() => table.AddRow(null)); // Then result.ShouldBeOfType() .ParamName.ShouldBe("columns"); } [Fact] public void Should_Add_Empty_Items_If_User_Provides_Less_Row_Items_Than_Columns() { // Given var table = new Table(); table.AddColumn("Hello"); table.AddColumn("World"); // When table.AddRow("Foo"); // Then table.RowCount.ShouldBe(1); } [Fact] public void Should_Throw_If_Row_Columns_Are_Greater_Than_Number_Of_Columns() { // Given var table = new Table(); table.AddColumn("Hello"); // When var result = Record.Exception(() => table.AddRow("Foo", "Bar")); // Then result.ShouldBeOfType(); result.Message.ShouldBe("The number of row columns are greater than the number of table columns."); } } public sealed class TheAddEmptyRowMethod { [Fact] public void Should_Render_Table_Correctly() { // Given var console = new PlainConsole(width: 80); var table = new Table(); table.AddColumns("Foo", "Bar", "Baz"); table.AddRow("Qux", "Corgi", "Waldo"); table.AddEmptyRow(); table.AddRow("Grault", "Garply", "Fred"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(7); console.Lines[0].ShouldBe("┌────────┬────────┬───────┐"); console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │"); console.Lines[2].ShouldBe("├────────┼────────┼───────┤"); console.Lines[3].ShouldBe("│ Qux │ Corgi │ Waldo │"); console.Lines[4].ShouldBe("│ │ │ │"); console.Lines[5].ShouldBe("│ Grault │ Garply │ Fred │"); console.Lines[6].ShouldBe("└────────┴────────┴───────┘"); } } [Fact] public void Should_Render_Table_Correctly() { // Given var console = new PlainConsole(width: 80); var table = new Table(); table.AddColumns("Foo", "Bar", "Baz"); table.AddRow("Qux", "Corgi", "Waldo"); table.AddRow("Grault", "Garply", "Fred"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(6); console.Lines[0].ShouldBe("┌────────┬────────┬───────┐"); console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │"); console.Lines[2].ShouldBe("├────────┼────────┼───────┤"); console.Lines[3].ShouldBe("│ Qux │ Corgi │ Waldo │"); console.Lines[4].ShouldBe("│ Grault │ Garply │ Fred │"); console.Lines[5].ShouldBe("└────────┴────────┴───────┘"); } [Fact] public void Should_Left_Align_Table_Correctly() { // Given var console = new PlainConsole(width: 80); var table = new Table(); table.Alignment = Justify.Left; table.AddColumns("Foo", "Bar", "Baz"); table.AddRow("Qux", "Corgi", "Waldo"); table.AddRow("Grault", "Garply", "Fred"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(6); console.Lines[0].ShouldBe("┌────────┬────────┬───────┐"); console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │"); console.Lines[2].ShouldBe("├────────┼────────┼───────┤"); console.Lines[3].ShouldBe("│ Qux │ Corgi │ Waldo │"); console.Lines[4].ShouldBe("│ Grault │ Garply │ Fred │"); console.Lines[5].ShouldBe("└────────┴────────┴───────┘"); } [Fact] public void Should_Center_Table_Correctly() { // Given var console = new PlainConsole(width: 80); var table = new Table(); table.Alignment = Justify.Center; table.AddColumns("Foo", "Bar", "Baz"); table.AddRow("Qux", "Corgi", "Waldo"); table.AddRow("Grault", "Garply", "Fred"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(6); console.Lines[0].ShouldBe(" ┌────────┬────────┬───────┐ "); console.Lines[1].ShouldBe(" │ Foo │ Bar │ Baz │ "); console.Lines[2].ShouldBe(" ├────────┼────────┼───────┤ "); console.Lines[3].ShouldBe(" │ Qux │ Corgi │ Waldo │ "); console.Lines[4].ShouldBe(" │ Grault │ Garply │ Fred │ "); console.Lines[5].ShouldBe(" └────────┴────────┴───────┘ "); } [Fact] public void Should_Right_Align_Table_Correctly() { // Given var console = new PlainConsole(width: 80); var table = new Table(); table.Alignment = Justify.Right; table.AddColumns("Foo", "Bar", "Baz"); table.AddRow("Qux", "Corgi", "Waldo"); table.AddRow("Grault", "Garply", "Fred"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(6); console.Lines[0].ShouldBe(" ┌────────┬────────┬───────┐"); console.Lines[1].ShouldBe(" │ Foo │ Bar │ Baz │"); console.Lines[2].ShouldBe(" ├────────┼────────┼───────┤"); console.Lines[3].ShouldBe(" │ Qux │ Corgi │ Waldo │"); console.Lines[4].ShouldBe(" │ Grault │ Garply │ Fred │"); console.Lines[5].ShouldBe(" └────────┴────────┴───────┘"); } [Fact] public void Should_Render_Table_Nested_In_Panels_Correctly() { // A simple table var console = new PlainConsole(width: 80); var table = new Table() { Border = TableBorder.Rounded }; table.AddColumn("Foo"); table.AddColumn("Bar"); table.AddColumn(new TableColumn("Baz") { Alignment = Justify.Right }); table.AddRow("Qux\nQuuuuuux", "[blue]Corgi[/]", "Waldo"); table.AddRow("Grault", "Garply", "Fred"); // Render a table in some panels. console.Render(new Panel(new Panel(table) { Border = BoxBorder.Ascii, })); // Then console.Lines.Count.ShouldBe(11); console.Lines[00].ShouldBe("┌───────────────────────────────────┐"); console.Lines[01].ShouldBe("│ +-------------------------------+ │"); console.Lines[02].ShouldBe("│ | ╭──────────┬────────┬───────╮ | │"); console.Lines[03].ShouldBe("│ | │ Foo │ Bar │ Baz │ | │"); console.Lines[04].ShouldBe("│ | ├──────────┼────────┼───────┤ | │"); console.Lines[05].ShouldBe("│ | │ Qux │ Corgi │ Waldo │ | │"); console.Lines[06].ShouldBe("│ | │ Quuuuuux │ │ │ | │"); console.Lines[07].ShouldBe("│ | │ Grault │ Garply │ Fred │ | │"); console.Lines[08].ShouldBe("│ | ╰──────────┴────────┴───────╯ | │"); console.Lines[09].ShouldBe("│ +-------------------------------+ │"); console.Lines[10].ShouldBe("└───────────────────────────────────┘"); } [Fact] public void Should_Render_Table_With_Column_Justification_Correctly() { // Given var console = new PlainConsole(width: 80); var table = new Table(); table.AddColumn(new TableColumn("Foo") { Alignment = Justify.Left }); table.AddColumn(new TableColumn("Bar") { Alignment = Justify.Right }); table.AddColumn(new TableColumn("Baz") { Alignment = Justify.Center }); table.AddRow("Qux", "Corgi", "Waldo"); table.AddRow("Grault", "Garply", "Lorem ipsum dolor sit amet"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(6); console.Lines[0].ShouldBe("┌────────┬────────┬────────────────────────────┐"); console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │"); console.Lines[2].ShouldBe("├────────┼────────┼────────────────────────────┤"); console.Lines[3].ShouldBe("│ Qux │ Corgi │ Waldo │"); console.Lines[4].ShouldBe("│ Grault │ Garply │ Lorem ipsum dolor sit amet │"); console.Lines[5].ShouldBe("└────────┴────────┴────────────────────────────┘"); } [Fact] public void Should_Expand_Table_To_Available_Space_If_Specified() { // Given var console = new PlainConsole(width: 80); var table = new Table() { Expand = true }; table.AddColumns("Foo", "Bar", "Baz"); table.AddRow("Qux", "Corgi", "Waldo"); table.AddRow("Grault", "Garply", "Fred"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(6); console.Lines[0].Length.ShouldBe(80); console.Lines[0].ShouldBe("┌───────────────────────────┬───────────────────────────┬──────────────────────┐"); console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │"); console.Lines[2].ShouldBe("├───────────────────────────┼───────────────────────────┼──────────────────────┤"); console.Lines[3].ShouldBe("│ Qux │ Corgi │ Waldo │"); console.Lines[4].ShouldBe("│ Grault │ Garply │ Fred │"); console.Lines[5].ShouldBe("└───────────────────────────┴───────────────────────────┴──────────────────────┘"); } [Fact] public void Should_Render_Table_With_No_Border_Correctly() { // Given var console = new PlainConsole(width: 80); var table = new Table { Border = TableBorder.None }; table.AddColumns("Foo", "Bar", "Baz"); table.AddRow("Qux", "Corgi", "Waldo"); table.AddRow("Grault", "Garply", "Fred"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(3); console.Lines[0].ShouldBe("Foo Bar Baz "); console.Lines[1].ShouldBe("Qux Corgi Waldo"); console.Lines[2].ShouldBe("Grault Garply Fred "); } [Fact] public void Should_Render_Table_With_Multiple_Rows_In_Cell_Correctly() { // Given var console = new PlainConsole(width: 80); var table = new Table(); table.AddColumns("Foo", "Bar", "Baz"); table.AddRow("Qux\nQuuux", "Corgi", "Waldo"); table.AddRow("Grault", "Garply", "Fred"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(7); console.Lines[0].ShouldBe("┌────────┬────────┬───────┐"); console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │"); console.Lines[2].ShouldBe("├────────┼────────┼───────┤"); console.Lines[3].ShouldBe("│ Qux │ Corgi │ Waldo │"); console.Lines[4].ShouldBe("│ Quuux │ │ │"); console.Lines[5].ShouldBe("│ Grault │ Garply │ Fred │"); console.Lines[6].ShouldBe("└────────┴────────┴───────┘"); } [Fact] public void Should_Render_Table_With_Cell_Padding_Correctly() { // Given var console = new PlainConsole(width: 80); var table = new Table(); table.AddColumns("Foo", "Bar"); table.AddColumn(new TableColumn("Baz") { Padding = new Padding(3, 0, 2, 0) }); table.AddRow("Qux\nQuuux", "Corgi", "Waldo"); table.AddRow("Grault", "Garply", "Fred"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(7); console.Lines[0].ShouldBe("┌────────┬────────┬──────────┐"); console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │"); console.Lines[2].ShouldBe("├────────┼────────┼──────────┤"); console.Lines[3].ShouldBe("│ Qux │ Corgi │ Waldo │"); console.Lines[4].ShouldBe("│ Quuux │ │ │"); console.Lines[5].ShouldBe("│ Grault │ Garply │ Fred │"); console.Lines[6].ShouldBe("└────────┴────────┴──────────┘"); } [Fact] public void Should_Render_Table_Without_Footer_If_No_Rows_Are_Added() { // Given var console = new PlainConsole(width: 80); var table = new Table(); table.AddColumns("Foo", "Bar"); table.AddColumn(new TableColumn("Baz") { Padding = new Padding(3, 0, 2, 0) }); // When console.Render(table); // Then console.Lines.Count.ShouldBe(3); console.Lines[0].ShouldBe("┌─────┬─────┬────────┐"); console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │"); console.Lines[2].ShouldBe("└─────┴─────┴────────┘"); } [Fact] public void Should_Not_Draw_Tables_That_Are_Impossible_To_Draw() { // Given var console = new PlainConsole(width: 25); var first = new Table().SetBorder(TableBorder.Rounded).SetBorderColor(Color.Red); first.AddColumn(new TableColumn("[u]PS1[/]").Centered()); first.AddColumn(new TableColumn("[u]PS2[/]")); first.AddColumn(new TableColumn("[u]PS3[/]")); first.AddRow("Hello", "[red]World[/]", string.Empty); first.AddRow("[blue]Bonjour[/]", "[white]le[/]", "[red]monde![/]"); first.AddRow("[blue]Hej[/]", "[yellow]Världen[/]", string.Empty); var second = new Table().SetBorder(TableBorder.Square).SetBorderColor(Color.Green); second.AddColumn(new TableColumn("[u]Foo[/]")); second.AddColumn(new TableColumn("[u]Bar[/]")); second.AddColumn(new TableColumn("[u]Baz[/]")); second.AddRow("Hello", "[red]World[/]", string.Empty); second.AddRow(first, new Text("Whaaat"), new Text("Lolz")); second.AddRow("[blue]Hej[/]", "[yellow]Världen[/]", string.Empty); var table = new Table().SetBorder(TableBorder.Rounded); table.AddColumn(new TableColumn(new Panel("[u]ABC[/]").SetBorderColor(Color.Red))); table.AddColumn(new TableColumn(new Panel("[u]DEF[/]").SetBorderColor(Color.Green))); table.AddColumn(new TableColumn(new Panel("[u]GHI[/]").SetBorderColor(Color.Blue))); table.AddRow(new Text("Hello").Centered(), new Markup("[red]World[/]"), Text.Empty); table.AddRow(second, new Text("Whaat"), new Text("Lol").RightAligned()); table.AddRow(new Markup("[blue]Hej[/]"), new Markup("[yellow]Världen[/]"), Text.Empty); // When console.Render(table); // Then console.Lines.Count.ShouldBe(12); console.Lines[00].ShouldBe("╭───────┬───────┬───────╮"); console.Lines[01].ShouldBe("│ ┌───┐ │ ┌───┐ │ ┌───┐ │"); console.Lines[02].ShouldBe("│ │ A │ │ │ D │ │ │ G │ │"); console.Lines[03].ShouldBe("│ │ B │ │ │ E │ │ │ H │ │"); console.Lines[04].ShouldBe("│ │ C │ │ │ F │ │ │ I │ │"); console.Lines[05].ShouldBe("│ └───┘ │ └───┘ │ └───┘ │"); console.Lines[06].ShouldBe("├───────┼───────┼───────┤"); console.Lines[07].ShouldBe("│ Hello │ World │ │"); console.Lines[08].ShouldBe("│ … │ Whaat │ Lol │"); console.Lines[09].ShouldBe("│ Hej │ Värld │ │"); console.Lines[10].ShouldBe("│ │ en │ │"); console.Lines[11].ShouldBe("╰───────┴───────┴───────╯"); } [Fact] public void Should_Render_Table_With_Title_And_Footnote_Correctly() { // Given var console = new PlainConsole(width: 80); var table = new Table { Border = TableBorder.Rounded }; table.Heading = new TableTitle("Hello World"); table.Footnote = new TableTitle("Goodbye World"); table.AddColumns("Foo", "Bar", "Baz"); table.AddRow("Qux", "Corgi", "Waldo"); table.AddRow("Grault", "Garply", "Fred"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(8); console.Lines[0].ShouldBe(" Hello World "); console.Lines[1].ShouldBe("╭────────┬────────┬───────╮"); console.Lines[2].ShouldBe("│ Foo │ Bar │ Baz │"); console.Lines[3].ShouldBe("├────────┼────────┼───────┤"); console.Lines[4].ShouldBe("│ Qux │ Corgi │ Waldo │"); console.Lines[5].ShouldBe("│ Grault │ Garply │ Fred │"); console.Lines[6].ShouldBe("╰────────┴────────┴───────╯"); console.Lines[7].ShouldBe(" Goodbye World "); } [Fact] public void Should_Left_Align_Table_With_Title_And_Footnote_Correctly() { // Given var console = new PlainConsole(width: 80); var table = new Table { Border = TableBorder.Rounded }; table.LeftAligned(); table.Heading = new TableTitle("Hello World"); table.Footnote = new TableTitle("Goodbye World"); table.AddColumns("Foo", "Bar", "Baz"); table.AddRow("Qux", "Corgi", "Waldo"); table.AddRow("Grault", "Garply", "Fred"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(8); console.Lines[0].ShouldBe(" Hello World "); console.Lines[1].ShouldBe("╭────────┬────────┬───────╮"); console.Lines[2].ShouldBe("│ Foo │ Bar │ Baz │"); console.Lines[3].ShouldBe("├────────┼────────┼───────┤"); console.Lines[4].ShouldBe("│ Qux │ Corgi │ Waldo │"); console.Lines[5].ShouldBe("│ Grault │ Garply │ Fred │"); console.Lines[6].ShouldBe("╰────────┴────────┴───────╯"); console.Lines[7].ShouldBe(" Goodbye World "); } [Fact] public void Should_Center_Table_With_Title_And_Footnote_Correctly() { // Given var console = new PlainConsole(width: 80); var table = new Table { Border = TableBorder.Rounded }; table.Centered(); table.Heading = new TableTitle("Hello World"); table.Footnote = new TableTitle("Goodbye World"); table.AddColumns("Foo", "Bar", "Baz"); table.AddRow("Qux", "Corgi", "Waldo"); table.AddRow("Grault", "Garply", "Fred"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(8); console.Lines[0].ShouldBe(" Hello World "); console.Lines[1].ShouldBe(" ╭────────┬────────┬───────╮ "); console.Lines[2].ShouldBe(" │ Foo │ Bar │ Baz │ "); console.Lines[3].ShouldBe(" ├────────┼────────┼───────┤ "); console.Lines[4].ShouldBe(" │ Qux │ Corgi │ Waldo │ "); console.Lines[5].ShouldBe(" │ Grault │ Garply │ Fred │ "); console.Lines[6].ShouldBe(" ╰────────┴────────┴───────╯ "); console.Lines[7].ShouldBe(" Goodbye World "); } [Fact] public void Should_Right_Align_Table_With_Title_And_Footnote_Correctly() { // Given var console = new PlainConsole(width: 80); var table = new Table { Border = TableBorder.Rounded }; table.RightAligned(); table.Heading = new TableTitle("Hello World"); table.Footnote = new TableTitle("Goodbye World"); table.AddColumns("Foo", "Bar", "Baz"); table.AddRow("Qux", "Corgi", "Waldo"); table.AddRow("Grault", "Garply", "Fred"); // When console.Render(table); // Then console.Lines.Count.ShouldBe(8); console.Lines[0].ShouldBe(" Hello World "); console.Lines[1].ShouldBe(" ╭────────┬────────┬───────╮"); console.Lines[2].ShouldBe(" │ Foo │ Bar │ Baz │"); console.Lines[3].ShouldBe(" ├────────┼────────┼───────┤"); console.Lines[4].ShouldBe(" │ Qux │ Corgi │ Waldo │"); console.Lines[5].ShouldBe(" │ Grault │ Garply │ Fred │"); console.Lines[6].ShouldBe(" ╰────────┴────────┴───────╯"); console.Lines[7].ShouldBe(" Goodbye World "); } } }