mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-06-19 13:28:16 +08:00
Add global usings (#668)
* Use global usings * Fix namespace declarations for test projects
This commit is contained in:
@ -1,79 +1,71 @@
|
||||
using System.Threading.Tasks;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("AlternateScreen")]
|
||||
public sealed class AlternateScreenTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("AlternateScreen")]
|
||||
public sealed class AlternateScreenTests
|
||||
[Fact]
|
||||
public void Should_Throw_If_Alternative_Buffer_Is_Not_Supported_By_Terminal()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Throw_If_Alternative_Buffer_Is_Not_Supported_By_Terminal()
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Profile.Capabilities.AlternateBuffer = false;
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() =>
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Profile.Capabilities.AlternateBuffer = false;
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() =>
|
||||
{
|
||||
console.WriteLine("Foo");
|
||||
console.AlternateScreen(() =>
|
||||
{
|
||||
console.WriteLine("Bar");
|
||||
});
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Message.ShouldBe("Alternate buffers are not supported by your terminal.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Ansi_Is_Not_Supported_By_Terminal()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Profile.Capabilities.Ansi = false;
|
||||
console.Profile.Capabilities.AlternateBuffer = true;
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() =>
|
||||
{
|
||||
console.WriteLine("Foo");
|
||||
console.AlternateScreen(() =>
|
||||
{
|
||||
console.WriteLine("Bar");
|
||||
});
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Message.ShouldBe("Alternate buffers are not supported since your terminal does not support ANSI.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Show")]
|
||||
public async Task Should_Write_To_Alternate_Screen()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.EmitAnsiSequences = true;
|
||||
console.Profile.Capabilities.AlternateBuffer = true;
|
||||
|
||||
// When
|
||||
console.WriteLine("Foo");
|
||||
console.AlternateScreen(() =>
|
||||
{
|
||||
console.WriteLine("Bar");
|
||||
});
|
||||
});
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Message.ShouldBe("Alternate buffers are not supported by your terminal.");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Ansi_Is_Not_Supported_By_Terminal()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Profile.Capabilities.Ansi = false;
|
||||
console.Profile.Capabilities.AlternateBuffer = true;
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() =>
|
||||
{
|
||||
console.WriteLine("Foo");
|
||||
console.AlternateScreen(() =>
|
||||
{
|
||||
console.WriteLine("Bar");
|
||||
});
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Message.ShouldBe("Alternate buffers are not supported since your terminal does not support ANSI.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Show")]
|
||||
public async Task Should_Write_To_Alternate_Screen()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.EmitAnsiSequences = true;
|
||||
console.Profile.Capabilities.AlternateBuffer = true;
|
||||
|
||||
// When
|
||||
console.WriteLine("Foo");
|
||||
console.AlternateScreen(() =>
|
||||
{
|
||||
console.WriteLine("Bar");
|
||||
});
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +1,55 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Advanced;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public sealed partial class AnsiConsoleTests
|
||||
{
|
||||
public sealed partial class AnsiConsoleTests
|
||||
public sealed class Advanced
|
||||
{
|
||||
public sealed class Advanced
|
||||
[Fact]
|
||||
public void Should_Write_Ansi_Codes_To_Console_If_Supported()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Write_Ansi_Codes_To_Console_If_Supported()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.SupportsAnsi(true)
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.SupportsAnsi(true)
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.WriteAnsi("[101mHello[0m");
|
||||
// When
|
||||
console.WriteAnsi("[101mHello[0m");
|
||||
|
||||
// Then
|
||||
console.Output.NormalizeLineEndings()
|
||||
.ShouldBe("[101mHello[0m");
|
||||
}
|
||||
// Then
|
||||
console.Output.NormalizeLineEndings()
|
||||
.ShouldBe("[101mHello[0m");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Write_Ansi_Codes_To_Console_If_Not_Supported()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.SupportsAnsi(false)
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
[Fact]
|
||||
public void Should_Not_Write_Ansi_Codes_To_Console_If_Not_Supported()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.SupportsAnsi(false)
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.WriteAnsi("[101mHello[0m");
|
||||
// When
|
||||
console.WriteAnsi("[101mHello[0m");
|
||||
|
||||
// Then
|
||||
console.Output.NormalizeLineEndings()
|
||||
.ShouldBeEmpty();
|
||||
}
|
||||
// Then
|
||||
console.Output.NormalizeLineEndings()
|
||||
.ShouldBeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Ansi_For_Renderable()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Colors(ColorSystem.TrueColor);
|
||||
var markup = new Console.Markup("[yellow]Hello [blue]World[/]![/]");
|
||||
[Fact]
|
||||
public void Should_Return_Ansi_For_Renderable()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Colors(ColorSystem.TrueColor);
|
||||
var markup = new Console.Markup("[yellow]Hello [blue]World[/]![/]");
|
||||
|
||||
// When
|
||||
var result = console.ToAnsi(markup);
|
||||
// When
|
||||
var result = console.ToAnsi(markup);
|
||||
|
||||
// Then
|
||||
result.ShouldBe("[38;5;11mHello [0m[38;5;12mWorld[0m[38;5;11m![0m");
|
||||
}
|
||||
// Then
|
||||
result.ShouldBe("[38;5;11mHello [0m[38;5;12mWorld[0m[38;5;11m![0m");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,248 +1,242 @@
|
||||
using System.IO;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public partial class AnsiConsoleTests
|
||||
{
|
||||
public partial class AnsiConsoleTests
|
||||
[Theory]
|
||||
[InlineData(ColorSystemSupport.NoColors, ColorSystem.NoColors)]
|
||||
[InlineData(ColorSystemSupport.Legacy, ColorSystem.Legacy)]
|
||||
[InlineData(ColorSystemSupport.Standard, ColorSystem.Standard)]
|
||||
[InlineData(ColorSystemSupport.EightBit, ColorSystem.EightBit)]
|
||||
[InlineData(ColorSystemSupport.TrueColor, ColorSystem.TrueColor)]
|
||||
public void Should_Create_Console_With_Requested_ColorSystem(ColorSystemSupport requested, ColorSystem expected)
|
||||
{
|
||||
// Given, When
|
||||
var console = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
ColorSystem = requested,
|
||||
Out = new AnsiConsoleOutput(new StringWriter()),
|
||||
});
|
||||
|
||||
// Then
|
||||
console.Profile.Capabilities.ColorSystem.ShouldBe(expected);
|
||||
}
|
||||
|
||||
public sealed class TrueColor
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(ColorSystemSupport.NoColors, ColorSystem.NoColors)]
|
||||
[InlineData(ColorSystemSupport.Legacy, ColorSystem.Legacy)]
|
||||
[InlineData(ColorSystemSupport.Standard, ColorSystem.Standard)]
|
||||
[InlineData(ColorSystemSupport.EightBit, ColorSystem.EightBit)]
|
||||
[InlineData(ColorSystemSupport.TrueColor, ColorSystem.TrueColor)]
|
||||
public void Should_Create_Console_With_Requested_ColorSystem(ColorSystemSupport requested, ColorSystem expected)
|
||||
[InlineData(true, "\u001b[38;2;128;0;128mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[48;2;128;0;128mHello\u001b[0m")]
|
||||
public void Should_Return_Correct_Code(bool foreground, string expected)
|
||||
{
|
||||
// Given, When
|
||||
var console = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
ColorSystem = requested,
|
||||
Out = new AnsiConsoleOutput(new StringWriter()),
|
||||
});
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.TrueColor)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(128, 0, 128), foreground));
|
||||
|
||||
// Then
|
||||
console.Profile.Capabilities.ColorSystem.ShouldBe(expected);
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
public sealed class TrueColor
|
||||
[Theory]
|
||||
[InlineData(true, "\u001b[38;5;5mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[48;5;5mHello\u001b[0m")]
|
||||
public void Should_Return_Eight_Bit_Ansi_Code_For_Known_Colors(bool foreground, string expected)
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(true, "\u001b[38;2;128;0;128mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[48;2;128;0;128mHello\u001b[0m")]
|
||||
public void Should_Return_Correct_Code(bool foreground, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.TrueColor)
|
||||
.EmitAnsiSequences();
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.TrueColor)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(128, 0, 128), foreground));
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(Color.Purple, foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, "\u001b[38;5;5mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[48;5;5mHello\u001b[0m")]
|
||||
public void Should_Return_Eight_Bit_Ansi_Code_For_Known_Colors(bool foreground, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.TrueColor)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(Color.Purple, foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EightBit
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(true, "\u001b[38;5;3mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[48;5;3mHello\u001b[0m")]
|
||||
public void Should_Return_Correct_Code_For_Known_Color(bool foreground, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.EightBit)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(Color.Olive, foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, "\u001b[38;5;3mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[48;5;3mHello\u001b[0m")]
|
||||
public void Should_Map_TrueColor_To_Nearest_Eight_Bit_Color_If_Possible(bool foreground, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.EightBit)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(128, 128, 0), foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, "\u001b[38;5;3mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[48;5;3mHello\u001b[0m")]
|
||||
public void Should_Estimate_TrueColor_To_Nearest_Eight_Bit_Color(bool foreground, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.EightBit)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(126, 127, 0), foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Standard
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(true, "\u001b[33mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[43mHello\u001b[0m")]
|
||||
public void Should_Return_Correct_Code_For_Known_Color(bool foreground, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(Color.Olive, foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, 128, 128, 128, "\u001b[90mHello\u001b[0m")]
|
||||
[InlineData(false, 128, 128, 128, "\u001b[100mHello\u001b[0m")]
|
||||
[InlineData(true, 0, 128, 0, "\u001b[32mHello\u001b[0m")]
|
||||
[InlineData(false, 0, 128, 0, "\u001b[42mHello\u001b[0m")]
|
||||
public void Should_Map_TrueColor_To_Nearest_Four_Bit_Color_If_Possible(
|
||||
bool foreground,
|
||||
byte r, byte g, byte b,
|
||||
string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(r, g, b), foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, 112, 120, 128, "\u001b[90mHello\u001b[0m")]
|
||||
[InlineData(false, 112, 120, 128, "\u001b[100mHello\u001b[0m")]
|
||||
[InlineData(true, 0, 120, 12, "\u001b[32mHello\u001b[0m")]
|
||||
[InlineData(false, 0, 120, 12, "\u001b[42mHello\u001b[0m")]
|
||||
public void Should_Estimate_TrueColor_To_Nearest_Four_Bit_Color(
|
||||
bool foreground,
|
||||
byte r, byte g, byte b,
|
||||
string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(r, g, b), foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Legacy
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(true, "\u001b[33mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[43mHello\u001b[0m")]
|
||||
public void Should_Return_Correct_Code_For_Known_Color(bool foreground, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Legacy)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(Color.Olive, foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, 128, 128, 128, "\u001b[37mHello\u001b[0m")]
|
||||
[InlineData(false, 128, 128, 128, "\u001b[47mHello\u001b[0m")]
|
||||
[InlineData(true, 0, 128, 0, "\u001b[32mHello\u001b[0m")]
|
||||
[InlineData(false, 0, 128, 0, "\u001b[42mHello\u001b[0m")]
|
||||
public void Should_Map_TrueColor_To_Nearest_Three_Bit_Color_If_Possible(
|
||||
bool foreground,
|
||||
byte r, byte g, byte b,
|
||||
string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Legacy)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(r, g, b), foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, 112, 120, 128, "\u001b[36mHello\u001b[0m")]
|
||||
[InlineData(false, 112, 120, 128, "\u001b[46mHello\u001b[0m")]
|
||||
[InlineData(true, 0, 120, 12, "\u001b[32mHello\u001b[0m")]
|
||||
[InlineData(false, 0, 120, 12, "\u001b[42mHello\u001b[0m")]
|
||||
public void Should_Estimate_TrueColor_To_Nearest_Three_Bit_Color(
|
||||
bool foreground,
|
||||
byte r, byte g, byte b,
|
||||
string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Legacy)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(r, g, b), foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EightBit
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(true, "\u001b[38;5;3mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[48;5;3mHello\u001b[0m")]
|
||||
public void Should_Return_Correct_Code_For_Known_Color(bool foreground, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.EightBit)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(Color.Olive, foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, "\u001b[38;5;3mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[48;5;3mHello\u001b[0m")]
|
||||
public void Should_Map_TrueColor_To_Nearest_Eight_Bit_Color_If_Possible(bool foreground, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.EightBit)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(128, 128, 0), foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, "\u001b[38;5;3mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[48;5;3mHello\u001b[0m")]
|
||||
public void Should_Estimate_TrueColor_To_Nearest_Eight_Bit_Color(bool foreground, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.EightBit)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(126, 127, 0), foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Standard
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(true, "\u001b[33mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[43mHello\u001b[0m")]
|
||||
public void Should_Return_Correct_Code_For_Known_Color(bool foreground, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(Color.Olive, foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, 128, 128, 128, "\u001b[90mHello\u001b[0m")]
|
||||
[InlineData(false, 128, 128, 128, "\u001b[100mHello\u001b[0m")]
|
||||
[InlineData(true, 0, 128, 0, "\u001b[32mHello\u001b[0m")]
|
||||
[InlineData(false, 0, 128, 0, "\u001b[42mHello\u001b[0m")]
|
||||
public void Should_Map_TrueColor_To_Nearest_Four_Bit_Color_If_Possible(
|
||||
bool foreground,
|
||||
byte r, byte g, byte b,
|
||||
string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(r, g, b), foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, 112, 120, 128, "\u001b[90mHello\u001b[0m")]
|
||||
[InlineData(false, 112, 120, 128, "\u001b[100mHello\u001b[0m")]
|
||||
[InlineData(true, 0, 120, 12, "\u001b[32mHello\u001b[0m")]
|
||||
[InlineData(false, 0, 120, 12, "\u001b[42mHello\u001b[0m")]
|
||||
public void Should_Estimate_TrueColor_To_Nearest_Four_Bit_Color(
|
||||
bool foreground,
|
||||
byte r, byte g, byte b,
|
||||
string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(r, g, b), foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Legacy
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(true, "\u001b[33mHello\u001b[0m")]
|
||||
[InlineData(false, "\u001b[43mHello\u001b[0m")]
|
||||
public void Should_Return_Correct_Code_For_Known_Color(bool foreground, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Legacy)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(Color.Olive, foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, 128, 128, 128, "\u001b[37mHello\u001b[0m")]
|
||||
[InlineData(false, 128, 128, 128, "\u001b[47mHello\u001b[0m")]
|
||||
[InlineData(true, 0, 128, 0, "\u001b[32mHello\u001b[0m")]
|
||||
[InlineData(false, 0, 128, 0, "\u001b[42mHello\u001b[0m")]
|
||||
public void Should_Map_TrueColor_To_Nearest_Three_Bit_Color_If_Possible(
|
||||
bool foreground,
|
||||
byte r, byte g, byte b,
|
||||
string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Legacy)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(r, g, b), foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, 112, 120, 128, "\u001b[36mHello\u001b[0m")]
|
||||
[InlineData(false, 112, 120, 128, "\u001b[46mHello\u001b[0m")]
|
||||
[InlineData(true, 0, 120, 12, "\u001b[32mHello\u001b[0m")]
|
||||
[InlineData(false, 0, 120, 12, "\u001b[42mHello\u001b[0m")]
|
||||
public void Should_Estimate_TrueColor_To_Nearest_Three_Bit_Color(
|
||||
bool foreground,
|
||||
byte r, byte g, byte b,
|
||||
string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Legacy)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello", new Style().SetColor(new Color(r, g, b), foreground));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,52 +1,47 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public partial class AnsiConsoleTests
|
||||
{
|
||||
public partial class AnsiConsoleTests
|
||||
public sealed class Cursor
|
||||
{
|
||||
public sealed class Cursor
|
||||
public sealed class TheMoveMethod
|
||||
{
|
||||
public sealed class TheMoveMethod
|
||||
[Theory]
|
||||
[InlineData(CursorDirection.Up, "Hello[2AWorld")]
|
||||
[InlineData(CursorDirection.Down, "Hello[2BWorld")]
|
||||
[InlineData(CursorDirection.Right, "Hello[2CWorld")]
|
||||
[InlineData(CursorDirection.Left, "Hello[2DWorld")]
|
||||
public void Should_Return_Correct_Ansi_Code(CursorDirection direction, string expected)
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(CursorDirection.Up, "Hello[2AWorld")]
|
||||
[InlineData(CursorDirection.Down, "Hello[2BWorld")]
|
||||
[InlineData(CursorDirection.Right, "Hello[2CWorld")]
|
||||
[InlineData(CursorDirection.Left, "Hello[2DWorld")]
|
||||
public void Should_Return_Correct_Ansi_Code(CursorDirection direction, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().EmitAnsiSequences();
|
||||
// Given
|
||||
var console = new TestConsole().EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello");
|
||||
console.Cursor.Move(direction, 2);
|
||||
console.Write("World");
|
||||
// When
|
||||
console.Write("Hello");
|
||||
console.Cursor.Move(direction, 2);
|
||||
console.Write("World");
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheSetPositionMethod
|
||||
public sealed class TheSetPositionMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Ansi_Code()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Ansi_Code()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().EmitAnsiSequences();
|
||||
// Given
|
||||
var console = new TestConsole().EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello");
|
||||
console.Cursor.SetPosition(5, 3);
|
||||
console.Write("World");
|
||||
// When
|
||||
console.Write("Hello");
|
||||
console.Cursor.SetPosition(5, 3);
|
||||
console.Write("World");
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello[3;5HWorld");
|
||||
}
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello[3;5HWorld");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,120 +1,114 @@
|
||||
using System;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public partial class AnsiConsoleTests
|
||||
{
|
||||
public partial class AnsiConsoleTests
|
||||
public sealed class Markup
|
||||
{
|
||||
public sealed class Markup
|
||||
[Theory]
|
||||
[InlineData("[yellow]Hello[/]", "[93mHello[0m")]
|
||||
[InlineData("[yellow]Hello [italic]World[/]![/]", "[93mHello [0m[3;93mWorld[0m[93m![0m")]
|
||||
public void Should_Output_Expected_Ansi_For_Markup(string markup, string expected)
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("[yellow]Hello[/]", "[93mHello[0m")]
|
||||
[InlineData("[yellow]Hello [italic]World[/]![/]", "[93mHello [0m[3;93mWorld[0m[93m![0m")]
|
||||
public void Should_Output_Expected_Ansi_For_Markup(string markup, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Markup(markup);
|
||||
// When
|
||||
console.Markup(markup);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Output_Expected_Ansi_For_Link_With_Url_And_Text()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.EmitAnsiSequences();
|
||||
[Fact]
|
||||
public void Should_Output_Expected_Ansi_For_Link_With_Url_And_Text()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Markup("[link=https://patriksvensson.se]Click to visit my blog[/]");
|
||||
// When
|
||||
console.Markup("[link=https://patriksvensson.se]Click to visit my blog[/]");
|
||||
|
||||
// Then
|
||||
console.Output.ShouldMatch("]8;id=[0-9]*;https:\\/\\/patriksvensson\\.se\\\\Click to visit my blog]8;;\\\\");
|
||||
}
|
||||
// Then
|
||||
console.Output.ShouldMatch("]8;id=[0-9]*;https:\\/\\/patriksvensson\\.se\\\\Click to visit my blog]8;;\\\\");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Output_Expected_Ansi_For_Link_With_Only_Url()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.EmitAnsiSequences();
|
||||
[Fact]
|
||||
public void Should_Output_Expected_Ansi_For_Link_With_Only_Url()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Markup("[link]https://patriksvensson.se[/]");
|
||||
// When
|
||||
console.Markup("[link]https://patriksvensson.se[/]");
|
||||
|
||||
// Then
|
||||
console.Output.ShouldMatch("]8;id=[0-9]*;https:\\/\\/patriksvensson\\.se\\\\https:\\/\\/patriksvensson\\.se]8;;\\\\");
|
||||
}
|
||||
// Then
|
||||
console.Output.ShouldMatch("]8;id=[0-9]*;https:\\/\\/patriksvensson\\.se\\\\https:\\/\\/patriksvensson\\.se]8;;\\\\");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("[yellow]Hello [[ World[/]", "[93mHello [ World[0m")]
|
||||
public void Should_Be_Able_To_Escape_Tags(string markup, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
[Theory]
|
||||
[InlineData("[yellow]Hello [[ World[/]", "[93mHello [ World[0m")]
|
||||
public void Should_Be_Able_To_Escape_Tags(string markup, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Markup(markup);
|
||||
// When
|
||||
console.Markup(markup);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("[yellow]Hello[", "Encountered malformed markup tag at position 14.")]
|
||||
[InlineData("[yellow]Hello[/", "Encountered malformed markup tag at position 15.")]
|
||||
[InlineData("[yellow]Hello[/foo", "Encountered malformed markup tag at position 15.")]
|
||||
[InlineData("[yellow Hello", "Encountered malformed markup tag at position 13.")]
|
||||
public void Should_Throw_If_Encounters_Malformed_Tag(string markup, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
[Theory]
|
||||
[InlineData("[yellow]Hello[", "Encountered malformed markup tag at position 14.")]
|
||||
[InlineData("[yellow]Hello[/", "Encountered malformed markup tag at position 15.")]
|
||||
[InlineData("[yellow]Hello[/foo", "Encountered malformed markup tag at position 15.")]
|
||||
[InlineData("[yellow Hello", "Encountered malformed markup tag at position 13.")]
|
||||
public void Should_Throw_If_Encounters_Malformed_Tag(string markup, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => console.Markup(markup));
|
||||
// When
|
||||
var result = Record.Exception(() => console.Markup(markup));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>()
|
||||
.Message.ShouldBe(expected);
|
||||
}
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>()
|
||||
.Message.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Tags_Are_Unbalanced()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
[Fact]
|
||||
public void Should_Throw_If_Tags_Are_Unbalanced()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => console.Markup("[yellow][blue]Hello[/]"));
|
||||
// When
|
||||
var result = Record.Exception(() => console.Markup("[yellow][blue]Hello[/]"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>()
|
||||
.Message.ShouldBe("Unbalanced markup stack. Did you forget to close a tag?");
|
||||
}
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>()
|
||||
.Message.ShouldBe("Unbalanced markup stack. Did you forget to close a tag?");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Encounters_Closing_Tag()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
[Fact]
|
||||
public void Should_Throw_If_Encounters_Closing_Tag()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => console.Markup("Hello[/]World"));
|
||||
// When
|
||||
var result = Record.Exception(() => console.Markup("Hello[/]World"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>()
|
||||
.Message.ShouldBe("Encountered closing tag when none was expected near position 5.");
|
||||
}
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>()
|
||||
.Message.ShouldBe("Encountered closing tag when none was expected near position 5.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,23 @@
|
||||
using System;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public partial class AnsiConsoleTests
|
||||
{
|
||||
public partial class AnsiConsoleTests
|
||||
public sealed class Prompt
|
||||
{
|
||||
public sealed class Prompt
|
||||
[Theory]
|
||||
[InlineData(true, true)]
|
||||
[InlineData(false, false)]
|
||||
public void Should_Return_Default_Value_If_Nothing_Is_Entered(bool expected, bool defaultValue)
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(true, true)]
|
||||
[InlineData(false, false)]
|
||||
public void Should_Return_Default_Value_If_Nothing_Is_Entered(bool expected, bool defaultValue)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().EmitAnsiSequences();
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
// Given
|
||||
var console = new TestConsole().EmitAnsiSequences();
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
|
||||
// When
|
||||
var result = console.Confirm("Want some prompt?", defaultValue);
|
||||
// When
|
||||
var result = console.Confirm("Want some prompt?", defaultValue);
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,48 +1,43 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public partial class AnsiConsoleTests
|
||||
{
|
||||
public partial class AnsiConsoleTests
|
||||
[Theory]
|
||||
[InlineData(Decoration.Bold, "\u001b[1mHello World[0m")]
|
||||
[InlineData(Decoration.Dim, "\u001b[2mHello World[0m")]
|
||||
[InlineData(Decoration.Italic, "\u001b[3mHello World[0m")]
|
||||
[InlineData(Decoration.Underline, "\u001b[4mHello World[0m")]
|
||||
[InlineData(Decoration.Invert, "\u001b[7mHello World[0m")]
|
||||
[InlineData(Decoration.Conceal, "\u001b[8mHello World[0m")]
|
||||
[InlineData(Decoration.SlowBlink, "\u001b[5mHello World[0m")]
|
||||
[InlineData(Decoration.RapidBlink, "\u001b[6mHello World[0m")]
|
||||
[InlineData(Decoration.Strikethrough, "\u001b[9mHello World[0m")]
|
||||
public void Should_Write_Decorated_Text_Correctly(Decoration decoration, string expected)
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(Decoration.Bold, "\u001b[1mHello World[0m")]
|
||||
[InlineData(Decoration.Dim, "\u001b[2mHello World[0m")]
|
||||
[InlineData(Decoration.Italic, "\u001b[3mHello World[0m")]
|
||||
[InlineData(Decoration.Underline, "\u001b[4mHello World[0m")]
|
||||
[InlineData(Decoration.Invert, "\u001b[7mHello World[0m")]
|
||||
[InlineData(Decoration.Conceal, "\u001b[8mHello World[0m")]
|
||||
[InlineData(Decoration.SlowBlink, "\u001b[5mHello World[0m")]
|
||||
[InlineData(Decoration.RapidBlink, "\u001b[6mHello World[0m")]
|
||||
[InlineData(Decoration.Strikethrough, "\u001b[9mHello World[0m")]
|
||||
public void Should_Write_Decorated_Text_Correctly(Decoration decoration, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.EmitAnsiSequences();
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello World", new Style().Decoration(decoration));
|
||||
// When
|
||||
console.Write("Hello World", new Style().Decoration(decoration));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Decoration.Bold | Decoration.Underline, "\u001b[1;4mHello World[0m")]
|
||||
[InlineData(Decoration.Bold | Decoration.Underline | Decoration.Conceal, "\u001b[1;4;8mHello World[0m")]
|
||||
public void Should_Write_Text_With_Multiple_Decorations_Correctly(Decoration decoration, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello World", new Style().Decoration(decoration));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Decoration.Bold | Decoration.Underline, "\u001b[1;4mHello World[0m")]
|
||||
[InlineData(Decoration.Bold | Decoration.Underline | Decoration.Conceal, "\u001b[1;4;8mHello World[0m")]
|
||||
public void Should_Write_Text_With_Multiple_Decorations_Correctly(Decoration decoration, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello World", new Style().Decoration(decoration));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
@ -1,151 +1,145 @@
|
||||
using System;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public partial class AnsiConsoleTests
|
||||
{
|
||||
public partial class AnsiConsoleTests
|
||||
public sealed class Clear
|
||||
{
|
||||
public sealed class Clear
|
||||
[Theory]
|
||||
[InlineData(false, "Hello[2J[3JWorld")]
|
||||
[InlineData(true, "Hello[2J[3J[1;1HWorld")]
|
||||
public void Should_Clear_Screen(bool home, string expected)
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(false, "Hello[2J[3JWorld")]
|
||||
[InlineData(true, "Hello[2J[3J[1;1HWorld")]
|
||||
public void Should_Clear_Screen(bool home, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write("Hello");
|
||||
console.Clear(home);
|
||||
console.Write("World");
|
||||
// When
|
||||
console.Write("Hello");
|
||||
console.Clear(home);
|
||||
console.Write("World");
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Write
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Combine_Decoration_And_Colors()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write(
|
||||
"Hello",
|
||||
new Style()
|
||||
.Foreground(Color.RoyalBlue1)
|
||||
.Background(Color.NavajoWhite1)
|
||||
.Decoration(Decoration.Italic));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("\u001b[3;90;47mHello\u001b[0m");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Include_Foreground_If_Set_To_Default_Color()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write(
|
||||
"Hello",
|
||||
new Style()
|
||||
.Foreground(Color.Default)
|
||||
.Background(Color.NavajoWhite1)
|
||||
.Decoration(Decoration.Italic));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("\u001b[3;47mHello\u001b[0m");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Include_Background_If_Set_To_Default_Color()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write(
|
||||
"Hello",
|
||||
new Style()
|
||||
.Foreground(Color.RoyalBlue1)
|
||||
.Background(Color.Default)
|
||||
.Decoration(Decoration.Italic));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("\u001b[3;90mHello\u001b[0m");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Include_Decoration_If_Set_To_None()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write(
|
||||
"Hello",
|
||||
new Style()
|
||||
.Foreground(Color.RoyalBlue1)
|
||||
.Background(Color.NavajoWhite1)
|
||||
.Decoration(Decoration.None));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("\u001b[90;47mHello\u001b[0m");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class WriteLine
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Reset_Colors_Correctly_After_Line_Break()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.WriteLine("Hello", new Style().Background(ConsoleColor.Red));
|
||||
console.WriteLine("World", new Style().Background(ConsoleColor.Green));
|
||||
|
||||
// Then
|
||||
console.Output.NormalizeLineEndings()
|
||||
.ShouldBe("[101mHello[0m\n[102mWorld[0m\n");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Reset_Colors_Correctly_After_Line_Break_In_Text()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.WriteLine("Hello\nWorld", new Style().Background(ConsoleColor.Red));
|
||||
|
||||
// Then
|
||||
console.Output.NormalizeLineEndings()
|
||||
.ShouldBe("[101mHello[0m\n[101mWorld[0m\n");
|
||||
}
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Write
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Combine_Decoration_And_Colors()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write(
|
||||
"Hello",
|
||||
new Style()
|
||||
.Foreground(Color.RoyalBlue1)
|
||||
.Background(Color.NavajoWhite1)
|
||||
.Decoration(Decoration.Italic));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("\u001b[3;90;47mHello\u001b[0m");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Include_Foreground_If_Set_To_Default_Color()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write(
|
||||
"Hello",
|
||||
new Style()
|
||||
.Foreground(Color.Default)
|
||||
.Background(Color.NavajoWhite1)
|
||||
.Decoration(Decoration.Italic));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("\u001b[3;47mHello\u001b[0m");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Include_Background_If_Set_To_Default_Color()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write(
|
||||
"Hello",
|
||||
new Style()
|
||||
.Foreground(Color.RoyalBlue1)
|
||||
.Background(Color.Default)
|
||||
.Decoration(Decoration.Italic));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("\u001b[3;90mHello\u001b[0m");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Include_Decoration_If_Set_To_None()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.Write(
|
||||
"Hello",
|
||||
new Style()
|
||||
.Foreground(Color.RoyalBlue1)
|
||||
.Background(Color.NavajoWhite1)
|
||||
.Decoration(Decoration.None));
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("\u001b[90;47mHello\u001b[0m");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class WriteLine
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Reset_Colors_Correctly_After_Line_Break()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.WriteLine("Hello", new Style().Background(ConsoleColor.Red));
|
||||
console.WriteLine("World", new Style().Background(ConsoleColor.Green));
|
||||
|
||||
// Then
|
||||
console.Output.NormalizeLineEndings()
|
||||
.ShouldBe("[101mHello[0m\n[102mWorld[0m\n");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Reset_Colors_Correctly_After_Line_Break_In_Text()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
// When
|
||||
console.WriteLine("Hello\nWorld", new Style().Background(ConsoleColor.Red));
|
||||
|
||||
// Then
|
||||
console.Output.NormalizeLineEndings()
|
||||
.ShouldBe("[101mHello[0m\n[101mWorld[0m\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,97 +1,88 @@
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli.Annotations;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli.Annotations
|
||||
[ExpectationPath("Cli/Arguments")]
|
||||
public sealed partial class CommandArgumentAttributeTests
|
||||
{
|
||||
[ExpectationPath("Cli/Arguments")]
|
||||
public sealed partial class CommandArgumentAttributeTests
|
||||
[UsesVerify]
|
||||
public sealed class ArgumentCannotContainOptions
|
||||
{
|
||||
[UsesVerify]
|
||||
public sealed class ArgumentCannotContainOptions
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "--foo <BAR>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("ArgumentCannotContainOptions")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
[CommandArgument(0, "--foo <BAR>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class MultipleValuesAreNotSupported
|
||||
[Fact]
|
||||
[Expectation("ArgumentCannotContainOptions")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<FOO> <BAR>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
[Fact]
|
||||
[Expectation("MultipleValuesAreNotSupported")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
}
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
[UsesVerify]
|
||||
public sealed class MultipleValuesAreNotSupported
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<FOO> <BAR>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class ValuesMustHaveName
|
||||
[Fact]
|
||||
[Expectation("MultipleValuesAreNotSupported")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
[Fact]
|
||||
[Expectation("ValuesMustHaveName")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
}
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
[UsesVerify]
|
||||
public sealed class ValuesMustHaveName
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
private static class Fixture
|
||||
[Fact]
|
||||
[Expectation("ValuesMustHaveName")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
public static string Run<TSettings>(params string[] args)
|
||||
where TSettings : CommandSettings
|
||||
{
|
||||
using (var writer = new TestConsole())
|
||||
{
|
||||
var app = new CommandApp();
|
||||
app.Configure(c => c.ConfigureConsole(writer));
|
||||
app.Configure(c => c.AddCommand<GenericCommand<TSettings>>("foo"));
|
||||
app.Run(args);
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
return writer.Output
|
||||
.NormalizeLineEndings()
|
||||
.TrimLines()
|
||||
.Trim();
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Fixture
|
||||
{
|
||||
public static string Run<TSettings>(params string[] args)
|
||||
where TSettings : CommandSettings
|
||||
{
|
||||
using (var writer = new TestConsole())
|
||||
{
|
||||
var app = new CommandApp();
|
||||
app.Configure(c => c.ConfigureConsole(writer));
|
||||
app.Configure(c => c.AddCommand<GenericCommand<TSettings>>("foo"));
|
||||
app.Run(args);
|
||||
|
||||
return writer.Output
|
||||
.NormalizeLineEndings()
|
||||
.TrimLines()
|
||||
.Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,64 +1,59 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli.Annotations;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli.Annotations
|
||||
public sealed partial class CommandArgumentAttributeTests
|
||||
{
|
||||
public sealed partial class CommandArgumentAttributeTests
|
||||
[Fact]
|
||||
public void Should_Not_Contain_Options()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Not_Contain_Options()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new CommandArgumentAttribute(0, "--foo <BAR>"));
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new CommandArgumentAttribute(0, "--foo <BAR>"));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBe(null);
|
||||
result.ShouldBeOfType<CommandTemplateException>().And(exception =>
|
||||
exception.Message.ShouldBe("Arguments can not contain options."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("<FOO> <BAR>")]
|
||||
[InlineData("[FOO] [BAR]")]
|
||||
[InlineData("[FOO] <BAR>")]
|
||||
[InlineData("<FOO> [BAR]")]
|
||||
public void Should_Not_Contain_Multiple_Value_Names(string template)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new CommandArgumentAttribute(0, template));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBe(null);
|
||||
result.ShouldBeOfType<CommandTemplateException>().And(exception =>
|
||||
exception.Message.ShouldBe("Multiple values are not supported."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("<>")]
|
||||
[InlineData("[]")]
|
||||
public void Should_Not_Contain_Empty_Value_Name(string template)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new CommandArgumentAttribute(0, template));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBe(null);
|
||||
result.ShouldBeOfType<CommandTemplateException>().And(exception =>
|
||||
exception.Message.ShouldBe("Values without name are not allowed."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("<FOO>", true)]
|
||||
[InlineData("[FOO]", false)]
|
||||
public void Should_Parse_Valid_Options(string template, bool required)
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandArgumentAttribute(0, template);
|
||||
|
||||
// Then
|
||||
result.ValueName.ShouldBe("FOO");
|
||||
result.IsRequired.ShouldBe(required);
|
||||
}
|
||||
// Then
|
||||
result.ShouldNotBe(null);
|
||||
result.ShouldBeOfType<CommandTemplateException>().And(exception =>
|
||||
exception.Message.ShouldBe("Arguments can not contain options."));
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("<FOO> <BAR>")]
|
||||
[InlineData("[FOO] [BAR]")]
|
||||
[InlineData("[FOO] <BAR>")]
|
||||
[InlineData("<FOO> [BAR]")]
|
||||
public void Should_Not_Contain_Multiple_Value_Names(string template)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new CommandArgumentAttribute(0, template));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBe(null);
|
||||
result.ShouldBeOfType<CommandTemplateException>().And(exception =>
|
||||
exception.Message.ShouldBe("Multiple values are not supported."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("<>")]
|
||||
[InlineData("[]")]
|
||||
public void Should_Not_Contain_Empty_Value_Name(string template)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new CommandArgumentAttribute(0, template));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBe(null);
|
||||
result.ShouldBeOfType<CommandTemplateException>().And(exception =>
|
||||
exception.Message.ShouldBe("Values without name are not allowed."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("<FOO>", true)]
|
||||
[InlineData("[FOO]", false)]
|
||||
public void Should_Parse_Valid_Options(string template, bool required)
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandArgumentAttribute(0, template);
|
||||
|
||||
// Then
|
||||
result.ValueName.ShouldBe("FOO");
|
||||
result.IsRequired.ShouldBe(required);
|
||||
}
|
||||
}
|
||||
|
@ -1,250 +1,240 @@
|
||||
using System.Threading.Tasks;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli.Annotations;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli.Annotations
|
||||
[ExpectationPath("Cli/Arguments")]
|
||||
public sealed partial class CommandOptionAttributeTests
|
||||
{
|
||||
[ExpectationPath("Cli/Arguments")]
|
||||
public sealed partial class CommandOptionAttributeTests
|
||||
[UsesVerify]
|
||||
public sealed class UnexpectedCharacter
|
||||
{
|
||||
[UsesVerify]
|
||||
public sealed class UnexpectedCharacter
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("<FOO> $ <BAR>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("UnexpectedCharacter")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Encountered unexpected character '$'.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
[CommandOption("<FOO> $ <BAR>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class UnterminatedValueName
|
||||
[Fact]
|
||||
[Expectation("UnexpectedCharacter")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("--foo|-f <BAR")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
[Fact]
|
||||
[Expectation("UnterminatedValueName")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Encountered unterminated value name 'BAR'.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class OptionsMustHaveName
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("--foo|-")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("OptionsMustHaveName")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Options without name are not allowed.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class OptionNamesCannotStartWithDigit
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("--1foo")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("OptionNamesCannotStartWithDigit")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Option names cannot start with a digit.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class InvalidCharacterInOptionName
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("--f$oo")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("InvalidCharacterInOptionName")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Encountered invalid character '$' in option name.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class LongOptionMustHaveMoreThanOneCharacter
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("--f")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("LongOptionMustHaveMoreThanOneCharacter")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Long option names must consist of more than one character.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class ShortOptionMustOnlyBeOneCharacter
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("--foo|-bar")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("ShortOptionMustOnlyBeOneCharacter")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Short option names can not be longer than one character.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class MultipleOptionValuesAreNotSupported
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("-f|--foo <FOO> <BAR>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("MultipleOptionValuesAreNotSupported")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Multiple option values are not supported.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class InvalidCharacterInValueName
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("-f|--foo <F$OO>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("InvalidCharacterInValueName")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Encountered invalid character '$' in value name.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class MissingLongAndShortName
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("<FOO>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("MissingLongAndShortName")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("No long or short name for option has been specified.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Fixture
|
||||
{
|
||||
public static CommandAppFailure Run<TSettings>(params string[] args)
|
||||
where TSettings : CommandSettings
|
||||
{
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(c =>
|
||||
{
|
||||
c.AddCommand<GenericCommand<TSettings>>("foo");
|
||||
});
|
||||
|
||||
return app.RunAndCatch<CommandTemplateException>(args);
|
||||
}
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Encountered unexpected character '$'.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class UnterminatedValueName
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("--foo|-f <BAR")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("UnterminatedValueName")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Encountered unterminated value name 'BAR'.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class OptionsMustHaveName
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("--foo|-")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("OptionsMustHaveName")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Options without name are not allowed.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class OptionNamesCannotStartWithDigit
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("--1foo")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("OptionNamesCannotStartWithDigit")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Option names cannot start with a digit.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class InvalidCharacterInOptionName
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("--f$oo")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("InvalidCharacterInOptionName")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Encountered invalid character '$' in option name.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class LongOptionMustHaveMoreThanOneCharacter
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("--f")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("LongOptionMustHaveMoreThanOneCharacter")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Long option names must consist of more than one character.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class ShortOptionMustOnlyBeOneCharacter
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("--foo|-bar")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("ShortOptionMustOnlyBeOneCharacter")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Short option names can not be longer than one character.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class MultipleOptionValuesAreNotSupported
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("-f|--foo <FOO> <BAR>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("MultipleOptionValuesAreNotSupported")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Multiple option values are not supported.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class InvalidCharacterInValueName
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("-f|--foo <F$OO>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("InvalidCharacterInValueName")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("Encountered invalid character '$' in value name.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class MissingLongAndShortName
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("<FOO>")]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("MissingLongAndShortName")]
|
||||
public Task Should_Return_Correct_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Fixture.Run<Settings>();
|
||||
|
||||
// Then
|
||||
result.Exception.Message.ShouldBe("No long or short name for option has been specified.");
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Fixture
|
||||
{
|
||||
public static CommandAppFailure Run<TSettings>(params string[] args)
|
||||
where TSettings : CommandSettings
|
||||
{
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(c =>
|
||||
{
|
||||
c.AddCommand<GenericCommand<TSettings>>("foo");
|
||||
});
|
||||
|
||||
return app.RunAndCatch<CommandTemplateException>(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,217 +1,212 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli.Annotations;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli.Annotations
|
||||
public sealed partial class CommandOptionAttributeTests
|
||||
{
|
||||
public sealed partial class CommandOptionAttributeTests
|
||||
[Fact]
|
||||
public void Should_Parse_Short_Name_Correctly()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Parse_Short_Name_Correctly()
|
||||
{
|
||||
// Given, When
|
||||
var option = new CommandOptionAttribute("-o|--option <VALUE>");
|
||||
// Given, When
|
||||
var option = new CommandOptionAttribute("-o|--option <VALUE>");
|
||||
|
||||
// Then
|
||||
option.ShortNames.ShouldContain("o");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Long_Name_Correctly()
|
||||
{
|
||||
// Given, When
|
||||
var option = new CommandOptionAttribute("-o|--option <VALUE>");
|
||||
|
||||
// Then
|
||||
option.LongNames.ShouldContain("option");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("<VALUE>")]
|
||||
public void Should_Parse_Value_Correctly(string value)
|
||||
{
|
||||
// Given, When
|
||||
var option = new CommandOptionAttribute($"-o|--option {value}");
|
||||
|
||||
// Then
|
||||
option.ValueName.ShouldBe("VALUE");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Only_Short_Name()
|
||||
{
|
||||
// Given, When
|
||||
var option = new CommandOptionAttribute("-o");
|
||||
|
||||
// Then
|
||||
option.ShortNames.ShouldContain("o");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Only_Long_Name()
|
||||
{
|
||||
// Given, When
|
||||
var option = new CommandOptionAttribute("--option");
|
||||
|
||||
// Then
|
||||
option.LongNames.ShouldContain("option");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData("<VALUE>")]
|
||||
public void Should_Throw_If_Template_Is_Empty(string value)
|
||||
{
|
||||
// Given, When
|
||||
var option = Record.Exception(() => new CommandOptionAttribute(value));
|
||||
|
||||
// Then
|
||||
option.ShouldBeOfType<CommandTemplateException>().And(e =>
|
||||
e.Message.ShouldBe("No long or short name for option has been specified."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("--bar|-foo")]
|
||||
[InlineData("--bar|-f-b")]
|
||||
public void Should_Throw_If_Short_Name_Is_Invalid(string value)
|
||||
{
|
||||
// Given, When
|
||||
var option = Record.Exception(() => new CommandOptionAttribute(value));
|
||||
|
||||
// Then
|
||||
option.ShouldBeOfType<CommandTemplateException>().And(e =>
|
||||
e.Message.ShouldBe("Short option names can not be longer than one character."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("--o")]
|
||||
public void Should_Throw_If_Long_Name_Is_Invalid(string value)
|
||||
{
|
||||
// Given, When
|
||||
var option = Record.Exception(() => new CommandOptionAttribute(value));
|
||||
|
||||
// Then
|
||||
option.ShouldBeOfType<CommandTemplateException>().And(e =>
|
||||
e.Message.ShouldBe("Long option names must consist of more than one character."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("-")]
|
||||
[InlineData("--")]
|
||||
public void Should_Throw_If_Option_Have_No_Name(string template)
|
||||
{
|
||||
// Given, When
|
||||
var option = Record.Exception(() => new CommandOptionAttribute(template));
|
||||
|
||||
// Then
|
||||
option.ShouldBeOfType<CommandTemplateException>().And(e =>
|
||||
e.Message.ShouldBe("Options without name are not allowed."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("--foo|-foo[b", '[')]
|
||||
[InlineData("--foo|-f€b", '€')]
|
||||
[InlineData("--foo|-foo@b", '@')]
|
||||
public void Should_Throw_If_Option_Contains_Invalid_Name(string template, char invalid)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new CommandOptionAttribute(template));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandTemplateException>().And(e =>
|
||||
{
|
||||
e.Message.ShouldBe($"Encountered invalid character '{invalid}' in option name.");
|
||||
e.Template.ShouldBe(template);
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("--foo <HELLO-WORLD>", "HELLO-WORLD")]
|
||||
[InlineData("--foo <HELLO_WORLD>", "HELLO_WORLD")]
|
||||
public void Should_Accept_Dash_And_Underscore_In_Value_Name(string template, string name)
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandOptionAttribute(template);
|
||||
|
||||
// Then
|
||||
result.ValueName.ShouldBe(name);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("--foo|-1")]
|
||||
public void Should_Throw_If_First_Letter_Of_An_Option_Name_Is_A_Digit(string template)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new CommandOptionAttribute(template));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandTemplateException>().And(e =>
|
||||
{
|
||||
e.Message.ShouldBe("Option names cannot start with a digit.");
|
||||
e.Template.ShouldBe(template);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Multiple_Short_Options_Are_Supported()
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandOptionAttribute("-f|-b");
|
||||
|
||||
// Then
|
||||
result.ShortNames.Count.ShouldBe(2);
|
||||
result.ShortNames.ShouldContain("f");
|
||||
result.ShortNames.ShouldContain("b");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Multiple_Long_Options_Are_Supported()
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandOptionAttribute("--foo|--bar");
|
||||
|
||||
// Then
|
||||
result.LongNames.Count.ShouldBe(2);
|
||||
result.LongNames.ShouldContain("foo");
|
||||
result.LongNames.ShouldContain("bar");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("-f|--foo <BAR>")]
|
||||
[InlineData("--foo|-f <BAR>")]
|
||||
[InlineData("<BAR> --foo|-f")]
|
||||
[InlineData("<BAR> -f|--foo")]
|
||||
[InlineData("-f <BAR> --foo")]
|
||||
[InlineData("--foo <BAR> -f")]
|
||||
public void Template_Parts_Can_Appear_In_Any_Order(string template)
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandOptionAttribute(template);
|
||||
|
||||
// Then
|
||||
result.LongNames.ShouldContain("foo");
|
||||
result.ShortNames.ShouldContain("f");
|
||||
result.ValueName.ShouldBe("BAR");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Is_Not_Hidden_From_Help_By_Default()
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandOptionAttribute("--foo");
|
||||
|
||||
// Then
|
||||
result.IsHidden.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Can_Indicate_That_It_Must_Be_Hidden_From_Help_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandOptionAttribute("--foo") { IsHidden = true };
|
||||
|
||||
// Then
|
||||
result.IsHidden.ShouldBeTrue();
|
||||
}
|
||||
// Then
|
||||
option.ShortNames.ShouldContain("o");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Long_Name_Correctly()
|
||||
{
|
||||
// Given, When
|
||||
var option = new CommandOptionAttribute("-o|--option <VALUE>");
|
||||
|
||||
// Then
|
||||
option.LongNames.ShouldContain("option");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("<VALUE>")]
|
||||
public void Should_Parse_Value_Correctly(string value)
|
||||
{
|
||||
// Given, When
|
||||
var option = new CommandOptionAttribute($"-o|--option {value}");
|
||||
|
||||
// Then
|
||||
option.ValueName.ShouldBe("VALUE");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Only_Short_Name()
|
||||
{
|
||||
// Given, When
|
||||
var option = new CommandOptionAttribute("-o");
|
||||
|
||||
// Then
|
||||
option.ShortNames.ShouldContain("o");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Only_Long_Name()
|
||||
{
|
||||
// Given, When
|
||||
var option = new CommandOptionAttribute("--option");
|
||||
|
||||
// Then
|
||||
option.LongNames.ShouldContain("option");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData("<VALUE>")]
|
||||
public void Should_Throw_If_Template_Is_Empty(string value)
|
||||
{
|
||||
// Given, When
|
||||
var option = Record.Exception(() => new CommandOptionAttribute(value));
|
||||
|
||||
// Then
|
||||
option.ShouldBeOfType<CommandTemplateException>().And(e =>
|
||||
e.Message.ShouldBe("No long or short name for option has been specified."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("--bar|-foo")]
|
||||
[InlineData("--bar|-f-b")]
|
||||
public void Should_Throw_If_Short_Name_Is_Invalid(string value)
|
||||
{
|
||||
// Given, When
|
||||
var option = Record.Exception(() => new CommandOptionAttribute(value));
|
||||
|
||||
// Then
|
||||
option.ShouldBeOfType<CommandTemplateException>().And(e =>
|
||||
e.Message.ShouldBe("Short option names can not be longer than one character."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("--o")]
|
||||
public void Should_Throw_If_Long_Name_Is_Invalid(string value)
|
||||
{
|
||||
// Given, When
|
||||
var option = Record.Exception(() => new CommandOptionAttribute(value));
|
||||
|
||||
// Then
|
||||
option.ShouldBeOfType<CommandTemplateException>().And(e =>
|
||||
e.Message.ShouldBe("Long option names must consist of more than one character."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("-")]
|
||||
[InlineData("--")]
|
||||
public void Should_Throw_If_Option_Have_No_Name(string template)
|
||||
{
|
||||
// Given, When
|
||||
var option = Record.Exception(() => new CommandOptionAttribute(template));
|
||||
|
||||
// Then
|
||||
option.ShouldBeOfType<CommandTemplateException>().And(e =>
|
||||
e.Message.ShouldBe("Options without name are not allowed."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("--foo|-foo[b", '[')]
|
||||
[InlineData("--foo|-f€b", '€')]
|
||||
[InlineData("--foo|-foo@b", '@')]
|
||||
public void Should_Throw_If_Option_Contains_Invalid_Name(string template, char invalid)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new CommandOptionAttribute(template));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandTemplateException>().And(e =>
|
||||
{
|
||||
e.Message.ShouldBe($"Encountered invalid character '{invalid}' in option name.");
|
||||
e.Template.ShouldBe(template);
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("--foo <HELLO-WORLD>", "HELLO-WORLD")]
|
||||
[InlineData("--foo <HELLO_WORLD>", "HELLO_WORLD")]
|
||||
public void Should_Accept_Dash_And_Underscore_In_Value_Name(string template, string name)
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandOptionAttribute(template);
|
||||
|
||||
// Then
|
||||
result.ValueName.ShouldBe(name);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("--foo|-1")]
|
||||
public void Should_Throw_If_First_Letter_Of_An_Option_Name_Is_A_Digit(string template)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new CommandOptionAttribute(template));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandTemplateException>().And(e =>
|
||||
{
|
||||
e.Message.ShouldBe("Option names cannot start with a digit.");
|
||||
e.Template.ShouldBe(template);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Multiple_Short_Options_Are_Supported()
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandOptionAttribute("-f|-b");
|
||||
|
||||
// Then
|
||||
result.ShortNames.Count.ShouldBe(2);
|
||||
result.ShortNames.ShouldContain("f");
|
||||
result.ShortNames.ShouldContain("b");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Multiple_Long_Options_Are_Supported()
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandOptionAttribute("--foo|--bar");
|
||||
|
||||
// Then
|
||||
result.LongNames.Count.ShouldBe(2);
|
||||
result.LongNames.ShouldContain("foo");
|
||||
result.LongNames.ShouldContain("bar");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("-f|--foo <BAR>")]
|
||||
[InlineData("--foo|-f <BAR>")]
|
||||
[InlineData("<BAR> --foo|-f")]
|
||||
[InlineData("<BAR> -f|--foo")]
|
||||
[InlineData("-f <BAR> --foo")]
|
||||
[InlineData("--foo <BAR> -f")]
|
||||
public void Template_Parts_Can_Appear_In_Any_Order(string template)
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandOptionAttribute(template);
|
||||
|
||||
// Then
|
||||
result.LongNames.ShouldContain("foo");
|
||||
result.ShortNames.ShouldContain("f");
|
||||
result.ValueName.ShouldBe("BAR");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Is_Not_Hidden_From_Help_By_Default()
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandOptionAttribute("--foo");
|
||||
|
||||
// Then
|
||||
result.IsHidden.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Can_Indicate_That_It_Must_Be_Hidden_From_Help_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = new CommandOptionAttribute("--foo") { IsHidden = true };
|
||||
|
||||
// Then
|
||||
result.IsHidden.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
|
@ -1,110 +1,104 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
public class NullableSettings : CommandSettings
|
||||
{
|
||||
public class NullableSettings : CommandSettings
|
||||
public NullableSettings(bool? detailed, string[] extra)
|
||||
{
|
||||
public NullableSettings(bool? detailed, string[] extra)
|
||||
{
|
||||
Detailed = detailed;
|
||||
Extra = extra;
|
||||
}
|
||||
|
||||
[CommandOption("-d")]
|
||||
public bool? Detailed { get; }
|
||||
|
||||
[CommandArgument(0, "[extra]")]
|
||||
public string[] Extra { get; }
|
||||
Detailed = detailed;
|
||||
Extra = extra;
|
||||
}
|
||||
|
||||
public class NullableWithInitSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("-d")]
|
||||
public bool? Detailed { get; init; }
|
||||
[CommandOption("-d")]
|
||||
public bool? Detailed { get; }
|
||||
|
||||
[CommandArgument(0, "[extra]")]
|
||||
public string[] Extra { get; init; }
|
||||
}
|
||||
|
||||
public class NullableCommand : Command<NullableSettings>
|
||||
{
|
||||
public override int Execute(CommandContext context, NullableSettings settings) => 0;
|
||||
}
|
||||
|
||||
public class NullableWithInitCommand : Command<NullableWithInitSettings>
|
||||
{
|
||||
public override int Execute(CommandContext context, NullableWithInitSettings settings) => 0;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Populate_Nullable_Objects_In_Settings()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<NullableCommand>("null");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("null");
|
||||
|
||||
// Then
|
||||
result.Settings.ShouldBeOfType<NullableSettings>().And(settings =>
|
||||
{
|
||||
settings.Detailed.ShouldBeNull();
|
||||
settings.Extra.ShouldBeNull();
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Populate_Nullable_Objects_With_Init_In_Settings()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<NullableWithInitCommand>("null");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("null");
|
||||
|
||||
// Then
|
||||
result.Settings.ShouldBeOfType<NullableWithInitSettings>().And(settings =>
|
||||
{
|
||||
settings.Detailed.ShouldBeNull();
|
||||
settings.Extra.ShouldBeNull();
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Populate_Regular_Settings()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<NullableCommand>("null");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("null", "-d", "true", "first-item");
|
||||
|
||||
// Then
|
||||
result.Settings.ShouldBeOfType<NullableSettings>().And(settings =>
|
||||
{
|
||||
settings.Detailed.ShouldBe(true);
|
||||
settings.Extra.ShouldBe(new[] { "first-item" });
|
||||
});
|
||||
}
|
||||
[CommandArgument(0, "[extra]")]
|
||||
public string[] Extra { get; }
|
||||
}
|
||||
}
|
||||
|
||||
public class NullableWithInitSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("-d")]
|
||||
public bool? Detailed { get; init; }
|
||||
|
||||
[CommandArgument(0, "[extra]")]
|
||||
public string[] Extra { get; init; }
|
||||
}
|
||||
|
||||
public class NullableCommand : Command<NullableSettings>
|
||||
{
|
||||
public override int Execute(CommandContext context, NullableSettings settings) => 0;
|
||||
}
|
||||
|
||||
public class NullableWithInitCommand : Command<NullableWithInitSettings>
|
||||
{
|
||||
public override int Execute(CommandContext context, NullableWithInitSettings settings) => 0;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Populate_Nullable_Objects_In_Settings()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<NullableCommand>("null");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("null");
|
||||
|
||||
// Then
|
||||
result.Settings.ShouldBeOfType<NullableSettings>().And(settings =>
|
||||
{
|
||||
settings.Detailed.ShouldBeNull();
|
||||
settings.Extra.ShouldBeNull();
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Populate_Nullable_Objects_With_Init_In_Settings()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<NullableWithInitCommand>("null");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("null");
|
||||
|
||||
// Then
|
||||
result.Settings.ShouldBeOfType<NullableWithInitSettings>().And(settings =>
|
||||
{
|
||||
settings.Detailed.ShouldBeNull();
|
||||
settings.Extra.ShouldBeNull();
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Populate_Regular_Settings()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<NullableCommand>("null");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("null", "-d", "true", "first-item");
|
||||
|
||||
// Then
|
||||
result.Settings.ShouldBeOfType<NullableSettings>().And(settings =>
|
||||
{
|
||||
settings.Detailed.ShouldBe(true);
|
||||
settings.Extra.ShouldBe(new[] { "first-item" });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,100 +1,92 @@
|
||||
using System;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
public sealed class Exception_Handling
|
||||
{
|
||||
public sealed class Exception_Handling
|
||||
[Fact]
|
||||
public void Should_Not_Propagate_Runtime_Exceptions_If_Not_Explicitly_Told_To_Do_So()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Not_Propagate_Runtime_Exceptions_If_Not_Explicitly_Told_To_Do_So()
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
animal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
animal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[] { "animal", "4", "dog", "101", "--name", "Rufus" });
|
||||
// When
|
||||
var result = app.Run(new[] { "animal", "4", "dog", "101", "--name", "Rufus" });
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(-1);
|
||||
}
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(-1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Propagate_Exceptions_If_Not_Explicitly_Told_To_Do_So()
|
||||
[Fact]
|
||||
public void Should_Not_Propagate_Exceptions_If_Not_Explicitly_Told_To_Do_So()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.AddCommand<ThrowingCommand>("throw");
|
||||
});
|
||||
config.AddCommand<ThrowingCommand>("throw");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[] { "throw" });
|
||||
// When
|
||||
var result = app.Run(new[] { "throw" });
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(-1);
|
||||
}
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(-1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Handle_Exceptions_If_ExceptionHandler_Is_Set_Using_Action()
|
||||
[Fact]
|
||||
public void Should_Handle_Exceptions_If_ExceptionHandler_Is_Set_Using_Action()
|
||||
{
|
||||
// Given
|
||||
var exceptionHandled = false;
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var exceptionHandled = false;
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
config.AddCommand<ThrowingCommand>("throw");
|
||||
config.SetExceptionHandler(_ =>
|
||||
{
|
||||
config.AddCommand<ThrowingCommand>("throw");
|
||||
config.SetExceptionHandler(_ =>
|
||||
{
|
||||
exceptionHandled = true;
|
||||
});
|
||||
exceptionHandled = true;
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[] { "throw" });
|
||||
// When
|
||||
var result = app.Run(new[] { "throw" });
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(-1);
|
||||
exceptionHandled.ShouldBeTrue();
|
||||
}
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(-1);
|
||||
exceptionHandled.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Handle_Exceptions_If_ExceptionHandler_Is_Set_Using_Function()
|
||||
[Fact]
|
||||
public void Should_Handle_Exceptions_If_ExceptionHandler_Is_Set_Using_Function()
|
||||
{
|
||||
// Given
|
||||
var exceptionHandled = false;
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var exceptionHandled = false;
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
config.AddCommand<ThrowingCommand>("throw");
|
||||
config.SetExceptionHandler(_ =>
|
||||
{
|
||||
config.AddCommand<ThrowingCommand>("throw");
|
||||
config.SetExceptionHandler(_ =>
|
||||
{
|
||||
exceptionHandled = true;
|
||||
return -99;
|
||||
});
|
||||
exceptionHandled = true;
|
||||
return -99;
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[] { "throw" });
|
||||
// When
|
||||
var result = app.Run(new[] { "throw" });
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(-99);
|
||||
exceptionHandled.ShouldBeTrue();
|
||||
}
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(-99);
|
||||
exceptionHandled.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,223 +1,214 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
public sealed class FlagValues
|
||||
{
|
||||
public sealed class FlagValues
|
||||
[SuppressMessage("Performance", "CA1812", Justification = "It's OK")]
|
||||
private sealed class FlagSettings : CommandSettings
|
||||
{
|
||||
[SuppressMessage("Performance", "CA1812", Justification = "It's OK")]
|
||||
private sealed class FlagSettings : CommandSettings
|
||||
[CommandOption("--serve [PORT]")]
|
||||
public FlagValue<int> Serve { get; set; }
|
||||
}
|
||||
|
||||
[SuppressMessage("Performance", "CA1812", Justification = "It's OK")]
|
||||
private sealed class FlagSettingsWithNullableValueType : CommandSettings
|
||||
{
|
||||
[CommandOption("--serve [PORT]")]
|
||||
public FlagValue<int?> Serve { get; set; }
|
||||
}
|
||||
|
||||
[SuppressMessage("Performance", "CA1812", Justification = "It's OK")]
|
||||
private sealed class FlagSettingsWithOptionalOptionButNoFlagValue : CommandSettings
|
||||
{
|
||||
[CommandOption("--serve [PORT]")]
|
||||
public int Serve { get; set; }
|
||||
}
|
||||
|
||||
[SuppressMessage("Performance", "CA1812", Justification = "It's OK")]
|
||||
private sealed class FlagSettingsWithDefaultValue : CommandSettings
|
||||
{
|
||||
[CommandOption("--serve [PORT]")]
|
||||
[DefaultValue(987)]
|
||||
public FlagValue<int> Serve { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Command_Option_Value_Is_Optional_But_Type_Is_Not_A_Flag_Value()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
[CommandOption("--serve [PORT]")]
|
||||
public FlagValue<int> Serve { get; set; }
|
||||
}
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<FlagSettingsWithOptionalOptionButNoFlagValue>>("foo");
|
||||
});
|
||||
|
||||
[SuppressMessage("Performance", "CA1812", Justification = "It's OK")]
|
||||
private sealed class FlagSettingsWithNullableValueType : CommandSettings
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[] { "foo", "--serve", "123" }));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandConfigurationException>().And(ex =>
|
||||
{
|
||||
[CommandOption("--serve [PORT]")]
|
||||
public FlagValue<int?> Serve { get; set; }
|
||||
}
|
||||
ex.Message.ShouldBe("The option 'serve' has an optional value but does not implement IFlagValue.");
|
||||
});
|
||||
}
|
||||
|
||||
[SuppressMessage("Performance", "CA1812", Justification = "It's OK")]
|
||||
private sealed class FlagSettingsWithOptionalOptionButNoFlagValue : CommandSettings
|
||||
[Fact]
|
||||
public void Should_Set_Flag_And_Value_If_Both_Were_Provided()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
[CommandOption("--serve [PORT]")]
|
||||
public int Serve { get; set; }
|
||||
}
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<FlagSettings>>("foo");
|
||||
});
|
||||
|
||||
[SuppressMessage("Performance", "CA1812", Justification = "It's OK")]
|
||||
private sealed class FlagSettingsWithDefaultValue : CommandSettings
|
||||
// When
|
||||
var result = app.Run(new[] { "foo", "--serve", "123", });
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<FlagSettings>().And(flag =>
|
||||
{
|
||||
[CommandOption("--serve [PORT]")]
|
||||
[DefaultValue(987)]
|
||||
public FlagValue<int> Serve { get; set; }
|
||||
}
|
||||
flag.Serve.IsSet.ShouldBeTrue();
|
||||
flag.Serve.Value.ShouldBe(123);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Command_Option_Value_Is_Optional_But_Type_Is_Not_A_Flag_Value()
|
||||
[Fact]
|
||||
public void Should_Only_Set_Flag_If_No_Value_Was_Provided()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<FlagSettingsWithOptionalOptionButNoFlagValue>>("foo");
|
||||
});
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<FlagSettings>>("foo");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[] { "foo", "--serve", "123" }));
|
||||
// When
|
||||
var result = app.Run(new[] { "foo", "--serve" });
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandConfigurationException>().And(ex =>
|
||||
{
|
||||
ex.Message.ShouldBe("The option 'serve' has an optional value but does not implement IFlagValue.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Set_Flag_And_Value_If_Both_Were_Provided()
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<FlagSettings>().And(flag =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<FlagSettings>>("foo");
|
||||
});
|
||||
flag.Serve.IsSet.ShouldBeTrue();
|
||||
flag.Serve.Value.ShouldBe(0);
|
||||
});
|
||||
}
|
||||
|
||||
// When
|
||||
var result = app.Run(new[] { "foo", "--serve", "123", });
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<FlagSettings>().And(flag =>
|
||||
{
|
||||
flag.Serve.IsSet.ShouldBeTrue();
|
||||
flag.Serve.Value.ShouldBe(123);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Only_Set_Flag_If_No_Value_Was_Provided()
|
||||
[Fact]
|
||||
public void Should_Set_Value_To_Default_Value_If_None_Was_Explicitly_Set()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<FlagSettings>>("foo");
|
||||
});
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<FlagSettingsWithDefaultValue>>("foo");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[] { "foo", "--serve" });
|
||||
// When
|
||||
var result = app.Run(new[] { "foo", "--serve" });
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<FlagSettings>().And(flag =>
|
||||
{
|
||||
flag.Serve.IsSet.ShouldBeTrue();
|
||||
flag.Serve.Value.ShouldBe(0);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Set_Value_To_Default_Value_If_None_Was_Explicitly_Set()
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<FlagSettingsWithDefaultValue>().And(flag =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<FlagSettingsWithDefaultValue>>("foo");
|
||||
});
|
||||
flag.Serve.IsSet.ShouldBeTrue();
|
||||
flag.Serve.Value.ShouldBe(987);
|
||||
});
|
||||
}
|
||||
|
||||
// When
|
||||
var result = app.Run(new[] { "foo", "--serve" });
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<FlagSettingsWithDefaultValue>().And(flag =>
|
||||
{
|
||||
flag.Serve.IsSet.ShouldBeTrue();
|
||||
flag.Serve.Value.ShouldBe(987);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Create_Unset_Instance_If_Flag_Was_Not_Set()
|
||||
[Fact]
|
||||
public void Should_Create_Unset_Instance_If_Flag_Was_Not_Set()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<FlagSettings>>("foo");
|
||||
});
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<FlagSettings>>("foo");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[] { "foo" });
|
||||
// When
|
||||
var result = app.Run(new[] { "foo" });
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<FlagSettings>().And(flag =>
|
||||
{
|
||||
flag.Serve.IsSet.ShouldBeFalse();
|
||||
flag.Serve.Value.ShouldBe(0);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Create_Unset_Instance_With_Null_For_Nullable_Value_Type_If_Flag_Was_Not_Set()
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<FlagSettings>().And(flag =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<FlagSettingsWithNullableValueType>>("foo");
|
||||
});
|
||||
flag.Serve.IsSet.ShouldBeFalse();
|
||||
flag.Serve.Value.ShouldBe(0);
|
||||
});
|
||||
}
|
||||
|
||||
// When
|
||||
var result = app.Run(new[] { "foo" });
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<FlagSettingsWithNullableValueType>().And(flag =>
|
||||
{
|
||||
flag.Serve.IsSet.ShouldBeFalse();
|
||||
flag.Serve.Value.ShouldBeNull();
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Foo", true, "Set=True, Value=Foo")]
|
||||
[InlineData("Bar", false, "Set=False, Value=Bar")]
|
||||
public void Should_Return_Correct_String_Representation_From_ToString(
|
||||
string value,
|
||||
bool isSet,
|
||||
string expected)
|
||||
[Fact]
|
||||
public void Should_Create_Unset_Instance_With_Null_For_Nullable_Value_Type_If_Flag_Was_Not_Set()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var flag = new FlagValue<string>
|
||||
{
|
||||
Value = value,
|
||||
IsSet = isSet,
|
||||
};
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<FlagSettingsWithNullableValueType>>("foo");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = flag.ToString();
|
||||
// When
|
||||
var result = app.Run(new[] { "foo" });
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, "Set=True")]
|
||||
[InlineData(false, "Set=False")]
|
||||
public void Should_Return_Correct_String_Representation_From_ToString_If_Value_Is_Not_Set(
|
||||
bool isSet,
|
||||
string expected)
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<FlagSettingsWithNullableValueType>().And(flag =>
|
||||
{
|
||||
// Given
|
||||
var flag = new FlagValue<string>
|
||||
{
|
||||
IsSet = isSet,
|
||||
};
|
||||
flag.Serve.IsSet.ShouldBeFalse();
|
||||
flag.Serve.Value.ShouldBeNull();
|
||||
});
|
||||
}
|
||||
|
||||
// When
|
||||
var result = flag.ToString();
|
||||
[Theory]
|
||||
[InlineData("Foo", true, "Set=True, Value=Foo")]
|
||||
[InlineData("Bar", false, "Set=False, Value=Bar")]
|
||||
public void Should_Return_Correct_String_Representation_From_ToString(
|
||||
string value,
|
||||
bool isSet,
|
||||
string expected)
|
||||
{
|
||||
// Given
|
||||
var flag = new FlagValue<string>
|
||||
{
|
||||
Value = value,
|
||||
IsSet = isSet,
|
||||
};
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
// When
|
||||
var result = flag.ToString();
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, "Set=True")]
|
||||
[InlineData(false, "Set=False")]
|
||||
public void Should_Return_Correct_String_Representation_From_ToString_If_Value_Is_Not_Set(
|
||||
bool isSet,
|
||||
string expected)
|
||||
{
|
||||
// Given
|
||||
var flag = new FlagValue<string>
|
||||
{
|
||||
IsSet = isSet,
|
||||
};
|
||||
|
||||
// When
|
||||
var result = flag.ToString();
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,302 +1,293 @@
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Cli/Help")]
|
||||
public class Help
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Cli/Help")]
|
||||
public class Help
|
||||
[Fact]
|
||||
[Expectation("Root")]
|
||||
public Task Should_Output_Root_Correctly()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Root")]
|
||||
public Task Should_Output_Root_Correctly()
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<DogCommand>("dog");
|
||||
configurator.AddCommand<HorseCommand>("horse");
|
||||
configurator.AddCommand<GiraffeCommand>("giraffe");
|
||||
});
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<DogCommand>("dog");
|
||||
configurator.AddCommand<HorseCommand>("horse");
|
||||
configurator.AddCommand<GiraffeCommand>("giraffe");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Hidden_Commands")]
|
||||
public Task Should_Skip_Hidden_Commands()
|
||||
[Fact]
|
||||
[Expectation("Hidden_Commands")]
|
||||
public Task Should_Skip_Hidden_Commands()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<DogCommand>("dog");
|
||||
configurator.AddCommand<HorseCommand>("horse");
|
||||
configurator.AddCommand<GiraffeCommand>("giraffe")
|
||||
.WithExample(new[] { "giraffe", "123" })
|
||||
.IsHidden();
|
||||
});
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<DogCommand>("dog");
|
||||
configurator.AddCommand<HorseCommand>("horse");
|
||||
configurator.AddCommand<GiraffeCommand>("giraffe")
|
||||
.WithExample(new[] { "giraffe", "123" })
|
||||
.IsHidden();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Command")]
|
||||
public Task Should_Output_Command_Correctly()
|
||||
[Fact]
|
||||
[Expectation("Command")]
|
||||
public Task Should_Output_Command_Correctly()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddBranch<CatSettings>("cat", animal =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddBranch<CatSettings>("cat", animal =>
|
||||
{
|
||||
animal.SetDescription("Contains settings for a cat.");
|
||||
animal.AddCommand<LionCommand>("lion");
|
||||
});
|
||||
animal.SetDescription("Contains settings for a cat.");
|
||||
animal.AddCommand<LionCommand>("lion");
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("cat", "--help");
|
||||
// When
|
||||
var result = fixture.Run("cat", "--help");
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Leaf")]
|
||||
public Task Should_Output_Leaf_Correctly()
|
||||
[Fact]
|
||||
[Expectation("Leaf")]
|
||||
public Task Should_Output_Leaf_Correctly()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddBranch<CatSettings>("cat", animal =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddBranch<CatSettings>("cat", animal =>
|
||||
{
|
||||
animal.SetDescription("Contains settings for a cat.");
|
||||
animal.AddCommand<LionCommand>("lion");
|
||||
});
|
||||
animal.SetDescription("Contains settings for a cat.");
|
||||
animal.AddCommand<LionCommand>("lion");
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("cat", "lion", "--help");
|
||||
// When
|
||||
var result = fixture.Run("cat", "lion", "--help");
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Default")]
|
||||
public Task Should_Output_Default_Command_Correctly()
|
||||
[Fact]
|
||||
[Expectation("Default")]
|
||||
public Task Should_Output_Default_Command_Correctly()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.SetDefaultCommand<LionCommand>();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.SetDefaultCommand<LionCommand>();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
});
|
||||
configurator.SetApplicationName("myapp");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("RootExamples")]
|
||||
public Task Should_Output_Root_Examples_Defined_On_Root()
|
||||
[Fact]
|
||||
[Expectation("RootExamples")]
|
||||
public Task Should_Output_Root_Examples_Defined_On_Root()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddExample(new[] { "dog", "--name", "Rufus", "--age", "12", "--good-boy" });
|
||||
configurator.AddExample(new[] { "horse", "--name", "Brutus" });
|
||||
configurator.AddCommand<DogCommand>("dog");
|
||||
configurator.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddExample(new[] { "dog", "--name", "Rufus", "--age", "12", "--good-boy" });
|
||||
configurator.AddExample(new[] { "horse", "--name", "Brutus" });
|
||||
configurator.AddCommand<DogCommand>("dog");
|
||||
configurator.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("RootExamples_Children")]
|
||||
public Task Should_Output_Root_Examples_Defined_On_Direct_Children_If_Root_Have_No_Examples()
|
||||
[Fact]
|
||||
[Expectation("RootExamples_Children")]
|
||||
public Task Should_Output_Root_Examples_Defined_On_Direct_Children_If_Root_Have_No_Examples()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<DogCommand>("dog")
|
||||
.WithExample(new[] { "dog", "--name", "Rufus", "--age", "12", "--good-boy" });
|
||||
configurator.AddCommand<HorseCommand>("horse")
|
||||
.WithExample(new[] { "horse", "--name", "Brutus" });
|
||||
});
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<DogCommand>("dog")
|
||||
.WithExample(new[] { "dog", "--name", "Rufus", "--age", "12", "--good-boy" });
|
||||
configurator.AddCommand<HorseCommand>("horse")
|
||||
.WithExample(new[] { "horse", "--name", "Brutus" });
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("RootExamples_Leafs")]
|
||||
public Task Should_Output_Root_Examples_Defined_On_Leaves_If_No_Other_Examples_Are_Found()
|
||||
[Fact]
|
||||
[Expectation("RootExamples_Leafs")]
|
||||
public Task Should_Output_Root_Examples_Defined_On_Leaves_If_No_Other_Examples_Are_Found()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
animal.SetDescription("The animal command.");
|
||||
animal.AddCommand<DogCommand>("dog")
|
||||
.WithExample(new[] { "animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy" });
|
||||
animal.AddCommand<HorseCommand>("horse")
|
||||
.WithExample(new[] { "animal", "horse", "--name", "Brutus" });
|
||||
});
|
||||
animal.SetDescription("The animal command.");
|
||||
animal.AddCommand<DogCommand>("dog")
|
||||
.WithExample(new[] { "animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy" });
|
||||
animal.AddCommand<HorseCommand>("horse")
|
||||
.WithExample(new[] { "animal", "horse", "--name", "Brutus" });
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("CommandExamples")]
|
||||
public Task Should_Only_Output_Command_Examples_Defined_On_Command()
|
||||
[Fact]
|
||||
[Expectation("CommandExamples")]
|
||||
public Task Should_Only_Output_Command_Examples_Defined_On_Command()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
animal.SetDescription("The animal command.");
|
||||
animal.AddExample(new[] { "animal", "--help" });
|
||||
animal.SetDescription("The animal command.");
|
||||
animal.AddExample(new[] { "animal", "--help" });
|
||||
|
||||
animal.AddCommand<DogCommand>("dog")
|
||||
.WithExample(new[] { "animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy" });
|
||||
animal.AddCommand<HorseCommand>("horse")
|
||||
.WithExample(new[] { "animal", "horse", "--name", "Brutus" });
|
||||
});
|
||||
animal.AddCommand<DogCommand>("dog")
|
||||
.WithExample(new[] { "animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy" });
|
||||
animal.AddCommand<HorseCommand>("horse")
|
||||
.WithExample(new[] { "animal", "horse", "--name", "Brutus" });
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("animal", "--help");
|
||||
// When
|
||||
var result = fixture.Run("animal", "--help");
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("DefaultExamples")]
|
||||
public Task Should_Output_Root_Examples_If_Default_Command_Is_Specified()
|
||||
[Fact]
|
||||
[Expectation("DefaultExamples")]
|
||||
public Task Should_Output_Root_Examples_If_Default_Command_Is_Specified()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.SetDefaultCommand<LionCommand>();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.SetDefaultCommand<LionCommand>();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddExample(new[] { "12", "-c", "3" });
|
||||
});
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddExample(new[] { "12", "-c", "3" });
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("NoDescription")]
|
||||
public Task Should_Not_Show_Truncated_Command_Table_If_Commands_Are_Missing_Description()
|
||||
[Fact]
|
||||
[Expectation("NoDescription")]
|
||||
public Task Should_Not_Show_Truncated_Command_Table_If_Commands_Are_Missing_Description()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<NoDescriptionCommand>("bar");
|
||||
});
|
||||
configurator.SetApplicationName("myapp");
|
||||
configurator.AddCommand<NoDescriptionCommand>("bar");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("ArgumentOrder")]
|
||||
public Task Should_List_Arguments_In_Correct_Order()
|
||||
[Fact]
|
||||
[Expectation("ArgumentOrder")]
|
||||
public Task Should_List_Arguments_In_Correct_Order()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.SetDefaultCommand<GenericCommand<ArgumentOrderSettings>>();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.SetDefaultCommand<GenericCommand<ArgumentOrderSettings>>();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
});
|
||||
configurator.SetApplicationName("myapp");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Hidden_Command_Options")]
|
||||
public Task Should_Not_Show_Hidden_Command_Options()
|
||||
[Fact]
|
||||
[Expectation("Hidden_Command_Options")]
|
||||
public Task Should_Not_Show_Hidden_Command_Options()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.SetDefaultCommand<GenericCommand<HiddenOptionSettings>>();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.SetDefaultCommand<GenericCommand<HiddenOptionSettings>>();
|
||||
fixture.Configure(configurator =>
|
||||
{
|
||||
configurator.SetApplicationName("myapp");
|
||||
});
|
||||
configurator.SetApplicationName("myapp");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
// When
|
||||
var result = fixture.Run("--help");
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,97 +1,90 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
public sealed class Injection
|
||||
{
|
||||
public sealed class Injection
|
||||
public sealed class FakeDependency
|
||||
{
|
||||
public sealed class FakeDependency
|
||||
}
|
||||
|
||||
public sealed class InjectSettings : CommandSettings
|
||||
{
|
||||
public FakeDependency Fake { get; set; }
|
||||
|
||||
[CommandOption("--name <NAME>")]
|
||||
public string Name { get; }
|
||||
|
||||
[CommandOption("--age <AGE>")]
|
||||
public int Age { get; set; }
|
||||
|
||||
public InjectSettings(FakeDependency fake, string name)
|
||||
{
|
||||
}
|
||||
|
||||
public sealed class InjectSettings : CommandSettings
|
||||
{
|
||||
public FakeDependency Fake { get; set; }
|
||||
|
||||
[CommandOption("--name <NAME>")]
|
||||
public string Name { get; }
|
||||
|
||||
[CommandOption("--age <AGE>")]
|
||||
public int Age { get; set; }
|
||||
|
||||
public InjectSettings(FakeDependency fake, string name)
|
||||
{
|
||||
Fake = fake;
|
||||
Name = "Hello " + name;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Inject_Parameters()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
var dependency = new FakeDependency();
|
||||
|
||||
app.SetDefaultCommand<GenericCommand<InjectSettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.Settings.Registrar.RegisterInstance(dependency);
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--name", "foo",
|
||||
"--age", "35",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<InjectSettings>().And(injected =>
|
||||
{
|
||||
injected.ShouldNotBeNull();
|
||||
injected.Fake.ShouldBeSameAs(dependency);
|
||||
injected.Name.ShouldBe("Hello foo");
|
||||
injected.Age.ShouldBe(35);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Inject_Dependency_Using_A_Given_Registrar()
|
||||
{
|
||||
// Given
|
||||
var dependency = new FakeDependency();
|
||||
var registrar = new FakeTypeRegistrar { TypeResolverFactory = FakeTypeResolver.Factory };
|
||||
registrar.RegisterInstance(typeof(FakeDependency), dependency);
|
||||
var app = new CommandAppTester(registrar);
|
||||
|
||||
app.SetDefaultCommand<GenericCommand<InjectSettings>>();
|
||||
app.Configure(config => config.PropagateExceptions());
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--name", "foo",
|
||||
"--age", "35",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<InjectSettings>().And(injected =>
|
||||
{
|
||||
injected.ShouldNotBeNull();
|
||||
injected.Fake.ShouldBeSameAs(dependency);
|
||||
injected.Name.ShouldBe("Hello foo");
|
||||
injected.Age.ShouldBe(35);
|
||||
});
|
||||
Fake = fake;
|
||||
Name = "Hello " + name;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Inject_Parameters()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
var dependency = new FakeDependency();
|
||||
|
||||
app.SetDefaultCommand<GenericCommand<InjectSettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.Settings.Registrar.RegisterInstance(dependency);
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--name", "foo",
|
||||
"--age", "35",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<InjectSettings>().And(injected =>
|
||||
{
|
||||
injected.ShouldNotBeNull();
|
||||
injected.Fake.ShouldBeSameAs(dependency);
|
||||
injected.Name.ShouldBe("Hello foo");
|
||||
injected.Age.ShouldBe(35);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Inject_Dependency_Using_A_Given_Registrar()
|
||||
{
|
||||
// Given
|
||||
var dependency = new FakeDependency();
|
||||
var registrar = new FakeTypeRegistrar { TypeResolverFactory = FakeTypeResolver.Factory };
|
||||
registrar.RegisterInstance(typeof(FakeDependency), dependency);
|
||||
var app = new CommandAppTester(registrar);
|
||||
|
||||
app.SetDefaultCommand<GenericCommand<InjectSettings>>();
|
||||
app.Configure(config => config.PropagateExceptions());
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--name", "foo",
|
||||
"--age", "35",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<InjectSettings>().And(injected =>
|
||||
{
|
||||
injected.ShouldNotBeNull();
|
||||
injected.Fake.ShouldBeSameAs(dependency);
|
||||
injected.Name.ShouldBe("Hello foo");
|
||||
injected.Age.ShouldBe(35);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,327 +1,316 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
public sealed class Pairs
|
||||
{
|
||||
public sealed class Pairs
|
||||
public sealed class AmbiguousSettings : CommandSettings
|
||||
{
|
||||
public sealed class AmbiguousSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--var <VALUE>")]
|
||||
[PairDeconstructor(typeof(StringIntDeconstructor))]
|
||||
[TypeConverter(typeof(CatAgilityConverter))]
|
||||
public ILookup<string, string> Values { get; set; }
|
||||
}
|
||||
[CommandOption("--var <VALUE>")]
|
||||
[PairDeconstructor(typeof(StringIntDeconstructor))]
|
||||
[TypeConverter(typeof(CatAgilityConverter))]
|
||||
public ILookup<string, string> Values { get; set; }
|
||||
}
|
||||
|
||||
public sealed class NotDeconstructableSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--var <VALUE>")]
|
||||
[PairDeconstructor(typeof(StringIntDeconstructor))]
|
||||
public string Values { get; set; }
|
||||
}
|
||||
public sealed class NotDeconstructableSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--var <VALUE>")]
|
||||
[PairDeconstructor(typeof(StringIntDeconstructor))]
|
||||
public string Values { get; set; }
|
||||
}
|
||||
|
||||
public sealed class DefaultPairDeconstructorSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--var <VALUE>")]
|
||||
public IDictionary<string, int> Values { get; set; }
|
||||
}
|
||||
public sealed class DefaultPairDeconstructorSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--var <VALUE>")]
|
||||
public IDictionary<string, int> Values { get; set; }
|
||||
}
|
||||
|
||||
public sealed class DefaultPairDeconstructorEnumValueSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--var <VALUE>")]
|
||||
public IDictionary<string, DayOfWeek> Values { get; set; }
|
||||
}
|
||||
public sealed class DefaultPairDeconstructorEnumValueSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--var <VALUE>")]
|
||||
public IDictionary<string, DayOfWeek> Values { get; set; }
|
||||
}
|
||||
|
||||
public sealed class LookupSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--var <VALUE>")]
|
||||
[PairDeconstructor(typeof(StringIntDeconstructor))]
|
||||
public ILookup<string, string> Values { get; set; }
|
||||
}
|
||||
public sealed class LookupSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--var <VALUE>")]
|
||||
[PairDeconstructor(typeof(StringIntDeconstructor))]
|
||||
public ILookup<string, string> Values { get; set; }
|
||||
}
|
||||
|
||||
public sealed class DictionarySettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--var <VALUE>")]
|
||||
[PairDeconstructor(typeof(StringIntDeconstructor))]
|
||||
public IDictionary<string, string> Values { get; set; }
|
||||
}
|
||||
public sealed class DictionarySettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--var <VALUE>")]
|
||||
[PairDeconstructor(typeof(StringIntDeconstructor))]
|
||||
public IDictionary<string, string> Values { get; set; }
|
||||
}
|
||||
|
||||
public sealed class ReadOnlyDictionarySettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--var <VALUE>")]
|
||||
[PairDeconstructor(typeof(StringIntDeconstructor))]
|
||||
public IReadOnlyDictionary<string, string> Values { get; set; }
|
||||
}
|
||||
public sealed class ReadOnlyDictionarySettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--var <VALUE>")]
|
||||
[PairDeconstructor(typeof(StringIntDeconstructor))]
|
||||
public IReadOnlyDictionary<string, string> Values { get; set; }
|
||||
}
|
||||
|
||||
public sealed class StringIntDeconstructor : PairDeconstructor<string, string>
|
||||
public sealed class StringIntDeconstructor : PairDeconstructor<string, string>
|
||||
{
|
||||
protected override (string Key, string Value) Deconstruct(string value)
|
||||
{
|
||||
protected override (string Key, string Value) Deconstruct(string value)
|
||||
if (value == null)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
var parts = value.Split(new[] { '=' });
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
throw new InvalidOperationException("Could not parse pair");
|
||||
}
|
||||
|
||||
return (parts[0], parts[1]);
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Option_Has_Pair_Deconstructor_And_Type_Converter()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp<GenericCommand<AmbiguousSettings>>();
|
||||
app.Configure(config =>
|
||||
var parts = value.Split(new[] { '=' });
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
throw new InvalidOperationException("Could not parse pair");
|
||||
}
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[]
|
||||
{
|
||||
"--var", "foo=bar",
|
||||
"--var", "foo=qux",
|
||||
}));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandConfigurationException>().And(ex =>
|
||||
{
|
||||
ex.Message.ShouldBe("The option 'var' is both marked as pair deconstructable and convertable.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Option_Has_Pair_Deconstructor_But_Type_Is_Not_Deconstructable()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp<GenericCommand<NotDeconstructableSettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[]
|
||||
{
|
||||
"--var", "foo=bar",
|
||||
"--var", "foo=qux",
|
||||
}));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandConfigurationException>().And(ex =>
|
||||
{
|
||||
ex.Message.ShouldBe("The option 'var' is marked as pair deconstructable, but the underlying type does not support that.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Map_Pairs_To_Pair_Deconstructable_Collection_Using_Default_Deconstructort()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<DefaultPairDeconstructorSettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", "foo=1",
|
||||
"--var", "foo=3",
|
||||
"--var", "bar=4",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DefaultPairDeconstructorSettings>().And(pair =>
|
||||
{
|
||||
pair.Values.ShouldNotBeNull();
|
||||
pair.Values.Count.ShouldBe(2);
|
||||
pair.Values["foo"].ShouldBe(3);
|
||||
pair.Values["bar"].ShouldBe(4);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Map_Pairs_With_Enum_Value_To_Pair_Deconstructable_Collection_Using_Default_Deconstructor()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<DefaultPairDeconstructorEnumValueSettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", "foo=Monday",
|
||||
"--var", "bar=Tuesday",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DefaultPairDeconstructorEnumValueSettings>().And(pair =>
|
||||
{
|
||||
pair.Values.ShouldNotBeNull();
|
||||
pair.Values.Count.ShouldBe(2);
|
||||
pair.Values["foo"].ShouldBe(DayOfWeek.Monday);
|
||||
pair.Values["bar"].ShouldBe(DayOfWeek.Tuesday);
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("foo=1=2", "Error: The value 'foo=1=2' is not in a correct format")]
|
||||
[InlineData("foo=1=2=3", "Error: The value 'foo=1=2=3' is not in a correct format")]
|
||||
public void Should_Throw_If_Value_Is_Not_In_A_Valid_Format_Using_Default_Deconstructor(
|
||||
string input, string expected)
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<DefaultPairDeconstructorSettings>>();
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", input,
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(-1);
|
||||
result.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Map_Lookup_Values()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<LookupSettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", "foo=bar",
|
||||
"--var", "foo=qux",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<LookupSettings>().And(pair =>
|
||||
{
|
||||
pair.Values.ShouldNotBeNull();
|
||||
pair.Values.Count.ShouldBe(1);
|
||||
pair.Values["foo"].ToList().Count.ShouldBe(2);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Map_Dictionary_Values()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<DictionarySettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", "foo=bar",
|
||||
"--var", "baz=qux",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DictionarySettings>().And(pair =>
|
||||
{
|
||||
pair.Values.ShouldNotBeNull();
|
||||
pair.Values.Count.ShouldBe(2);
|
||||
pair.Values["foo"].ShouldBe("bar");
|
||||
pair.Values["baz"].ShouldBe("qux");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Map_Latest_Value_Of_Same_Key_When_Mapping_To_Dictionary()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<DictionarySettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", "foo=bar",
|
||||
"--var", "foo=qux",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DictionarySettings>().And(pair =>
|
||||
{
|
||||
pair.Values.ShouldNotBeNull();
|
||||
pair.Values.Count.ShouldBe(1);
|
||||
pair.Values["foo"].ShouldBe("qux");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Map_ReadOnly_Dictionary_Values()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<ReadOnlyDictionarySettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", "foo=bar",
|
||||
"--var", "baz=qux",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<ReadOnlyDictionarySettings>().And(pair =>
|
||||
{
|
||||
pair.Values.ShouldNotBeNull();
|
||||
pair.Values.Count.ShouldBe(2);
|
||||
pair.Values["foo"].ShouldBe("bar");
|
||||
pair.Values["baz"].ShouldBe("qux");
|
||||
});
|
||||
return (parts[0], parts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Option_Has_Pair_Deconstructor_And_Type_Converter()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp<GenericCommand<AmbiguousSettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[]
|
||||
{
|
||||
"--var", "foo=bar",
|
||||
"--var", "foo=qux",
|
||||
}));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandConfigurationException>().And(ex =>
|
||||
{
|
||||
ex.Message.ShouldBe("The option 'var' is both marked as pair deconstructable and convertable.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Option_Has_Pair_Deconstructor_But_Type_Is_Not_Deconstructable()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp<GenericCommand<NotDeconstructableSettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[]
|
||||
{
|
||||
"--var", "foo=bar",
|
||||
"--var", "foo=qux",
|
||||
}));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandConfigurationException>().And(ex =>
|
||||
{
|
||||
ex.Message.ShouldBe("The option 'var' is marked as pair deconstructable, but the underlying type does not support that.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Map_Pairs_To_Pair_Deconstructable_Collection_Using_Default_Deconstructort()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<DefaultPairDeconstructorSettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", "foo=1",
|
||||
"--var", "foo=3",
|
||||
"--var", "bar=4",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DefaultPairDeconstructorSettings>().And(pair =>
|
||||
{
|
||||
pair.Values.ShouldNotBeNull();
|
||||
pair.Values.Count.ShouldBe(2);
|
||||
pair.Values["foo"].ShouldBe(3);
|
||||
pair.Values["bar"].ShouldBe(4);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Map_Pairs_With_Enum_Value_To_Pair_Deconstructable_Collection_Using_Default_Deconstructor()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<DefaultPairDeconstructorEnumValueSettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", "foo=Monday",
|
||||
"--var", "bar=Tuesday",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DefaultPairDeconstructorEnumValueSettings>().And(pair =>
|
||||
{
|
||||
pair.Values.ShouldNotBeNull();
|
||||
pair.Values.Count.ShouldBe(2);
|
||||
pair.Values["foo"].ShouldBe(DayOfWeek.Monday);
|
||||
pair.Values["bar"].ShouldBe(DayOfWeek.Tuesday);
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("foo=1=2", "Error: The value 'foo=1=2' is not in a correct format")]
|
||||
[InlineData("foo=1=2=3", "Error: The value 'foo=1=2=3' is not in a correct format")]
|
||||
public void Should_Throw_If_Value_Is_Not_In_A_Valid_Format_Using_Default_Deconstructor(
|
||||
string input, string expected)
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<DefaultPairDeconstructorSettings>>();
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", input,
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(-1);
|
||||
result.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Map_Lookup_Values()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<LookupSettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", "foo=bar",
|
||||
"--var", "foo=qux",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<LookupSettings>().And(pair =>
|
||||
{
|
||||
pair.Values.ShouldNotBeNull();
|
||||
pair.Values.Count.ShouldBe(1);
|
||||
pair.Values["foo"].ToList().Count.ShouldBe(2);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Map_Dictionary_Values()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<DictionarySettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", "foo=bar",
|
||||
"--var", "baz=qux",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DictionarySettings>().And(pair =>
|
||||
{
|
||||
pair.Values.ShouldNotBeNull();
|
||||
pair.Values.Count.ShouldBe(2);
|
||||
pair.Values["foo"].ShouldBe("bar");
|
||||
pair.Values["baz"].ShouldBe("qux");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Map_Latest_Value_Of_Same_Key_When_Mapping_To_Dictionary()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<DictionarySettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", "foo=bar",
|
||||
"--var", "foo=qux",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DictionarySettings>().And(pair =>
|
||||
{
|
||||
pair.Values.ShouldNotBeNull();
|
||||
pair.Values.Count.ShouldBe(1);
|
||||
pair.Values["foo"].ShouldBe("qux");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Map_ReadOnly_Dictionary_Values()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<ReadOnlyDictionarySettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"--var", "foo=bar",
|
||||
"--var", "baz=qux",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<ReadOnlyDictionarySettings>().And(pair =>
|
||||
{
|
||||
pair.Values.ShouldNotBeNull();
|
||||
pair.Values.Count.ShouldBe(2);
|
||||
pair.Values["foo"].ShouldBe("bar");
|
||||
pair.Values["baz"].ShouldBe("qux");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,77 +1,70 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
public sealed class Remaining
|
||||
{
|
||||
public sealed class Remaining
|
||||
[Fact]
|
||||
public void Should_Register_Remaining_Parsed_Arguments_With_Context()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Register_Remaining_Parsed_Arguments_With_Context()
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
config.PropagateExceptions();
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
});
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"animal", "4", "dog", "12", "--",
|
||||
"--foo", "bar", "--foo", "baz",
|
||||
"-bar", "\"baz\"", "qux",
|
||||
"foo bar baz qux",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.Context.Remaining.Parsed.Count.ShouldBe(4);
|
||||
result.Context.ShouldHaveRemainingArgument("foo", values: new[] { "bar", "baz" });
|
||||
result.Context.ShouldHaveRemainingArgument("b", values: new[] { (string)null });
|
||||
result.Context.ShouldHaveRemainingArgument("a", values: new[] { (string)null });
|
||||
result.Context.ShouldHaveRemainingArgument("r", values: new[] { (string)null });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Register_Remaining_Raw_Arguments_With_Context()
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
});
|
||||
});
|
||||
"animal", "4", "dog", "12", "--",
|
||||
"--foo", "bar", "--foo", "baz",
|
||||
"-bar", "\"baz\"", "qux",
|
||||
"foo bar baz qux",
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"animal", "4", "dog", "12", "--",
|
||||
"--foo", "bar", "-bar", "\"baz\"", "qux",
|
||||
"foo bar baz qux",
|
||||
});
|
||||
// Then
|
||||
result.Context.Remaining.Parsed.Count.ShouldBe(4);
|
||||
result.Context.ShouldHaveRemainingArgument("foo", values: new[] { "bar", "baz" });
|
||||
result.Context.ShouldHaveRemainingArgument("b", values: new[] { (string)null });
|
||||
result.Context.ShouldHaveRemainingArgument("a", values: new[] { (string)null });
|
||||
result.Context.ShouldHaveRemainingArgument("r", values: new[] { (string)null });
|
||||
}
|
||||
|
||||
// Then
|
||||
result.Context.Remaining.Raw.Count.ShouldBe(6);
|
||||
result.Context.Remaining.Raw[0].ShouldBe("--foo");
|
||||
result.Context.Remaining.Raw[1].ShouldBe("bar");
|
||||
result.Context.Remaining.Raw[2].ShouldBe("-bar");
|
||||
result.Context.Remaining.Raw[3].ShouldBe("baz");
|
||||
result.Context.Remaining.Raw[4].ShouldBe("qux");
|
||||
result.Context.Remaining.Raw[5].ShouldBe("foo bar baz qux");
|
||||
}
|
||||
[Fact]
|
||||
public void Should_Register_Remaining_Raw_Arguments_With_Context()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"animal", "4", "dog", "12", "--",
|
||||
"--foo", "bar", "-bar", "\"baz\"", "qux",
|
||||
"foo bar baz qux",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.Context.Remaining.Raw.Count.ShouldBe(6);
|
||||
result.Context.Remaining.Raw[0].ShouldBe("--foo");
|
||||
result.Context.Remaining.Raw[1].ShouldBe("bar");
|
||||
result.Context.Remaining.Raw[2].ShouldBe("-bar");
|
||||
result.Context.Remaining.Raw[3].ShouldBe("baz");
|
||||
result.Context.Remaining.Raw[4].ShouldBe("qux");
|
||||
result.Context.Remaining.Raw[5].ShouldBe("foo bar baz qux");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,118 +1,111 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandApptests
|
||||
{
|
||||
public sealed partial class CommandApptests
|
||||
[Fact]
|
||||
public void Should_Treat_Commands_As_Case_Sensitive_If_Specified()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Treat_Commands_As_Case_Sensitive_If_Specified()
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.UseStrictParsing();
|
||||
config.PropagateExceptions();
|
||||
config.CaseSensitivity(CaseSensitivity.Commands);
|
||||
config.AddCommand<GenericCommand<StringOptionSettings>>("command");
|
||||
});
|
||||
config.UseStrictParsing();
|
||||
config.PropagateExceptions();
|
||||
config.CaseSensitivity(CaseSensitivity.Commands);
|
||||
config.AddCommand<GenericCommand<StringOptionSettings>>("command");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[]
|
||||
{
|
||||
"Command", "--foo", "bar",
|
||||
}));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.ShouldBeOfType<CommandParseException>().And(ex =>
|
||||
{
|
||||
ex.Message.ShouldBe("Unknown command 'Command'.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Treat_Long_Options_As_Case_Sensitive_If_Specified()
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[]
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.UseStrictParsing();
|
||||
config.PropagateExceptions();
|
||||
config.CaseSensitivity(CaseSensitivity.LongOptions);
|
||||
config.AddCommand<GenericCommand<StringOptionSettings>>("command");
|
||||
});
|
||||
"Command", "--foo", "bar",
|
||||
}));
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[]
|
||||
{
|
||||
"command", "--Foo", "bar",
|
||||
}));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.ShouldBeOfType<CommandParseException>().And(ex =>
|
||||
{
|
||||
ex.Message.ShouldBe("Unknown option 'Foo'.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Treat_Short_Options_As_Case_Sensitive()
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.ShouldBeOfType<CommandParseException>().And(ex =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.UseStrictParsing();
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<StringOptionSettings>>("command");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[]
|
||||
{
|
||||
"command", "-F", "bar",
|
||||
}));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.ShouldBeOfType<CommandParseException>().And(ex =>
|
||||
{
|
||||
ex.Message.ShouldBe("Unknown option 'F'.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Suppress_Case_Sensitivity_If_Specified()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.UseStrictParsing();
|
||||
config.PropagateExceptions();
|
||||
config.CaseSensitivity(CaseSensitivity.None);
|
||||
config.AddCommand<GenericCommand<StringOptionSettings>>("command");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"Command", "--Foo", "bar",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<StringOptionSettings>().And(vec =>
|
||||
{
|
||||
vec.Foo.ShouldBe("bar");
|
||||
});
|
||||
}
|
||||
ex.Message.ShouldBe("Unknown command 'Command'.");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Treat_Long_Options_As_Case_Sensitive_If_Specified()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.UseStrictParsing();
|
||||
config.PropagateExceptions();
|
||||
config.CaseSensitivity(CaseSensitivity.LongOptions);
|
||||
config.AddCommand<GenericCommand<StringOptionSettings>>("command");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[]
|
||||
{
|
||||
"command", "--Foo", "bar",
|
||||
}));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.ShouldBeOfType<CommandParseException>().And(ex =>
|
||||
{
|
||||
ex.Message.ShouldBe("Unknown option 'Foo'.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Treat_Short_Options_As_Case_Sensitive()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.UseStrictParsing();
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<StringOptionSettings>>("command");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[]
|
||||
{
|
||||
"command", "-F", "bar",
|
||||
}));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.ShouldBeOfType<CommandParseException>().And(ex =>
|
||||
{
|
||||
ex.Message.ShouldBe("Unknown option 'F'.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Suppress_Case_Sensitivity_If_Specified()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.UseStrictParsing();
|
||||
config.PropagateExceptions();
|
||||
config.CaseSensitivity(CaseSensitivity.None);
|
||||
config.AddCommand<GenericCommand<StringOptionSettings>>("command");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"Command", "--Foo", "bar",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<StringOptionSettings>().And(vec =>
|
||||
{
|
||||
vec.Foo.ShouldBe("bar");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +1,21 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
[Fact]
|
||||
public void Should_Apply_Case_Sensitivity_For_Everything_By_Default()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Apply_Case_Sensitivity_For_Everything_By_Default()
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
|
||||
// When
|
||||
var defaultSensitivity = CaseSensitivity.None;
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
defaultSensitivity = config.Settings.CaseSensitivity;
|
||||
});
|
||||
|
||||
// When
|
||||
var defaultSensitivity = CaseSensitivity.None;
|
||||
app.Configure(config =>
|
||||
{
|
||||
defaultSensitivity = config.Settings.CaseSensitivity;
|
||||
});
|
||||
|
||||
// Then
|
||||
defaultSensitivity.ShouldBe(CaseSensitivity.All);
|
||||
}
|
||||
// Then
|
||||
defaultSensitivity.ShouldBe(CaseSensitivity.All);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +1,33 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
public sealed class TypeConverters
|
||||
{
|
||||
public sealed class TypeConverters
|
||||
[Fact]
|
||||
public void Should_Bind_Using_Custom_Type_Converter_If_Specified()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Bind_Using_Custom_Type_Converter_If_Specified()
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<CatCommand>("cat");
|
||||
});
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<CatCommand>("cat");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"cat", "--name", "Tiger",
|
||||
"--agility", "FOOBAR",
|
||||
});
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"cat", "--name", "Tiger",
|
||||
"--agility", "FOOBAR",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<CatSettings>().And(cat =>
|
||||
{
|
||||
cat.Agility.ShouldBe(6);
|
||||
});
|
||||
}
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<CatSettings>().And(cat =>
|
||||
{
|
||||
cat.Agility.ShouldBe(6);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,299 +1,291 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Cli.Unsafe;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
public sealed class SafetyOff
|
||||
{
|
||||
public sealed class SafetyOff
|
||||
[Fact]
|
||||
public void Can_Mix_Safe_And_Unsafe_Configurators()
|
||||
{
|
||||
[Fact]
|
||||
public void Can_Mix_Safe_And_Unsafe_Configurators()
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.PropagateExceptions();
|
||||
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
animal.SafetyOff().AddBranch("mammal", typeof(MammalSettings), mammal =>
|
||||
{
|
||||
animal.SafetyOff().AddBranch("mammal", typeof(MammalSettings), mammal =>
|
||||
{
|
||||
mammal.AddCommand("dog", typeof(DogCommand));
|
||||
mammal.AddCommand("horse", typeof(HorseCommand));
|
||||
});
|
||||
mammal.AddCommand("dog", typeof(DogCommand));
|
||||
mammal.AddCommand("horse", typeof(HorseCommand));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"animal", "--alive", "mammal", "--name",
|
||||
"Rufus", "dog", "12", "--good-boy",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
|
||||
{
|
||||
dog.Age.ShouldBe(12);
|
||||
dog.GoodBoy.ShouldBe(true);
|
||||
dog.Name.ShouldBe("Rufus");
|
||||
dog.IsAlive.ShouldBe(true);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Can_Turn_Safety_On_After_Turning_It_Off_For_Branch()
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
"animal", "--alive", "mammal", "--name",
|
||||
"Rufus", "dog", "12", "--good-boy",
|
||||
});
|
||||
|
||||
config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal =>
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
|
||||
{
|
||||
dog.Age.ShouldBe(12);
|
||||
dog.GoodBoy.ShouldBe(true);
|
||||
dog.Name.ShouldBe("Rufus");
|
||||
dog.IsAlive.ShouldBe(true);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Can_Turn_Safety_On_After_Turning_It_Off_For_Branch()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
|
||||
config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal =>
|
||||
{
|
||||
animal.SafetyOn<AnimalSettings>()
|
||||
.AddBranch<MammalSettings>("mammal", mammal =>
|
||||
{
|
||||
animal.SafetyOn<AnimalSettings>()
|
||||
.AddBranch<MammalSettings>("mammal", mammal =>
|
||||
{
|
||||
mammal.SafetyOff().AddCommand("dog", typeof(DogCommand));
|
||||
mammal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
mammal.SafetyOff().AddCommand("dog", typeof(DogCommand));
|
||||
mammal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"animal", "--alive", "mammal", "--name",
|
||||
"Rufus", "dog", "12", "--good-boy",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
|
||||
{
|
||||
dog.Age.ShouldBe(12);
|
||||
dog.GoodBoy.ShouldBe(true);
|
||||
dog.Name.ShouldBe("Rufus");
|
||||
dog.IsAlive.ShouldBe(true);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Trying_To_Convert_Unsafe_Branch_Configurator_To_Safe_Version_With_Wrong_Type()
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
"animal", "--alive", "mammal", "--name",
|
||||
"Rufus", "dog", "12", "--good-boy",
|
||||
});
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
|
||||
config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal =>
|
||||
{
|
||||
animal.SafetyOn<MammalSettings>().AddCommand<DogCommand>("dog");
|
||||
});
|
||||
}));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandConfigurationException>();
|
||||
result.Message.ShouldBe("Configurator cannot be converted to a safe configurator of type 'MammalSettings'.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Pass_Case_1()
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
dog.Age.ShouldBe(12);
|
||||
dog.GoodBoy.ShouldBe(true);
|
||||
dog.Name.ShouldBe("Rufus");
|
||||
dog.IsAlive.ShouldBe(true);
|
||||
});
|
||||
}
|
||||
|
||||
config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal =>
|
||||
[Fact]
|
||||
public void Should_Throw_If_Trying_To_Convert_Unsafe_Branch_Configurator_To_Safe_Version_With_Wrong_Type()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
|
||||
config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal =>
|
||||
{
|
||||
animal.SafetyOn<MammalSettings>().AddCommand<DogCommand>("dog");
|
||||
});
|
||||
}));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandConfigurationException>();
|
||||
result.Message.ShouldBe("Configurator cannot be converted to a safe configurator of type 'MammalSettings'.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Pass_Case_1()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
|
||||
config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal =>
|
||||
{
|
||||
animal.AddBranch("mammal", typeof(MammalSettings), mammal =>
|
||||
{
|
||||
animal.AddBranch("mammal", typeof(MammalSettings), mammal =>
|
||||
{
|
||||
mammal.AddCommand("dog", typeof(DogCommand));
|
||||
mammal.AddCommand("horse", typeof(HorseCommand));
|
||||
});
|
||||
mammal.AddCommand("dog", typeof(DogCommand));
|
||||
mammal.AddCommand("horse", typeof(HorseCommand));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"animal", "--alive", "mammal", "--name",
|
||||
"Rufus", "dog", "12", "--good-boy",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
|
||||
{
|
||||
dog.Age.ShouldBe(12);
|
||||
dog.GoodBoy.ShouldBe(true);
|
||||
dog.Name.ShouldBe("Rufus");
|
||||
dog.IsAlive.ShouldBe(true);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Pass_Case_2()
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.SafetyOff().AddCommand("dog", typeof(DogCommand));
|
||||
});
|
||||
"animal", "--alive", "mammal", "--name",
|
||||
"Rufus", "dog", "12", "--good-boy",
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"dog", "12", "4", "--good-boy",
|
||||
"--name", "Rufus", "--alive",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
|
||||
{
|
||||
dog.Legs.ShouldBe(12);
|
||||
dog.Age.ShouldBe(4);
|
||||
dog.GoodBoy.ShouldBe(true);
|
||||
dog.Name.ShouldBe("Rufus");
|
||||
dog.IsAlive.ShouldBe(true);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Pass_Case_3()
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal =>
|
||||
{
|
||||
animal.AddCommand("dog", typeof(DogCommand));
|
||||
animal.AddCommand("horse", typeof(HorseCommand));
|
||||
});
|
||||
});
|
||||
dog.Age.ShouldBe(12);
|
||||
dog.GoodBoy.ShouldBe(true);
|
||||
dog.Name.ShouldBe("Rufus");
|
||||
dog.IsAlive.ShouldBe(true);
|
||||
});
|
||||
}
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"animal", "dog", "12", "--good-boy",
|
||||
"--name", "Rufus",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
|
||||
{
|
||||
dog.Age.ShouldBe(12);
|
||||
dog.GoodBoy.ShouldBe(true);
|
||||
dog.Name.ShouldBe("Rufus");
|
||||
dog.IsAlive.ShouldBe(false);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Pass_Case_4()
|
||||
[Fact]
|
||||
public void Should_Pass_Case_2()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal =>
|
||||
{
|
||||
animal.AddCommand("dog", typeof(DogCommand));
|
||||
});
|
||||
});
|
||||
config.PropagateExceptions();
|
||||
config.SafetyOff().AddCommand("dog", typeof(DogCommand));
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"animal", "4", "dog", "12",
|
||||
"--good-boy", "--name", "Rufus",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
|
||||
{
|
||||
dog.Legs.ShouldBe(4);
|
||||
dog.Age.ShouldBe(12);
|
||||
dog.GoodBoy.ShouldBe(true);
|
||||
dog.IsAlive.ShouldBe(false);
|
||||
dog.Name.ShouldBe("Rufus");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Pass_Case_5()
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.SafetyOff().AddCommand("multi", typeof(OptionVectorCommand));
|
||||
});
|
||||
"dog", "12", "4", "--good-boy",
|
||||
"--name", "Rufus", "--alive",
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"multi", "--foo", "a", "--foo", "b", "--bar", "1", "--foo", "c", "--bar", "2",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<OptionVectorSettings>().And(vec =>
|
||||
{
|
||||
vec.Foo.Length.ShouldBe(3);
|
||||
vec.Foo.ShouldBe(new[] { "a", "b", "c" });
|
||||
vec.Bar.Length.ShouldBe(2);
|
||||
vec.Bar.ShouldBe(new[] { 1, 2 });
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Pass_Case_6()
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<ArgumentVectorSettings>>("multi");
|
||||
});
|
||||
dog.Legs.ShouldBe(12);
|
||||
dog.Age.ShouldBe(4);
|
||||
dog.GoodBoy.ShouldBe(true);
|
||||
dog.Name.ShouldBe("Rufus");
|
||||
dog.IsAlive.ShouldBe(true);
|
||||
});
|
||||
}
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
[Fact]
|
||||
public void Should_Pass_Case_3()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal =>
|
||||
{
|
||||
"multi", "a", "b", "c",
|
||||
animal.AddCommand("dog", typeof(DogCommand));
|
||||
animal.AddCommand("horse", typeof(HorseCommand));
|
||||
});
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<ArgumentVectorSettings>().And(vec =>
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"animal", "dog", "12", "--good-boy",
|
||||
"--name", "Rufus",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
|
||||
{
|
||||
dog.Age.ShouldBe(12);
|
||||
dog.GoodBoy.ShouldBe(true);
|
||||
dog.Name.ShouldBe("Rufus");
|
||||
dog.IsAlive.ShouldBe(false);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Pass_Case_4()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.SafetyOff().AddBranch("animal", typeof(AnimalSettings), animal =>
|
||||
{
|
||||
vec.Foo.Length.ShouldBe(3);
|
||||
vec.Foo.ShouldBe(new[] { "a", "b", "c" });
|
||||
animal.AddCommand("dog", typeof(DogCommand));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"animal", "4", "dog", "12",
|
||||
"--good-boy", "--name", "Rufus",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
|
||||
{
|
||||
dog.Legs.ShouldBe(4);
|
||||
dog.Age.ShouldBe(12);
|
||||
dog.GoodBoy.ShouldBe(true);
|
||||
dog.IsAlive.ShouldBe(false);
|
||||
dog.Name.ShouldBe("Rufus");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Pass_Case_5()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.SafetyOff().AddCommand("multi", typeof(OptionVectorCommand));
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"multi", "--foo", "a", "--foo", "b", "--bar", "1", "--foo", "c", "--bar", "2",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<OptionVectorSettings>().And(vec =>
|
||||
{
|
||||
vec.Foo.Length.ShouldBe(3);
|
||||
vec.Foo.ShouldBe(new[] { "a", "b", "c" });
|
||||
vec.Bar.Length.ShouldBe(2);
|
||||
vec.Bar.ShouldBe(new[] { 1, 2 });
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Pass_Case_6()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<ArgumentVectorSettings>>("multi");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"multi", "a", "b", "c",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<ArgumentVectorSettings>().And(vec =>
|
||||
{
|
||||
vec.Foo.Length.ShouldBe(3);
|
||||
vec.Foo.ShouldBe(new[] { "a", "b", "c" });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,88 +1,82 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
public sealed class Validation
|
||||
{
|
||||
public sealed class Validation
|
||||
[Fact]
|
||||
public void Should_Throw_If_Attribute_Validation_Fails()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Throw_If_Attribute_Validation_Fails()
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
config.PropagateExceptions();
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
animal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
animal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[] { "animal", "3", "dog", "7", "--name", "Rufus" }));
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[] { "animal", "3", "dog", "7", "--name", "Rufus" }));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandRuntimeException>().And(e =>
|
||||
{
|
||||
e.Message.ShouldBe("Animals must have an even number of legs.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Settings_Validation_Fails()
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandRuntimeException>().And(e =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
animal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
});
|
||||
e.Message.ShouldBe("Animals must have an even number of legs.");
|
||||
});
|
||||
}
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[] { "animal", "4", "dog", "7", "--name", "Tiger" }));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandRuntimeException>().And(e =>
|
||||
{
|
||||
e.Message.ShouldBe("Tiger is not a dog name!");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Command_Validation_Fails()
|
||||
[Fact]
|
||||
public void Should_Throw_If_Settings_Validation_Fails()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
config.PropagateExceptions();
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
animal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
animal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[] { "animal", "4", "dog", "101", "--name", "Rufus" }));
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[] { "animal", "4", "dog", "7", "--name", "Tiger" }));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandRuntimeException>().And(e =>
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandRuntimeException>().And(e =>
|
||||
{
|
||||
e.Message.ShouldBe("Tiger is not a dog name!");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Command_Validation_Fails()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
e.Message.ShouldBe("Dog is too old...");
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
animal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[] { "animal", "4", "dog", "101", "--name", "Rufus" }));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandRuntimeException>().And(e =>
|
||||
{
|
||||
e.Message.ShouldBe("Dog is too old...");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,97 +1,88 @@
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
public sealed class ValueProviders
|
||||
{
|
||||
public sealed class ValueProviders
|
||||
public sealed class ValueProviderSettings : CommandSettings
|
||||
{
|
||||
public sealed class ValueProviderSettings : CommandSettings
|
||||
[CommandOption("-f|--foo <VALUE>")]
|
||||
[IntegerValueProvider(32)]
|
||||
[TypeConverter(typeof(HexConverter))]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
public sealed class IntegerValueProvider : ParameterValueProviderAttribute
|
||||
{
|
||||
private readonly int _value;
|
||||
|
||||
public IntegerValueProvider(int value)
|
||||
{
|
||||
[CommandOption("-f|--foo <VALUE>")]
|
||||
[IntegerValueProvider(32)]
|
||||
[TypeConverter(typeof(HexConverter))]
|
||||
public string Foo { get; set; }
|
||||
_value = value;
|
||||
}
|
||||
|
||||
public sealed class IntegerValueProvider : ParameterValueProviderAttribute
|
||||
public override bool TryGetValue(CommandParameterContext context, out object result)
|
||||
{
|
||||
private readonly int _value;
|
||||
|
||||
public IntegerValueProvider(int value)
|
||||
if (context.Value == null)
|
||||
{
|
||||
_value = value;
|
||||
result = _value;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool TryGetValue(CommandParameterContext context, out object result)
|
||||
{
|
||||
if (context.Value == null)
|
||||
{
|
||||
result = _value;
|
||||
return true;
|
||||
}
|
||||
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HexConverter : TypeConverter
|
||||
{
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
if (value is int integer)
|
||||
{
|
||||
return integer.ToString("X");
|
||||
}
|
||||
|
||||
return value is string stringValue && int.TryParse(stringValue, out var intValue)
|
||||
? intValue.ToString("X")
|
||||
: base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Use_Provided_Value_If_No_Value_Was_Specified()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<ValueProviderSettings>>();
|
||||
app.Configure(config => config.PropagateExceptions());
|
||||
|
||||
// When
|
||||
var result = app.Run();
|
||||
|
||||
// Then
|
||||
result.Settings.ShouldBeOfType<ValueProviderSettings>().And(settings =>
|
||||
{
|
||||
settings.Foo.ShouldBe("20"); // 32 is 0x20
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Override_Value_If_Value_Was_Specified()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<ValueProviderSettings>>();
|
||||
app.Configure(config => config.PropagateExceptions());
|
||||
|
||||
// When
|
||||
var result = app.Run("--foo", "12");
|
||||
|
||||
// Then
|
||||
result.Settings.ShouldBeOfType<ValueProviderSettings>().And(settings =>
|
||||
{
|
||||
settings.Foo.ShouldBe("C"); // 12 is 0xC
|
||||
});
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HexConverter : TypeConverter
|
||||
{
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
if (value is int integer)
|
||||
{
|
||||
return integer.ToString("X");
|
||||
}
|
||||
|
||||
return value is string stringValue && int.TryParse(stringValue, out var intValue)
|
||||
? intValue.ToString("X")
|
||||
: base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Use_Provided_Value_If_No_Value_Was_Specified()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<ValueProviderSettings>>();
|
||||
app.Configure(config => config.PropagateExceptions());
|
||||
|
||||
// When
|
||||
var result = app.Run();
|
||||
|
||||
// Then
|
||||
result.Settings.ShouldBeOfType<ValueProviderSettings>().And(settings =>
|
||||
{
|
||||
settings.Foo.ShouldBe("20"); // 32 is 0x20
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Override_Value_If_Value_Was_Specified()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<ValueProviderSettings>>();
|
||||
app.Configure(config => config.PropagateExceptions());
|
||||
|
||||
// When
|
||||
var result = app.Run("--foo", "12");
|
||||
|
||||
// Then
|
||||
result.Settings.ShouldBeOfType<ValueProviderSettings>().And(settings =>
|
||||
{
|
||||
settings.Foo.ShouldBe("C"); // 12 is 0xC
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,111 +1,104 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
public sealed class Vectors
|
||||
{
|
||||
public sealed class Vectors
|
||||
[Fact]
|
||||
public void Should_Throw_If_A_Single_Command_Has_Multiple_Argument_Vectors()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Throw_If_A_Single_Command_Has_Multiple_Argument_Vectors()
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<MultipleArgumentVectorSettings>>("multi");
|
||||
});
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<MultipleArgumentVectorSettings>>("multi");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[] { "multi", "a", "b", "c" }));
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[] { "multi", "a", "b", "c" }));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandConfigurationException>().And(ex =>
|
||||
{
|
||||
ex.Message.ShouldBe("The command 'multi' specifies more than one vector argument.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_An_Argument_Vector_Is_Not_Specified_Last()
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandConfigurationException>().And(ex =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<MultipleArgumentVectorSpecifiedFirstSettings>>("multi");
|
||||
});
|
||||
ex.Message.ShouldBe("The command 'multi' specifies more than one vector argument.");
|
||||
});
|
||||
}
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[] { "multi", "a", "b", "c" }));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandConfigurationException>().And(ex =>
|
||||
{
|
||||
ex.Message.ShouldBe("The command 'multi' specifies an argument vector that is not the last argument.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Assign_Values_To_Argument_Vector()
|
||||
[Fact]
|
||||
public void Should_Throw_If_An_Argument_Vector_Is_Not_Specified_Last()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<ArgumentVectorSettings>>("multi");
|
||||
});
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<MultipleArgumentVectorSpecifiedFirstSettings>>("multi");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"multi", "a", "b", "c",
|
||||
});
|
||||
// When
|
||||
var result = Record.Exception(() => app.Run(new[] { "multi", "a", "b", "c" }));
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<ArgumentVectorSettings>().And(vec =>
|
||||
{
|
||||
vec.Foo.Length.ShouldBe(3);
|
||||
vec.Foo[0].ShouldBe("a");
|
||||
vec.Foo[1].ShouldBe("b");
|
||||
vec.Foo[2].ShouldBe("c");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Assign_Values_To_Option_Vector()
|
||||
// Then
|
||||
result.ShouldBeOfType<CommandConfigurationException>().And(ex =>
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<OptionVectorCommand>("cmd");
|
||||
});
|
||||
ex.Message.ShouldBe("The command 'multi' specifies an argument vector that is not the last argument.");
|
||||
});
|
||||
}
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"cmd", "--foo", "red",
|
||||
"--bar", "4", "--foo", "blue",
|
||||
});
|
||||
[Fact]
|
||||
public void Should_Assign_Values_To_Argument_Vector()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<GenericCommand<ArgumentVectorSettings>>("multi");
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<OptionVectorSettings>().And(vec =>
|
||||
{
|
||||
vec.Foo.ShouldBe(new string[] { "red", "blue" });
|
||||
vec.Bar.ShouldBe(new int[] { 4 });
|
||||
});
|
||||
}
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"multi", "a", "b", "c",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<ArgumentVectorSettings>().And(vec =>
|
||||
{
|
||||
vec.Foo.Length.ShouldBe(3);
|
||||
vec.Foo[0].ShouldBe("a");
|
||||
vec.Foo[1].ShouldBe("b");
|
||||
vec.Foo[2].ShouldBe("c");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Assign_Values_To_Option_Vector()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddCommand<OptionVectorCommand>("cmd");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = app.Run(new[]
|
||||
{
|
||||
"cmd", "--foo", "red",
|
||||
"--bar", "4", "--foo", "blue",
|
||||
});
|
||||
|
||||
// Then
|
||||
result.ExitCode.ShouldBe(0);
|
||||
result.Settings.ShouldBeOfType<OptionVectorSettings>().And(vec =>
|
||||
{
|
||||
vec.Foo.ShouldBe(new string[] { "red", "blue" });
|
||||
vec.Bar.ShouldBe(new int[] { 4 });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,37 +1,31 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
public sealed class Version
|
||||
{
|
||||
public sealed class Version
|
||||
[Fact]
|
||||
public void Should_Output_The_Version_To_The_Console()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Output_The_Version_To_The_Console()
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(config =>
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
animal.AddBranch<MammalSettings>("mammal", mammal =>
|
||||
{
|
||||
animal.AddBranch<MammalSettings>("mammal", mammal =>
|
||||
{
|
||||
mammal.AddCommand<DogCommand>("dog");
|
||||
mammal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
mammal.AddCommand<DogCommand>("dog");
|
||||
mammal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run(Constants.VersionCommand);
|
||||
// When
|
||||
var result = fixture.Run(Constants.VersionCommand);
|
||||
|
||||
// Then
|
||||
result.Output.ShouldStartWith("Spectre.Cli version ");
|
||||
}
|
||||
// Then
|
||||
result.Output.ShouldStartWith("Spectre.Cli version ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,157 +1,148 @@
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed partial class CommandAppTests
|
||||
{
|
||||
public sealed partial class CommandAppTests
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Cli/Xml")]
|
||||
public sealed class Xml
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Cli/Xml")]
|
||||
public sealed class Xml
|
||||
[Fact]
|
||||
[Expectation("Test_1")]
|
||||
public Task Should_Dump_Correct_Model_For_Case_1()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Test_1")]
|
||||
public Task Should_Dump_Correct_Model_For_Case_1()
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(config =>
|
||||
config.PropagateExceptions();
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
animal.AddBranch<MammalSettings>("mammal", mammal =>
|
||||
{
|
||||
animal.AddBranch<MammalSettings>("mammal", mammal =>
|
||||
{
|
||||
mammal.AddCommand<DogCommand>("dog");
|
||||
mammal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
mammal.AddCommand<DogCommand>("dog");
|
||||
mammal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Test_2")]
|
||||
public Task Should_Dump_Correct_Model_For_Case_2()
|
||||
[Fact]
|
||||
[Expectation("Test_2")]
|
||||
public Task Should_Dump_Correct_Model_For_Case_2()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(config =>
|
||||
config.AddCommand<DogCommand>("dog");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Test_3")]
|
||||
public Task Should_Dump_Correct_Model_For_Case_3()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(config =>
|
||||
{
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
config.AddCommand<DogCommand>("dog");
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
animal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Test_3")]
|
||||
public Task Should_Dump_Correct_Model_For_Case_3()
|
||||
[Fact]
|
||||
[Expectation("Test_4")]
|
||||
public Task Should_Dump_Correct_Model_For_Case_4()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(config =>
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
animal.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Test_4")]
|
||||
public Task Should_Dump_Correct_Model_For_Case_4()
|
||||
[Fact]
|
||||
[Expectation("Test_5")]
|
||||
public Task Should_Dump_Correct_Model_For_Case_5()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(config =>
|
||||
{
|
||||
config.AddBranch<AnimalSettings>("animal", animal =>
|
||||
{
|
||||
animal.AddCommand<DogCommand>("dog");
|
||||
});
|
||||
});
|
||||
config.AddCommand<OptionVectorCommand>("cmd");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Test_5")]
|
||||
public Task Should_Dump_Correct_Model_For_Case_5()
|
||||
[Fact]
|
||||
[Expectation("Test_6")]
|
||||
public Task Should_Dump_Correct_Model_For_Model_With_Default_Command()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.SetDefaultCommand<DogCommand>();
|
||||
fixture.Configure(config =>
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.Configure(config =>
|
||||
{
|
||||
config.AddCommand<OptionVectorCommand>("cmd");
|
||||
});
|
||||
config.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Test_6")]
|
||||
public Task Should_Dump_Correct_Model_For_Model_With_Default_Command()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.SetDefaultCommand<DogCommand>();
|
||||
fixture.Configure(config =>
|
||||
{
|
||||
config.AddCommand<HorseCommand>("horse");
|
||||
});
|
||||
[Fact]
|
||||
[Expectation("Hidden_Command_Options")]
|
||||
public Task Should_Not_Dump_Hidden_Options_On_A_Command()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.SetDefaultCommand<HiddenOptionsCommand>();
|
||||
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Hidden_Command_Options")]
|
||||
public Task Should_Not_Dump_Hidden_Options_On_A_Command()
|
||||
{
|
||||
// Given
|
||||
var fixture = new CommandAppTester();
|
||||
fixture.SetDefaultCommand<HiddenOptionsCommand>();
|
||||
|
||||
// When
|
||||
var result = fixture.Run(Constants.XmlDocCommand);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result.Output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,16 +1,11 @@
|
||||
using Spectre.Console.Cli;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Cli
|
||||
public sealed class DefaultTypeRegistrarTests
|
||||
{
|
||||
public sealed class DefaultTypeRegistrarTests
|
||||
[Fact]
|
||||
public void Should_Pass_Base_Registrar_Tests()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Pass_Base_Registrar_Tests()
|
||||
{
|
||||
var harness = new TypeRegistrarBaseTests(() => new DefaultTypeRegistrar());
|
||||
harness.RunAllTests();
|
||||
}
|
||||
var harness = new TypeRegistrarBaseTests(() => new DefaultTypeRegistrar());
|
||||
harness.RunAllTests();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,19 @@
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public sealed class ColorSystemTests
|
||||
{
|
||||
public sealed class ColorSystemTests
|
||||
[Theory]
|
||||
[InlineData(ColorSystem.NoColors, ColorSystemSupport.NoColors)]
|
||||
[InlineData(ColorSystem.Legacy, ColorSystemSupport.Legacy)]
|
||||
[InlineData(ColorSystem.Standard, ColorSystemSupport.Standard)]
|
||||
[InlineData(ColorSystem.EightBit, ColorSystemSupport.EightBit)]
|
||||
[InlineData(ColorSystem.TrueColor, ColorSystemSupport.TrueColor)]
|
||||
public void Should_Be_Analog_To_ColorSystemSupport(ColorSystem colors, ColorSystemSupport support)
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(ColorSystem.NoColors, ColorSystemSupport.NoColors)]
|
||||
[InlineData(ColorSystem.Legacy, ColorSystemSupport.Legacy)]
|
||||
[InlineData(ColorSystem.Standard, ColorSystemSupport.Standard)]
|
||||
[InlineData(ColorSystem.EightBit, ColorSystemSupport.EightBit)]
|
||||
[InlineData(ColorSystem.TrueColor, ColorSystemSupport.TrueColor)]
|
||||
public void Should_Be_Analog_To_ColorSystemSupport(ColorSystem colors, ColorSystemSupport support)
|
||||
{
|
||||
// Given, When
|
||||
var result = (int)colors;
|
||||
// Given, When
|
||||
var result = (int)colors;
|
||||
|
||||
// Then
|
||||
result.ShouldBe((int)support);
|
||||
}
|
||||
// Then
|
||||
result.ShouldBe((int)support);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,287 +1,280 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public sealed class ColorTests
|
||||
{
|
||||
public sealed class ColorTests
|
||||
public sealed class TheEqualsMethod
|
||||
{
|
||||
public sealed class TheEqualsMethod
|
||||
[Fact]
|
||||
public void Should_Consider_Color_And_Non_Color_Equal()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Consider_Color_And_Non_Color_Equal()
|
||||
{
|
||||
// Given
|
||||
var color1 = new Color(128, 0, 128);
|
||||
// Given
|
||||
var color1 = new Color(128, 0, 128);
|
||||
|
||||
// When
|
||||
var result = color1.Equals("Foo");
|
||||
// When
|
||||
var result = color1.Equals("Foo");
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Consider_Same_Colors_Equal_By_Component()
|
||||
{
|
||||
// Given
|
||||
var color1 = new Color(128, 0, 128);
|
||||
var color2 = new Color(128, 0, 128);
|
||||
|
||||
// When
|
||||
var result = color1.Equals(color2);
|
||||
|
||||
// Then
|
||||
result.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Consider_Same_Known_Colors_Equal()
|
||||
{
|
||||
// Given
|
||||
var color1 = Color.Cyan1;
|
||||
var color2 = Color.Cyan1;
|
||||
|
||||
// When
|
||||
var result = color1.Equals(color2);
|
||||
|
||||
// Then
|
||||
result.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Consider_Known_Color_And_Color_With_Same_Components_Equal()
|
||||
{
|
||||
// Given
|
||||
var color1 = Color.Cyan1;
|
||||
var color2 = new Color(0, 255, 255);
|
||||
|
||||
// When
|
||||
var result = color1.Equals(color2);
|
||||
|
||||
// Then
|
||||
result.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Consider_Different_Colors_Equal()
|
||||
{
|
||||
// Given
|
||||
var color1 = new Color(128, 0, 128);
|
||||
var color2 = new Color(128, 128, 128);
|
||||
|
||||
// When
|
||||
var result = color1.Equals(color2);
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Shourd_Not_Consider_Black_And_Default_Colors_Equal()
|
||||
{
|
||||
// Given
|
||||
var color1 = Color.Default;
|
||||
var color2 = Color.Black;
|
||||
|
||||
// When
|
||||
var result = color1.Equals(color2);
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheGetHashCodeMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Same_HashCode_For_Same_Colors()
|
||||
{
|
||||
// Given
|
||||
var color1 = new Color(128, 0, 128);
|
||||
var color2 = new Color(128, 0, 128);
|
||||
|
||||
// When
|
||||
var hash1 = color1.GetHashCode();
|
||||
var hash2 = color2.GetHashCode();
|
||||
|
||||
// Then
|
||||
hash1.ShouldBe(hash2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Different_HashCode_For_Different_Colors()
|
||||
{
|
||||
// Given
|
||||
var color1 = new Color(128, 0, 128);
|
||||
var color2 = new Color(128, 128, 128);
|
||||
|
||||
// When
|
||||
var hash1 = color1.GetHashCode();
|
||||
var hash2 = color2.GetHashCode();
|
||||
|
||||
// Then
|
||||
hash1.ShouldNotBe(hash2);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ImplicitConversions
|
||||
{
|
||||
public sealed class Int32ToColor
|
||||
{
|
||||
public static IEnumerable<object[]> Data =>
|
||||
Enumerable.Range(0, 255)
|
||||
.Select(number => new object[] { number });
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(Data))]
|
||||
public void Should_Return_Expected_Color(int number)
|
||||
{
|
||||
// Given, When
|
||||
var result = (Color)number;
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
result.ShouldBe(Color.FromInt32(number));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Consider_Same_Colors_Equal_By_Component()
|
||||
public void Should_Throw_If_Integer_Is_Lower_Than_Zero()
|
||||
{
|
||||
// Given
|
||||
var color1 = new Color(128, 0, 128);
|
||||
var color2 = new Color(128, 0, 128);
|
||||
|
||||
// When
|
||||
var result = color1.Equals(color2);
|
||||
// Given, When
|
||||
var result = Record.Exception(() => (Color)(-1));
|
||||
|
||||
// Then
|
||||
result.ShouldBeTrue();
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("Color number must be between 0 and 255");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Consider_Same_Known_Colors_Equal()
|
||||
public void Should_Throw_If_Integer_Is_Higher_Than_255()
|
||||
{
|
||||
// Given
|
||||
var color1 = Color.Cyan1;
|
||||
var color2 = Color.Cyan1;
|
||||
|
||||
// When
|
||||
var result = color1.Equals(color2);
|
||||
// Given, When
|
||||
var result = Record.Exception(() => (Color)256);
|
||||
|
||||
// Then
|
||||
result.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Consider_Known_Color_And_Color_With_Same_Components_Equal()
|
||||
{
|
||||
// Given
|
||||
var color1 = Color.Cyan1;
|
||||
var color2 = new Color(0, 255, 255);
|
||||
|
||||
// When
|
||||
var result = color1.Equals(color2);
|
||||
|
||||
// Then
|
||||
result.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Consider_Different_Colors_Equal()
|
||||
{
|
||||
// Given
|
||||
var color1 = new Color(128, 0, 128);
|
||||
var color2 = new Color(128, 128, 128);
|
||||
|
||||
// When
|
||||
var result = color1.Equals(color2);
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Shourd_Not_Consider_Black_And_Default_Colors_Equal()
|
||||
{
|
||||
// Given
|
||||
var color1 = Color.Default;
|
||||
var color2 = Color.Black;
|
||||
|
||||
// When
|
||||
var result = color1.Equals(color2);
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("Color number must be between 0 and 255");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheGetHashCodeMethod
|
||||
public sealed class ConsoleColorToColor
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Same_HashCode_For_Same_Colors()
|
||||
[Theory]
|
||||
[InlineData(ConsoleColor.Black, 0)]
|
||||
[InlineData(ConsoleColor.DarkRed, 1)]
|
||||
[InlineData(ConsoleColor.DarkGreen, 2)]
|
||||
[InlineData(ConsoleColor.DarkYellow, 3)]
|
||||
[InlineData(ConsoleColor.DarkBlue, 4)]
|
||||
[InlineData(ConsoleColor.DarkMagenta, 5)]
|
||||
[InlineData(ConsoleColor.DarkCyan, 6)]
|
||||
[InlineData(ConsoleColor.Gray, 7)]
|
||||
[InlineData(ConsoleColor.DarkGray, 8)]
|
||||
[InlineData(ConsoleColor.Red, 9)]
|
||||
[InlineData(ConsoleColor.Green, 10)]
|
||||
[InlineData(ConsoleColor.Yellow, 11)]
|
||||
[InlineData(ConsoleColor.Blue, 12)]
|
||||
[InlineData(ConsoleColor.Magenta, 13)]
|
||||
[InlineData(ConsoleColor.Cyan, 14)]
|
||||
[InlineData(ConsoleColor.White, 15)]
|
||||
public void Should_Return_Expected_Color(ConsoleColor color, int expected)
|
||||
{
|
||||
// Given
|
||||
var color1 = new Color(128, 0, 128);
|
||||
var color2 = new Color(128, 0, 128);
|
||||
|
||||
// When
|
||||
var hash1 = color1.GetHashCode();
|
||||
var hash2 = color2.GetHashCode();
|
||||
// Given, When
|
||||
var result = (Color)color;
|
||||
|
||||
// Then
|
||||
hash1.ShouldBe(hash2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Different_HashCode_For_Different_Colors()
|
||||
{
|
||||
// Given
|
||||
var color1 = new Color(128, 0, 128);
|
||||
var color2 = new Color(128, 128, 128);
|
||||
|
||||
// When
|
||||
var hash1 = color1.GetHashCode();
|
||||
var hash2 = color2.GetHashCode();
|
||||
|
||||
// Then
|
||||
hash1.ShouldNotBe(hash2);
|
||||
result.ShouldBe(Color.FromInt32(expected));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ImplicitConversions
|
||||
public sealed class ColorToConsoleColor
|
||||
{
|
||||
public sealed class Int32ToColor
|
||||
{
|
||||
public static IEnumerable<object[]> Data =>
|
||||
Enumerable.Range(0, 255)
|
||||
.Select(number => new object[] { number });
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(Data))]
|
||||
public void Should_Return_Expected_Color(int number)
|
||||
{
|
||||
// Given, When
|
||||
var result = (Color)number;
|
||||
|
||||
// Then
|
||||
result.ShouldBe(Color.FromInt32(number));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Integer_Is_Lower_Than_Zero()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => (Color)(-1));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("Color number must be between 0 and 255");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Integer_Is_Higher_Than_255()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => (Color)256);
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("Color number must be between 0 and 255");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ConsoleColorToColor
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(ConsoleColor.Black, 0)]
|
||||
[InlineData(ConsoleColor.DarkRed, 1)]
|
||||
[InlineData(ConsoleColor.DarkGreen, 2)]
|
||||
[InlineData(ConsoleColor.DarkYellow, 3)]
|
||||
[InlineData(ConsoleColor.DarkBlue, 4)]
|
||||
[InlineData(ConsoleColor.DarkMagenta, 5)]
|
||||
[InlineData(ConsoleColor.DarkCyan, 6)]
|
||||
[InlineData(ConsoleColor.Gray, 7)]
|
||||
[InlineData(ConsoleColor.DarkGray, 8)]
|
||||
[InlineData(ConsoleColor.Red, 9)]
|
||||
[InlineData(ConsoleColor.Green, 10)]
|
||||
[InlineData(ConsoleColor.Yellow, 11)]
|
||||
[InlineData(ConsoleColor.Blue, 12)]
|
||||
[InlineData(ConsoleColor.Magenta, 13)]
|
||||
[InlineData(ConsoleColor.Cyan, 14)]
|
||||
[InlineData(ConsoleColor.White, 15)]
|
||||
public void Should_Return_Expected_Color(ConsoleColor color, int expected)
|
||||
{
|
||||
// Given, When
|
||||
var result = (Color)color;
|
||||
|
||||
// Then
|
||||
result.ShouldBe(Color.FromInt32(expected));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ColorToConsoleColor
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(0, ConsoleColor.Black)]
|
||||
[InlineData(1, ConsoleColor.DarkRed)]
|
||||
[InlineData(2, ConsoleColor.DarkGreen)]
|
||||
[InlineData(3, ConsoleColor.DarkYellow)]
|
||||
[InlineData(4, ConsoleColor.DarkBlue)]
|
||||
[InlineData(5, ConsoleColor.DarkMagenta)]
|
||||
[InlineData(6, ConsoleColor.DarkCyan)]
|
||||
[InlineData(7, ConsoleColor.Gray)]
|
||||
[InlineData(8, ConsoleColor.DarkGray)]
|
||||
[InlineData(9, ConsoleColor.Red)]
|
||||
[InlineData(10, ConsoleColor.Green)]
|
||||
[InlineData(11, ConsoleColor.Yellow)]
|
||||
[InlineData(12, ConsoleColor.Blue)]
|
||||
[InlineData(13, ConsoleColor.Magenta)]
|
||||
[InlineData(14, ConsoleColor.Cyan)]
|
||||
[InlineData(15, ConsoleColor.White)]
|
||||
public void Should_Return_Expected_ConsoleColor_For_Known_Color(int color, ConsoleColor expected)
|
||||
{
|
||||
// Given, When
|
||||
var result = (ConsoleColor)Color.FromInt32(color);
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheToMarkupMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Default_Color()
|
||||
[Theory]
|
||||
[InlineData(0, ConsoleColor.Black)]
|
||||
[InlineData(1, ConsoleColor.DarkRed)]
|
||||
[InlineData(2, ConsoleColor.DarkGreen)]
|
||||
[InlineData(3, ConsoleColor.DarkYellow)]
|
||||
[InlineData(4, ConsoleColor.DarkBlue)]
|
||||
[InlineData(5, ConsoleColor.DarkMagenta)]
|
||||
[InlineData(6, ConsoleColor.DarkCyan)]
|
||||
[InlineData(7, ConsoleColor.Gray)]
|
||||
[InlineData(8, ConsoleColor.DarkGray)]
|
||||
[InlineData(9, ConsoleColor.Red)]
|
||||
[InlineData(10, ConsoleColor.Green)]
|
||||
[InlineData(11, ConsoleColor.Yellow)]
|
||||
[InlineData(12, ConsoleColor.Blue)]
|
||||
[InlineData(13, ConsoleColor.Magenta)]
|
||||
[InlineData(14, ConsoleColor.Cyan)]
|
||||
[InlineData(15, ConsoleColor.White)]
|
||||
public void Should_Return_Expected_ConsoleColor_For_Known_Color(int color, ConsoleColor expected)
|
||||
{
|
||||
// Given, When
|
||||
var result = Color.Default.ToMarkup();
|
||||
var result = (ConsoleColor)Color.FromInt32(color);
|
||||
|
||||
// Then
|
||||
result.ShouldBe("default");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Known_Color()
|
||||
{
|
||||
// Given, When
|
||||
var result = Color.Red.ToMarkup();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("red");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Custom_Color()
|
||||
{
|
||||
// Given, When
|
||||
var result = new Color(255, 1, 12).ToMarkup();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("#FF010C");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheToStringMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Color_Name_For_Known_Colors()
|
||||
{
|
||||
// Given, When
|
||||
var name = Color.Fuchsia.ToString();
|
||||
|
||||
// Then
|
||||
name.ShouldBe("fuchsia");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Hex_String_For_Unknown_Colors()
|
||||
{
|
||||
// Given, When
|
||||
var name = new Color(128, 0, 128).ToString();
|
||||
|
||||
// Then
|
||||
name.ShouldBe("#800080 (RGB=128,0,128)");
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheToMarkupMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Default_Color()
|
||||
{
|
||||
// Given, When
|
||||
var result = Color.Default.ToMarkup();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("default");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Known_Color()
|
||||
{
|
||||
// Given, When
|
||||
var result = Color.Red.ToMarkup();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("red");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Custom_Color()
|
||||
{
|
||||
// Given, When
|
||||
var result = new Color(255, 1, 12).ToMarkup();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("#FF010C");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheToStringMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Color_Name_For_Known_Colors()
|
||||
{
|
||||
// Given, When
|
||||
var name = Color.Fuchsia.ToString();
|
||||
|
||||
// Then
|
||||
name.ShouldBe("fuchsia");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Hex_String_For_Unknown_Colors()
|
||||
{
|
||||
// Given, When
|
||||
var name = new Color(128, 0, 128).ToString();
|
||||
|
||||
// Then
|
||||
name.ShouldBe("#800080 (RGB=128,0,128)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,96 +1,91 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public sealed class EmojiTests
|
||||
{
|
||||
public sealed class EmojiTests
|
||||
[Fact]
|
||||
public void Should_Substitute_Emoji_Shortcodes_In_Markdown()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Markup("Hello :globe_showing_europe_africa:!");
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello 🌍!");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Contain_Predefined_Emojis()
|
||||
{
|
||||
// Given, When
|
||||
const string result = "Hello " + Emoji.Known.GlobeShowingEuropeAfrica + "!";
|
||||
|
||||
// Then
|
||||
result.ShouldBe("Hello 🌍!");
|
||||
}
|
||||
|
||||
public sealed class TheReplaceMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Substitute_Emoji_Shortcodes_In_Markdown()
|
||||
public void Should_Replace_Emojis_In_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Emoji.Replace("Hello :globe_showing_europe_africa:!");
|
||||
|
||||
// Then
|
||||
result.ShouldBe("Hello 🌍!");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Parsing
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(":", ":")]
|
||||
[InlineData("::", "::")]
|
||||
[InlineData(":::", ":::")]
|
||||
[InlineData("::::", "::::")]
|
||||
[InlineData("::i:", "::i:")]
|
||||
[InlineData(":i:i:", ":i:i:")]
|
||||
[InlineData("::globe_showing_europe_africa::", ":🌍:")]
|
||||
[InlineData(":globe_showing_europe_africa::globe_showing_europe_africa:", "🌍🌍")]
|
||||
[InlineData("::globe_showing_europe_africa:::test:::globe_showing_europe_africa:::", ":🌍::test::🌍::")]
|
||||
public void Can_Handle_Different_Combinations(string markup, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Markup("Hello :globe_showing_europe_africa:!");
|
||||
console.Markup(markup);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello 🌍!");
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Contain_Predefined_Emojis()
|
||||
public void Should_Leave_Single_Colons()
|
||||
{
|
||||
// Given, When
|
||||
const string result = "Hello " + Emoji.Known.GlobeShowingEuropeAfrica + "!";
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Markup("Hello :globe_showing_europe_africa:! Output: good");
|
||||
|
||||
// Then
|
||||
result.ShouldBe("Hello 🌍!");
|
||||
console.Output.ShouldBe("Hello 🌍! Output: good");
|
||||
}
|
||||
|
||||
public sealed class TheReplaceMethod
|
||||
[Fact]
|
||||
public void Unknown_emojis_should_remain_unchanged()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Replace_Emojis_In_Text()
|
||||
{
|
||||
// Given, When
|
||||
var result = Emoji.Replace("Hello :globe_showing_europe_africa:!");
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("Hello 🌍!");
|
||||
}
|
||||
}
|
||||
// When
|
||||
console.Markup("Hello :globe_showing_flat_earth:!");
|
||||
|
||||
public sealed class Parsing
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(":", ":")]
|
||||
[InlineData("::", "::")]
|
||||
[InlineData(":::", ":::")]
|
||||
[InlineData("::::", "::::")]
|
||||
[InlineData("::i:", "::i:")]
|
||||
[InlineData(":i:i:", ":i:i:")]
|
||||
[InlineData("::globe_showing_europe_africa::", ":🌍:")]
|
||||
[InlineData(":globe_showing_europe_africa::globe_showing_europe_africa:", "🌍🌍")]
|
||||
[InlineData("::globe_showing_europe_africa:::test:::globe_showing_europe_africa:::", ":🌍::test::🌍::")]
|
||||
public void Can_Handle_Different_Combinations(string markup, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Markup(markup);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Leave_Single_Colons()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Markup("Hello :globe_showing_europe_africa:! Output: good");
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello 🌍! Output: good");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Unknown_emojis_should_remain_unchanged()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Markup("Hello :globe_showing_flat_earth:!");
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello :globe_showing_flat_earth:!");
|
||||
}
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello :globe_showing_flat_earth:!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,104 +1,95 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Console.Tests.Data;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Exception")]
|
||||
public sealed class ExceptionTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Exception")]
|
||||
public sealed class ExceptionTests
|
||||
[Fact]
|
||||
[Expectation("Default")]
|
||||
public Task Should_Write_Exception()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Default")]
|
||||
public Task Should_Write_Exception()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(1024);
|
||||
var dex = GetException(() => TestExceptions.MethodThatThrows(null));
|
||||
// Given
|
||||
var console = new TestConsole().Width(1024);
|
||||
var dex = GetException(() => TestExceptions.MethodThatThrows(null));
|
||||
|
||||
// When
|
||||
var result = console.WriteNormalizedException(dex);
|
||||
// When
|
||||
var result = console.WriteNormalizedException(dex);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("ShortenedTypes")]
|
||||
public Task Should_Write_Exception_With_Shortened_Types()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(1024);
|
||||
var dex = GetException(() => TestExceptions.MethodThatThrows(null));
|
||||
|
||||
// When
|
||||
var result = console.WriteNormalizedException(dex, ExceptionFormats.ShortenTypes);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("ShortenedMethods")]
|
||||
public Task Should_Write_Exception_With_Shortened_Methods()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(1024);
|
||||
var dex = GetException(() => TestExceptions.MethodThatThrows(null));
|
||||
|
||||
// When
|
||||
var result = console.WriteNormalizedException(dex, ExceptionFormats.ShortenMethods);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("InnerException")]
|
||||
public Task Should_Write_Exception_With_Inner_Exception()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(1024);
|
||||
var dex = GetException(() => TestExceptions.ThrowWithInnerException());
|
||||
|
||||
// When
|
||||
var result = console.WriteNormalizedException(dex);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("CallSite")]
|
||||
public Task Should_Write_Exceptions_With_Generic_Type_Parameters_In_Callsite_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(1024);
|
||||
var dex = GetException(() => TestExceptions.ThrowWithGenericInnerException());
|
||||
|
||||
// When
|
||||
var result = console.WriteNormalizedException(dex);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
|
||||
public static Exception GetException(Action action)
|
||||
{
|
||||
try
|
||||
{
|
||||
action?.Invoke();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Exception harness failed");
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("ShortenedTypes")]
|
||||
public Task Should_Write_Exception_With_Shortened_Types()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(1024);
|
||||
var dex = GetException(() => TestExceptions.MethodThatThrows(null));
|
||||
|
||||
// When
|
||||
var result = console.WriteNormalizedException(dex, ExceptionFormats.ShortenTypes);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("ShortenedMethods")]
|
||||
public Task Should_Write_Exception_With_Shortened_Methods()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(1024);
|
||||
var dex = GetException(() => TestExceptions.MethodThatThrows(null));
|
||||
|
||||
// When
|
||||
var result = console.WriteNormalizedException(dex, ExceptionFormats.ShortenMethods);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("InnerException")]
|
||||
public Task Should_Write_Exception_With_Inner_Exception()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(1024);
|
||||
var dex = GetException(() => TestExceptions.ThrowWithInnerException());
|
||||
|
||||
// When
|
||||
var result = console.WriteNormalizedException(dex);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("CallSite")]
|
||||
public Task Should_Write_Exceptions_With_Generic_Type_Parameters_In_Callsite_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(1024);
|
||||
var dex = GetException(() => TestExceptions.ThrowWithGenericInnerException());
|
||||
|
||||
// When
|
||||
var result = console.WriteNormalizedException(dex);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
|
||||
public static Exception GetException(Action action)
|
||||
{
|
||||
try
|
||||
{
|
||||
action?.Invoke();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Exception harness failed");
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,25 @@
|
||||
using System.Globalization;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public sealed class DownloadedColumnTests
|
||||
{
|
||||
public sealed class DownloadedColumnTests
|
||||
[Theory]
|
||||
[InlineData(0, 1, "0/1 byte")]
|
||||
[InlineData(37, 101, "37/101 bytes")]
|
||||
[InlineData(101, 101, "101 bytes")]
|
||||
[InlineData(512, 1024, "0.5/1.0 KB")]
|
||||
[InlineData(1024, 1024, "1.0 KB")]
|
||||
[InlineData(1024 * 512, 5 * 1024 * 1024, "0.5/5.0 MB")]
|
||||
[InlineData(5 * 1024 * 1024, 5 * 1024 * 1024, "5.0 MB")]
|
||||
public void Should_Return_Correct_Value(double value, double total, string expected)
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(0, 1, "0/1 byte")]
|
||||
[InlineData(37, 101, "37/101 bytes")]
|
||||
[InlineData(101, 101, "101 bytes")]
|
||||
[InlineData(512, 1024, "0.5/1.0 KB")]
|
||||
[InlineData(1024, 1024, "1.0 KB")]
|
||||
[InlineData(1024 * 512, 5 * 1024 * 1024, "0.5/5.0 MB")]
|
||||
[InlineData(5 * 1024 * 1024, 5 * 1024 * 1024, "5.0 MB")]
|
||||
public void Should_Return_Correct_Value(double value, double total, string expected)
|
||||
{
|
||||
// Given
|
||||
var fixture = new ProgressColumnFixture<DownloadedColumn>(value, total);
|
||||
fixture.Column.Culture = CultureInfo.InvariantCulture;
|
||||
// Given
|
||||
var fixture = new ProgressColumnFixture<DownloadedColumn>(value, total);
|
||||
fixture.Column.Culture = CultureInfo.InvariantCulture;
|
||||
|
||||
// When
|
||||
var result = fixture.Render();
|
||||
// When
|
||||
var result = fixture.Render();
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +1,23 @@
|
||||
using System;
|
||||
using Spectre.Console.Rendering;
|
||||
using Spectre.Console.Testing;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public sealed class ProgressColumnFixture<T>
|
||||
where T : ProgressColumn, new()
|
||||
{
|
||||
public sealed class ProgressColumnFixture<T>
|
||||
where T : ProgressColumn, new()
|
||||
public T Column { get; }
|
||||
public ProgressTask Task { get; set; }
|
||||
|
||||
public ProgressColumnFixture(double completed, double total)
|
||||
{
|
||||
public T Column { get; }
|
||||
public ProgressTask Task { get; set; }
|
||||
|
||||
public ProgressColumnFixture(double completed, double total)
|
||||
{
|
||||
Column = new T();
|
||||
Task = new ProgressTask(1, "Foo", total);
|
||||
Task.Increment(completed);
|
||||
}
|
||||
|
||||
public string Render()
|
||||
{
|
||||
var console = new TestConsole();
|
||||
var context = new RenderContext(console.Profile.Capabilities);
|
||||
console.Write(Column.Render(context, Task, TimeSpan.Zero));
|
||||
return console.Output;
|
||||
}
|
||||
Column = new T();
|
||||
Task = new ProgressTask(1, "Foo", total);
|
||||
Task.Increment(completed);
|
||||
}
|
||||
}
|
||||
|
||||
public string Render()
|
||||
{
|
||||
var console = new TestConsole();
|
||||
var context = new RenderContext(console.Profile.Capabilities);
|
||||
console.Write(Column.Render(context, Task, TimeSpan.Zero));
|
||||
return console.Output;
|
||||
}
|
||||
}
|
||||
|
@ -1,275 +1,267 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Live/Progress")]
|
||||
public sealed class ProgressTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Live/Progress")]
|
||||
public sealed class ProgressTests
|
||||
[Fact]
|
||||
public void Should_Render_Task_Correctly()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Render_Task_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Width(10)
|
||||
.Interactive()
|
||||
.EmitAnsiSequences();
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Width(10)
|
||||
.Interactive()
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(true);
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(true);
|
||||
|
||||
// When
|
||||
progress.Start(ctx => ctx.AddTask("foo"));
|
||||
// When
|
||||
progress.Start(ctx => ctx.AddTask("foo"));
|
||||
|
||||
// Then
|
||||
console.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe(
|
||||
"[?25l" + // Hide cursor
|
||||
" \n" + // Top padding
|
||||
"[38;5;8m━━━━━━━━━━[0m\n" + // Task
|
||||
" " + // Bottom padding
|
||||
"[2K[1A[2K[1A[2K[?25h"); // Clear + show cursor
|
||||
}
|
||||
// Then
|
||||
console.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe(
|
||||
"[?25l" + // Hide cursor
|
||||
" \n" + // Top padding
|
||||
"[38;5;8m━━━━━━━━━━[0m\n" + // Task
|
||||
" " + // Bottom padding
|
||||
"[2K[1A[2K[1A[2K[?25h"); // Clear + show cursor
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Auto_Clear_If_Specified()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Width(10)
|
||||
.Interactive()
|
||||
.EmitAnsiSequences();
|
||||
[Fact]
|
||||
public void Should_Not_Auto_Clear_If_Specified()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Width(10)
|
||||
.Interactive()
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
|
||||
// When
|
||||
progress.Start(ctx => ctx.AddTask("foo"));
|
||||
// When
|
||||
progress.Start(ctx => ctx.AddTask("foo"));
|
||||
|
||||
// Then
|
||||
console.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe(
|
||||
"[?25l" + // Hide cursor
|
||||
" \n" + // Top padding
|
||||
"[38;5;8m━━━━━━━━━━[0m\n" + // Task
|
||||
" \n" + // Bottom padding
|
||||
"[?25h"); // show cursor
|
||||
}
|
||||
// Then
|
||||
console.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe(
|
||||
"[?25l" + // Hide cursor
|
||||
" \n" + // Top padding
|
||||
"[38;5;8m━━━━━━━━━━[0m\n" + // Task
|
||||
" \n" + // Bottom padding
|
||||
"[?25h"); // show cursor
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_ReduceWidth")]
|
||||
public Task Should_Reduce_Width_If_Needed()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Width(20)
|
||||
.Interactive();
|
||||
[Fact]
|
||||
[Expectation("Render_ReduceWidth")]
|
||||
public Task Should_Reduce_Width_If_Needed()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Width(20)
|
||||
.Interactive();
|
||||
|
||||
var progress = new Progress(console)
|
||||
.Columns(new ProgressColumn[]
|
||||
{
|
||||
var progress = new Progress(console)
|
||||
.Columns(new ProgressColumn[]
|
||||
{
|
||||
new TaskDescriptionColumn(),
|
||||
new ProgressBarColumn(),
|
||||
new PercentageColumn(),
|
||||
new RemainingTimeColumn(),
|
||||
new SpinnerColumn(),
|
||||
})
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
})
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
ctx.AddTask("foo");
|
||||
ctx.AddTask("bar");
|
||||
ctx.AddTask("baz");
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Setting_Max_Value_Should_Set_The_MaxValue_And_Cap_Value()
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Interactive();
|
||||
ctx.AddTask("foo");
|
||||
ctx.AddTask("bar");
|
||||
ctx.AddTask("baz");
|
||||
});
|
||||
|
||||
var task = default(ProgressTask);
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
task = ctx.AddTask("foo");
|
||||
task.Increment(100);
|
||||
task.MaxValue = 20;
|
||||
});
|
||||
|
||||
// Then
|
||||
task.MaxValue.ShouldBe(20);
|
||||
task.Value.ShouldBe(20);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Setting_Value_Should_Override_Incremented_Value()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Interactive();
|
||||
|
||||
var task = default(ProgressTask);
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
task = ctx.AddTask("foo");
|
||||
task.Increment(50);
|
||||
task.Value = 20;
|
||||
});
|
||||
|
||||
// Then
|
||||
task.MaxValue.ShouldBe(100);
|
||||
task.Value.ShouldBe(20);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Setting_Value_To_MaxValue_Should_Finish_Task()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Interactive();
|
||||
|
||||
var task = default(ProgressTask);
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
task = ctx.AddTask("foo");
|
||||
task.Value = task.MaxValue;
|
||||
});
|
||||
|
||||
// Then
|
||||
task.IsFinished.ShouldBe(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Increment_Manually_Set_Value()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Interactive();
|
||||
|
||||
var task = default(ProgressTask);
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
task = ctx.AddTask("foo");
|
||||
task.Value = 50;
|
||||
task.Increment(10);
|
||||
});
|
||||
|
||||
// Then
|
||||
task.Value.ShouldBe(60);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Hide_Completed_Tasks()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Width(10)
|
||||
.Interactive()
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var taskFinished = default(ProgressTask);
|
||||
var taskInProgress1 = default(ProgressTask);
|
||||
var taskInProgress2 = default(ProgressTask);
|
||||
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false)
|
||||
.HideCompleted(true);
|
||||
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
taskInProgress1 = ctx.AddTask("foo");
|
||||
taskFinished = ctx.AddTask("bar");
|
||||
taskInProgress2 = ctx.AddTask("baz");
|
||||
taskInProgress2.Increment(20);
|
||||
taskFinished.Value = taskFinished.MaxValue;
|
||||
});
|
||||
|
||||
// Then
|
||||
console.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe(
|
||||
"[?25l" + // Hide cursor
|
||||
" \n" + // top padding
|
||||
"[38;5;8m━━━━━━━━━━[0m\n" + // taskInProgress1
|
||||
"[38;5;11m━━[0m[38;5;8m━━━━━━━━[0m\n" + // taskInProgress2
|
||||
" \n" + // bottom padding
|
||||
"[?25h"); // show cursor
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Report_Max_Remaining_Time_For_Extremely_Small_Progress()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Interactive();
|
||||
|
||||
var task = default(ProgressTask);
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new RemainingTimeColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
task = ctx.AddTask("foo");
|
||||
task.Increment(double.Epsilon);
|
||||
// Make sure that at least one millisecond has elapsed between the increments else the RemainingTime is null
|
||||
// when the last timestamp is equal to the first timestamp of the samples.
|
||||
Thread.Sleep(1);
|
||||
task.Increment(double.Epsilon);
|
||||
});
|
||||
|
||||
// Then
|
||||
task.RemainingTime.ShouldBe(TimeSpan.MaxValue);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Setting_Max_Value_Should_Set_The_MaxValue_And_Cap_Value()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Interactive();
|
||||
|
||||
var task = default(ProgressTask);
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
task = ctx.AddTask("foo");
|
||||
task.Increment(100);
|
||||
task.MaxValue = 20;
|
||||
});
|
||||
|
||||
// Then
|
||||
task.MaxValue.ShouldBe(20);
|
||||
task.Value.ShouldBe(20);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Setting_Value_Should_Override_Incremented_Value()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Interactive();
|
||||
|
||||
var task = default(ProgressTask);
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
task = ctx.AddTask("foo");
|
||||
task.Increment(50);
|
||||
task.Value = 20;
|
||||
});
|
||||
|
||||
// Then
|
||||
task.MaxValue.ShouldBe(100);
|
||||
task.Value.ShouldBe(20);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Setting_Value_To_MaxValue_Should_Finish_Task()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Interactive();
|
||||
|
||||
var task = default(ProgressTask);
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
task = ctx.AddTask("foo");
|
||||
task.Value = task.MaxValue;
|
||||
});
|
||||
|
||||
// Then
|
||||
task.IsFinished.ShouldBe(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Increment_Manually_Set_Value()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Interactive();
|
||||
|
||||
var task = default(ProgressTask);
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
task = ctx.AddTask("foo");
|
||||
task.Value = 50;
|
||||
task.Increment(10);
|
||||
});
|
||||
|
||||
// Then
|
||||
task.Value.ShouldBe(60);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Hide_Completed_Tasks()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Width(10)
|
||||
.Interactive()
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var taskFinished = default(ProgressTask);
|
||||
var taskInProgress1 = default(ProgressTask);
|
||||
var taskInProgress2 = default(ProgressTask);
|
||||
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new ProgressBarColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false)
|
||||
.HideCompleted(true);
|
||||
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
taskInProgress1 = ctx.AddTask("foo");
|
||||
taskFinished = ctx.AddTask("bar");
|
||||
taskInProgress2 = ctx.AddTask("baz");
|
||||
taskInProgress2.Increment(20);
|
||||
taskFinished.Value = taskFinished.MaxValue;
|
||||
});
|
||||
|
||||
// Then
|
||||
console.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe(
|
||||
"[?25l" + // Hide cursor
|
||||
" \n" + // top padding
|
||||
"[38;5;8m━━━━━━━━━━[0m\n" + // taskInProgress1
|
||||
"[38;5;11m━━[0m[38;5;8m━━━━━━━━[0m\n" + // taskInProgress2
|
||||
" \n" + // bottom padding
|
||||
"[?25h"); // show cursor
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Report_Max_Remaining_Time_For_Extremely_Small_Progress()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Interactive();
|
||||
|
||||
var task = default(ProgressTask);
|
||||
var progress = new Progress(console)
|
||||
.Columns(new[] { new RemainingTimeColumn() })
|
||||
.AutoRefresh(false)
|
||||
.AutoClear(false);
|
||||
|
||||
// When
|
||||
progress.Start(ctx =>
|
||||
{
|
||||
task = ctx.AddTask("foo");
|
||||
task.Increment(double.Epsilon);
|
||||
|
||||
// Make sure that at least one millisecond has elapsed between the increments else the RemainingTime is null
|
||||
// when the last timestamp is equal to the first timestamp of the samples.
|
||||
Thread.Sleep(1);
|
||||
|
||||
task.Increment(double.Epsilon);
|
||||
});
|
||||
|
||||
// Then
|
||||
task.RemainingTime.ShouldBe(TimeSpan.MaxValue);
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +1,52 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Live/Status")]
|
||||
public sealed class StatusTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Live/Status")]
|
||||
public sealed class StatusTests
|
||||
public sealed class DummySpinner1 : Spinner
|
||||
{
|
||||
public sealed class DummySpinner1 : Spinner
|
||||
{
|
||||
public override TimeSpan Interval => TimeSpan.FromMilliseconds(100);
|
||||
public override bool IsUnicode => true;
|
||||
public override IReadOnlyList<string> Frames => new List<string> { "*", };
|
||||
}
|
||||
|
||||
public sealed class DummySpinner2 : Spinner
|
||||
{
|
||||
public override TimeSpan Interval => TimeSpan.FromMilliseconds(100);
|
||||
public override bool IsUnicode => true;
|
||||
public override IReadOnlyList<string> Frames => new List<string> { "-", };
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Status_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.TrueColor)
|
||||
.Width(10)
|
||||
.Interactive()
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var status = new Status(console)
|
||||
{
|
||||
AutoRefresh = false,
|
||||
Spinner = new DummySpinner1(),
|
||||
};
|
||||
|
||||
// When
|
||||
status.Start("foo", ctx =>
|
||||
{
|
||||
ctx.Refresh();
|
||||
ctx.Spinner(new DummySpinner2());
|
||||
ctx.Status("bar");
|
||||
ctx.Refresh();
|
||||
ctx.Spinner(new DummySpinner1());
|
||||
ctx.Status("baz");
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
public override TimeSpan Interval => TimeSpan.FromMilliseconds(100);
|
||||
public override bool IsUnicode => true;
|
||||
public override IReadOnlyList<string> Frames => new List<string> { "*", };
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class DummySpinner2 : Spinner
|
||||
{
|
||||
public override TimeSpan Interval => TimeSpan.FromMilliseconds(100);
|
||||
public override bool IsUnicode => true;
|
||||
public override IReadOnlyList<string> Frames => new List<string> { "-", };
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Status_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.TrueColor)
|
||||
.Width(10)
|
||||
.Interactive()
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var status = new Status(console)
|
||||
{
|
||||
AutoRefresh = false,
|
||||
Spinner = new DummySpinner1(),
|
||||
};
|
||||
|
||||
// When
|
||||
status.Start("foo", ctx =>
|
||||
{
|
||||
ctx.Refresh();
|
||||
ctx.Spinner(new DummySpinner2());
|
||||
ctx.Status("bar");
|
||||
ctx.Refresh();
|
||||
ctx.Spinner(new DummySpinner1());
|
||||
ctx.Status("baz");
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
@ -1,156 +1,149 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public sealed class MultiSelectionPromptTests
|
||||
{
|
||||
public sealed class MultiSelectionPromptTests
|
||||
private class CustomItem
|
||||
{
|
||||
private class CustomItem
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
|
||||
public class Comparer : IEqualityComparer<CustomItem>
|
||||
{
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
|
||||
public class Comparer : IEqualityComparer<CustomItem>
|
||||
public bool Equals(CustomItem x, CustomItem y)
|
||||
{
|
||||
public bool Equals(CustomItem x, CustomItem y)
|
||||
{
|
||||
return x.X == y.X && x.Y == y.Y;
|
||||
}
|
||||
return x.X == y.X && x.Y == y.Y;
|
||||
}
|
||||
|
||||
public int GetHashCode([DisallowNull] CustomItem obj)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public int GetHashCode([DisallowNull] CustomItem obj)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Mark_Item_As_Selected_By_Default()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<int>();
|
||||
|
||||
// When
|
||||
var choice = prompt.AddChoice(32);
|
||||
|
||||
// Then
|
||||
choice.IsSelected.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Mark_Item_As_Selected()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<int>();
|
||||
var choice = prompt.AddChoice(32);
|
||||
|
||||
// When
|
||||
prompt.Select(32);
|
||||
|
||||
// Then
|
||||
choice.IsSelected.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Mark_Custom_Item_As_Selected_If_The_Same_Reference_Is_Used()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<CustomItem>();
|
||||
var item = new CustomItem { X = 18, Y = 32 };
|
||||
var choice = prompt.AddChoice(item);
|
||||
|
||||
// When
|
||||
prompt.Select(item);
|
||||
|
||||
// Then
|
||||
choice.IsSelected.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Mark_Custom_Item_As_Selected_If_A_Comparer_Is_Provided()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<CustomItem>(new CustomItem.Comparer());
|
||||
var choice = prompt.AddChoice(new CustomItem { X = 18, Y = 32 });
|
||||
|
||||
// When
|
||||
prompt.Select(new CustomItem { X = 18, Y = 32 });
|
||||
|
||||
// Then
|
||||
choice.IsSelected.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Get_The_Direct_Parent()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<string>();
|
||||
prompt.AddChoice("root").AddChild("level-1").AddChild("level-2").AddChild("item");
|
||||
|
||||
// When
|
||||
var actual = prompt.GetParent("item");
|
||||
|
||||
// Then
|
||||
actual.ShouldBe("level-2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Get_The_List_Of_All_Parents()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<string>();
|
||||
prompt.AddChoice("root").AddChild("level-1").AddChild("level-2").AddChild("item");
|
||||
|
||||
// When
|
||||
var actual = prompt.GetParents("item");
|
||||
|
||||
// Then
|
||||
actual.ShouldBe(new[] { "root", "level-1", "level-2" });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Get_An_Empty_List_Of_Parents_For_Root_Node()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<string>();
|
||||
prompt.AddChoice("root");
|
||||
|
||||
// When
|
||||
var actual = prompt.GetParents("root");
|
||||
|
||||
// Then
|
||||
actual.ShouldBeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Get_Null_As_Direct_Parent_Of_Root_Node()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<string>();
|
||||
prompt.AddChoice("root");
|
||||
|
||||
// When
|
||||
var actual = prompt.GetParent("root");
|
||||
|
||||
// Then
|
||||
actual.ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_When_Getting_Parents_Of_Non_Existing_Node()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<string>();
|
||||
prompt.AddChoice("root").AddChild("level-1").AddChild("level-2").AddChild("item");
|
||||
|
||||
// When
|
||||
Action action = () => prompt.GetParents("non-existing");
|
||||
|
||||
// Then
|
||||
action.ShouldThrow<ArgumentOutOfRangeException>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Mark_Item_As_Selected_By_Default()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<int>();
|
||||
|
||||
// When
|
||||
var choice = prompt.AddChoice(32);
|
||||
|
||||
// Then
|
||||
choice.IsSelected.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Mark_Item_As_Selected()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<int>();
|
||||
var choice = prompt.AddChoice(32);
|
||||
|
||||
// When
|
||||
prompt.Select(32);
|
||||
|
||||
// Then
|
||||
choice.IsSelected.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Mark_Custom_Item_As_Selected_If_The_Same_Reference_Is_Used()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<CustomItem>();
|
||||
var item = new CustomItem { X = 18, Y = 32 };
|
||||
var choice = prompt.AddChoice(item);
|
||||
|
||||
// When
|
||||
prompt.Select(item);
|
||||
|
||||
// Then
|
||||
choice.IsSelected.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Mark_Custom_Item_As_Selected_If_A_Comparer_Is_Provided()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<CustomItem>(new CustomItem.Comparer());
|
||||
var choice = prompt.AddChoice(new CustomItem { X = 18, Y = 32 });
|
||||
|
||||
// When
|
||||
prompt.Select(new CustomItem { X = 18, Y = 32 });
|
||||
|
||||
// Then
|
||||
choice.IsSelected.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Get_The_Direct_Parent()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<string>();
|
||||
prompt.AddChoice("root").AddChild("level-1").AddChild("level-2").AddChild("item");
|
||||
|
||||
// When
|
||||
var actual = prompt.GetParent("item");
|
||||
|
||||
// Then
|
||||
actual.ShouldBe("level-2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Get_The_List_Of_All_Parents()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<string>();
|
||||
prompt.AddChoice("root").AddChild("level-1").AddChild("level-2").AddChild("item");
|
||||
|
||||
// When
|
||||
var actual = prompt.GetParents("item");
|
||||
|
||||
// Then
|
||||
actual.ShouldBe(new[] { "root", "level-1", "level-2" });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Get_An_Empty_List_Of_Parents_For_Root_Node()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<string>();
|
||||
prompt.AddChoice("root");
|
||||
|
||||
// When
|
||||
var actual = prompt.GetParents("root");
|
||||
|
||||
// Then
|
||||
actual.ShouldBeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Get_Null_As_Direct_Parent_Of_Root_Node()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<string>();
|
||||
prompt.AddChoice("root");
|
||||
|
||||
// When
|
||||
var actual = prompt.GetParent("root");
|
||||
|
||||
// Then
|
||||
actual.ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_When_Getting_Parents_Of_Non_Existing_Node()
|
||||
{
|
||||
// Given
|
||||
var prompt = new MultiSelectionPrompt<string>();
|
||||
prompt.AddChoice("root").AddChild("level-1").AddChild("level-2").AddChild("item");
|
||||
|
||||
// When
|
||||
Action action = () => prompt.GetParents("non-existing");
|
||||
|
||||
// Then
|
||||
action.ShouldThrow<ArgumentOutOfRangeException>();
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,24 @@
|
||||
using System;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public sealed class SelectionPromptTests
|
||||
{
|
||||
public sealed class SelectionPromptTests
|
||||
[Fact]
|
||||
[GitHubIssue(608)]
|
||||
public void Should_Not_Throw_When_Selecting_An_Item_With_Escaped_Markup()
|
||||
{
|
||||
[Fact]
|
||||
[GitHubIssue(608)]
|
||||
public void Should_Not_Throw_When_Selecting_An_Item_With_Escaped_Markup()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Profile.Capabilities.Interactive = true;
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
var input = "[red]This text will never be red[/]".EscapeMarkup();
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Profile.Capabilities.Interactive = true;
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
var input = "[red]This text will never be red[/]".EscapeMarkup();
|
||||
|
||||
// When
|
||||
var prompt = new SelectionPrompt<string>()
|
||||
.Title("Select one")
|
||||
.AddChoices(input);
|
||||
prompt.Show(console);
|
||||
// When
|
||||
var prompt = new SelectionPrompt<string>()
|
||||
.Title("Select one")
|
||||
.AddChoices(input);
|
||||
prompt.Show(console);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldContain(@"[red]This text will never be red[/]");
|
||||
}
|
||||
// Then
|
||||
console.Output.ShouldContain(@"[red]This text will never be red[/]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,253 +1,244 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Prompts/Text")]
|
||||
public sealed class TextPromptTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Prompts/Text")]
|
||||
public sealed class TextPromptTests
|
||||
[Fact]
|
||||
public void Should_Return_Entered_Text()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Entered_Text()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("Hello World");
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("Hello World");
|
||||
|
||||
// When
|
||||
var result = console.Prompt(new TextPrompt<string>("Enter text:"));
|
||||
// When
|
||||
var result = console.Prompt(new TextPrompt<string>("Enter text:"));
|
||||
|
||||
// Then
|
||||
result.ShouldBe("Hello World");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("ConversionError")]
|
||||
public Task Should_Return_Validation_Error_If_Value_Cannot_Be_Converted()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("ninety-nine");
|
||||
console.Input.PushTextWithEnter("99");
|
||||
|
||||
// When
|
||||
console.Prompt(new TextPrompt<int>("Age?"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Lines);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("DefaultValue")]
|
||||
public Task Should_Chose_Default_Value_If_Nothing_Is_Entered()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.AddChoice("Banana")
|
||||
.AddChoice("Orange")
|
||||
.DefaultValue("Banana"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("InvalidChoice")]
|
||||
public Task Should_Return_Error_If_An_Invalid_Choice_Is_Made()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("Apple");
|
||||
console.Input.PushTextWithEnter("Banana");
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.AddChoice("Banana")
|
||||
.AddChoice("Orange")
|
||||
.DefaultValue("Banana"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("AcceptChoice")]
|
||||
public Task Should_Accept_Choice_In_List()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("Orange");
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.AddChoice("Banana")
|
||||
.AddChoice("Orange")
|
||||
.DefaultValue("Banana"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("AutoComplete_Empty")]
|
||||
public Task Should_Auto_Complete_To_First_Choice_If_Pressing_Tab_On_Empty_String()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushKey(ConsoleKey.Tab);
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.AddChoice("Banana")
|
||||
.AddChoice("Orange")
|
||||
.DefaultValue("Banana"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("AutoComplete_BestMatch")]
|
||||
public Task Should_Auto_Complete_To_Best_Match()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushText("Band");
|
||||
console.Input.PushKey(ConsoleKey.Tab);
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.AddChoice("Banana")
|
||||
.AddChoice("Bandana")
|
||||
.AddChoice("Orange"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("AutoComplete_NextChoice")]
|
||||
public Task Should_Auto_Complete_To_Next_Choice_When_Pressing_Tab_On_A_Match()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushText("Apple");
|
||||
console.Input.PushKey(ConsoleKey.Tab);
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.AddChoice("Apple")
|
||||
.AddChoice("Banana")
|
||||
.AddChoice("Orange"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("CustomValidation")]
|
||||
public Task Should_Return_Error_If_Custom_Validation_Fails()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("22");
|
||||
console.Input.PushTextWithEnter("102");
|
||||
console.Input.PushTextWithEnter("ABC");
|
||||
console.Input.PushTextWithEnter("99");
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<int>("Guess number:")
|
||||
.ValidationErrorMessage("Invalid input")
|
||||
.Validate(age =>
|
||||
{
|
||||
if (age < 99)
|
||||
{
|
||||
return ValidationResult.Error("Too low");
|
||||
}
|
||||
else if (age > 99)
|
||||
{
|
||||
return ValidationResult.Error("Too high");
|
||||
}
|
||||
|
||||
return ValidationResult.Success();
|
||||
}));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("CustomConverter")]
|
||||
public Task Should_Use_Custom_Converter()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("Banana");
|
||||
|
||||
// When
|
||||
var result = console.Prompt(
|
||||
new TextPrompt<(int, string)>("Favorite fruit?")
|
||||
.AddChoice((1, "Apple"))
|
||||
.AddChoice((2, "Banana"))
|
||||
.WithConverter(testData => testData.Item2));
|
||||
|
||||
// Then
|
||||
result.Item1.ShouldBe(2);
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("SecretDefaultValue")]
|
||||
public Task Should_Chose_Masked_Default_Value_If_Nothing_Is_Entered_And_Prompt_Is_Secret()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.Secret()
|
||||
.DefaultValue("Banana"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("NoSuffix")]
|
||||
[GitHubIssue(413)]
|
||||
public Task Should_Not_Append_Questionmark_Or_Colon_If_No_Choices_Are_Set()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("Orange");
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Enter command$"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
// Then
|
||||
result.ShouldBe("Hello World");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("ConversionError")]
|
||||
public Task Should_Return_Validation_Error_If_Value_Cannot_Be_Converted()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("ninety-nine");
|
||||
console.Input.PushTextWithEnter("99");
|
||||
|
||||
// When
|
||||
console.Prompt(new TextPrompt<int>("Age?"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Lines);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("DefaultValue")]
|
||||
public Task Should_Chose_Default_Value_If_Nothing_Is_Entered()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.AddChoice("Banana")
|
||||
.AddChoice("Orange")
|
||||
.DefaultValue("Banana"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("InvalidChoice")]
|
||||
public Task Should_Return_Error_If_An_Invalid_Choice_Is_Made()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("Apple");
|
||||
console.Input.PushTextWithEnter("Banana");
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.AddChoice("Banana")
|
||||
.AddChoice("Orange")
|
||||
.DefaultValue("Banana"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("AcceptChoice")]
|
||||
public Task Should_Accept_Choice_In_List()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("Orange");
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.AddChoice("Banana")
|
||||
.AddChoice("Orange")
|
||||
.DefaultValue("Banana"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("AutoComplete_Empty")]
|
||||
public Task Should_Auto_Complete_To_First_Choice_If_Pressing_Tab_On_Empty_String()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushKey(ConsoleKey.Tab);
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.AddChoice("Banana")
|
||||
.AddChoice("Orange")
|
||||
.DefaultValue("Banana"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("AutoComplete_BestMatch")]
|
||||
public Task Should_Auto_Complete_To_Best_Match()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushText("Band");
|
||||
console.Input.PushKey(ConsoleKey.Tab);
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.AddChoice("Banana")
|
||||
.AddChoice("Bandana")
|
||||
.AddChoice("Orange"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("AutoComplete_NextChoice")]
|
||||
public Task Should_Auto_Complete_To_Next_Choice_When_Pressing_Tab_On_A_Match()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushText("Apple");
|
||||
console.Input.PushKey(ConsoleKey.Tab);
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.AddChoice("Apple")
|
||||
.AddChoice("Banana")
|
||||
.AddChoice("Orange"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("CustomValidation")]
|
||||
public Task Should_Return_Error_If_Custom_Validation_Fails()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("22");
|
||||
console.Input.PushTextWithEnter("102");
|
||||
console.Input.PushTextWithEnter("ABC");
|
||||
console.Input.PushTextWithEnter("99");
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<int>("Guess number:")
|
||||
.ValidationErrorMessage("Invalid input")
|
||||
.Validate(age =>
|
||||
{
|
||||
if (age < 99)
|
||||
{
|
||||
return ValidationResult.Error("Too low");
|
||||
}
|
||||
else if (age > 99)
|
||||
{
|
||||
return ValidationResult.Error("Too high");
|
||||
}
|
||||
|
||||
return ValidationResult.Success();
|
||||
}));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("CustomConverter")]
|
||||
public Task Should_Use_Custom_Converter()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("Banana");
|
||||
|
||||
// When
|
||||
var result = console.Prompt(
|
||||
new TextPrompt<(int, string)>("Favorite fruit?")
|
||||
.AddChoice((1, "Apple"))
|
||||
.AddChoice((2, "Banana"))
|
||||
.WithConverter(testData => testData.Item2));
|
||||
|
||||
// Then
|
||||
result.Item1.ShouldBe(2);
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("SecretDefaultValue")]
|
||||
public Task Should_Chose_Masked_Default_Value_If_Nothing_Is_Entered_And_Prompt_Is_Secret()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushKey(ConsoleKey.Enter);
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Favorite fruit?")
|
||||
.Secret()
|
||||
.DefaultValue("Banana"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("NoSuffix")]
|
||||
[GitHubIssue(413)]
|
||||
public Task Should_Not_Append_Questionmark_Or_Colon_If_No_Choices_Are_Set()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Input.PushTextWithEnter("Orange");
|
||||
|
||||
// When
|
||||
console.Prompt(
|
||||
new TextPrompt<string>("Enter command$"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
@ -1,54 +1,47 @@
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Recorder")]
|
||||
public sealed class RecorderTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Recorder")]
|
||||
public sealed class RecorderTests
|
||||
[Fact]
|
||||
[Expectation("Text")]
|
||||
public Task Should_Export_Text_As_Expected()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Text")]
|
||||
public Task Should_Export_Text_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var recorder = new Recorder(console);
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var recorder = new Recorder(console);
|
||||
|
||||
recorder.Write(new Table()
|
||||
.AddColumns("Foo", "Bar", "Qux")
|
||||
.AddRow("Corgi", "Waldo", "Zap")
|
||||
.AddRow(new Panel("Hello World").RoundedBorder()));
|
||||
recorder.Write(new Table()
|
||||
.AddColumns("Foo", "Bar", "Qux")
|
||||
.AddRow("Corgi", "Waldo", "Zap")
|
||||
.AddRow(new Panel("Hello World").RoundedBorder()));
|
||||
|
||||
// When
|
||||
var result = recorder.ExportText();
|
||||
// When
|
||||
var result = recorder.ExportText();
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Html")]
|
||||
public Task Should_Export_Html_Text_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var recorder = new Recorder(console);
|
||||
|
||||
recorder.Write(new Table()
|
||||
.AddColumns("[red on black]Foo[/]", "[green bold]Bar[/]", "[blue italic]Qux[/]")
|
||||
.AddRow("[invert underline]Corgi[/]", "[bold strikethrough]Waldo[/]", "[dim]Zap[/]")
|
||||
.AddRow(new Panel("[blue]Hello World[/]")
|
||||
.BorderColor(Color.Red).RoundedBorder()));
|
||||
|
||||
// When
|
||||
var result = recorder.ExportHtml();
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Html")]
|
||||
public Task Should_Export_Html_Text_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var recorder = new Recorder(console);
|
||||
|
||||
recorder.Write(new Table()
|
||||
.AddColumns("[red on black]Foo[/]", "[green bold]Bar[/]", "[blue italic]Qux[/]")
|
||||
.AddRow("[invert underline]Corgi[/]", "[bold strikethrough]Waldo[/]", "[dim]Zap[/]")
|
||||
.AddRow(new Panel("[blue]Hello World[/]")
|
||||
.BorderColor(Color.Red).RoundedBorder()));
|
||||
|
||||
// When
|
||||
var result = recorder.ExportHtml();
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(result);
|
||||
}
|
||||
}
|
||||
|
@ -1,210 +1,201 @@
|
||||
using System.Threading.Tasks;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Rendering;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Rendering/Borders/Box")]
|
||||
public sealed class BoxBorderTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Rendering/Borders/Box")]
|
||||
public sealed class BoxBorderTests
|
||||
public sealed class NoBorder
|
||||
{
|
||||
[UsesVerify]
|
||||
public sealed class NoBorder
|
||||
{
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxExtensions.GetSafeBorder(BoxBorder.None, safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.None);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("NoBorder")]
|
||||
public Task Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var panel = Fixture.GetPanel().NoBorder();
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class AsciiBorder
|
||||
{
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxExtensions.GetSafeBorder(BoxBorder.Ascii, safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Ascii);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("AsciiBorder")]
|
||||
public Task Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var panel = Fixture.GetPanel().AsciiBorder();
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class DoubleBorder
|
||||
{
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxExtensions.GetSafeBorder(BoxBorder.Double, safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Double);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("DoubleBorder")]
|
||||
public Task Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var panel = Fixture.GetPanel().DoubleBorder();
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class HeavyBorder
|
||||
{
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxExtensions.GetSafeBorder(BoxBorder.Heavy, safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Square);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("HeavyBorder")]
|
||||
public Task Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var panel = Fixture.GetPanel().HeavyBorder();
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class RoundedBorder
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxExtensions.GetSafeBorder(BoxBorder.Rounded, safe: true);
|
||||
var border = BoxExtensions.GetSafeBorder(BoxBorder.None, safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Square);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("RoundedBorder")]
|
||||
public Task Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var panel = Fixture.GetPanel().RoundedBorder();
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
border.ShouldBeSameAs(BoxBorder.None);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class SquareBorder
|
||||
[Fact]
|
||||
[Expectation("NoBorder")]
|
||||
public Task Should_Render_As_Expected()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxExtensions.GetSafeBorder(BoxBorder.Square, safe: true);
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var panel = Fixture.GetPanel().NoBorder();
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Square);
|
||||
}
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
[Fact]
|
||||
[Expectation("SquareBorder")]
|
||||
public Task Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var panel = Fixture.GetPanel().SquareBorder();
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Fixture
|
||||
{
|
||||
public static Panel GetPanel()
|
||||
{
|
||||
return new Panel("Hello World")
|
||||
.Header("Greeting");
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class AsciiBorder
|
||||
{
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxExtensions.GetSafeBorder(BoxBorder.Ascii, safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Ascii);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("AsciiBorder")]
|
||||
public Task Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var panel = Fixture.GetPanel().AsciiBorder();
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class DoubleBorder
|
||||
{
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxExtensions.GetSafeBorder(BoxBorder.Double, safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Double);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("DoubleBorder")]
|
||||
public Task Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var panel = Fixture.GetPanel().DoubleBorder();
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class HeavyBorder
|
||||
{
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxExtensions.GetSafeBorder(BoxBorder.Heavy, safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Square);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("HeavyBorder")]
|
||||
public Task Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var panel = Fixture.GetPanel().HeavyBorder();
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class RoundedBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxExtensions.GetSafeBorder(BoxBorder.Rounded, safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Square);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("RoundedBorder")]
|
||||
public Task Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var panel = Fixture.GetPanel().RoundedBorder();
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class SquareBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxExtensions.GetSafeBorder(BoxBorder.Square, safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Square);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("SquareBorder")]
|
||||
public Task Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var panel = Fixture.GetPanel().SquareBorder();
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Fixture
|
||||
{
|
||||
public static Panel GetPanel()
|
||||
{
|
||||
return new Panel("Hello World")
|
||||
.Header("Greeting");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,35 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Rendering;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public sealed class RenderHookTests
|
||||
{
|
||||
public sealed class RenderHookTests
|
||||
private sealed class HelloRenderHook : IRenderHook
|
||||
{
|
||||
private sealed class HelloRenderHook : IRenderHook
|
||||
public IEnumerable<IRenderable> Process(RenderContext context, IEnumerable<IRenderable> renderables)
|
||||
{
|
||||
public IEnumerable<IRenderable> Process(RenderContext context, IEnumerable<IRenderable> renderables)
|
||||
{
|
||||
return new IRenderable[] { new Text("Hello\n") }.Concat(renderables);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Inject_Renderable_Before_Writing_To_Console()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Pipeline.Attach(new HelloRenderHook());
|
||||
|
||||
// When
|
||||
console.Write(new Text("World"));
|
||||
|
||||
// Then
|
||||
console.Lines[0].ShouldBe("Hello");
|
||||
console.Lines[1].ShouldBe("World");
|
||||
return new IRenderable[] { new Text("Hello\n") }.Concat(renderables);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Inject_Renderable_Before_Writing_To_Console()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
console.Pipeline.Attach(new HelloRenderHook());
|
||||
|
||||
// When
|
||||
console.Write(new Text("World"));
|
||||
|
||||
// Then
|
||||
console.Lines[0].ShouldBe("Hello");
|
||||
console.Lines[1].ShouldBe("World");
|
||||
}
|
||||
}
|
||||
|
@ -1,95 +1,90 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Rendering;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public sealed class SegmentTests
|
||||
{
|
||||
public sealed class SegmentTests
|
||||
[UsesVerify]
|
||||
public sealed class TheSplitMethod
|
||||
{
|
||||
[UsesVerify]
|
||||
public sealed class TheSplitMethod
|
||||
[Theory]
|
||||
[InlineData("Foo Bar", 0, "", "Foo Bar")]
|
||||
[InlineData("Foo Bar", 1, "F", "oo Bar")]
|
||||
[InlineData("Foo Bar", 2, "Fo", "o Bar")]
|
||||
[InlineData("Foo Bar", 3, "Foo", " Bar")]
|
||||
[InlineData("Foo Bar", 4, "Foo ", "Bar")]
|
||||
[InlineData("Foo Bar", 5, "Foo B", "ar")]
|
||||
[InlineData("Foo Bar", 6, "Foo Ba", "r")]
|
||||
[InlineData("Foo Bar", 7, "Foo Bar", null)]
|
||||
[InlineData("Foo 测试 Bar", 0, "", "Foo 测试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 1, "F", "oo 测试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 2, "Fo", "o 测试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 3, "Foo", " 测试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 4, "Foo ", "测试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 5, "Foo 测", "试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 6, "Foo 测", "试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 7, "Foo 测试", " Bar")]
|
||||
[InlineData("Foo 测试 Bar", 8, "Foo 测试", " Bar")]
|
||||
[InlineData("Foo 测试 Bar", 9, "Foo 测试 ", "Bar")]
|
||||
[InlineData("Foo 测试 Bar", 10, "Foo 测试 B", "ar")]
|
||||
[InlineData("Foo 测试 Bar", 11, "Foo 测试 Ba", "r")]
|
||||
[InlineData("Foo 测试 Bar", 12, "Foo 测试 Bar", null)]
|
||||
public void Should_Split_Segment_Correctly(string text, int offset, string expectedFirst, string expectedSecond)
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Foo Bar", 0, "", "Foo Bar")]
|
||||
[InlineData("Foo Bar", 1, "F", "oo Bar")]
|
||||
[InlineData("Foo Bar", 2, "Fo", "o Bar")]
|
||||
[InlineData("Foo Bar", 3, "Foo", " Bar")]
|
||||
[InlineData("Foo Bar", 4, "Foo ", "Bar")]
|
||||
[InlineData("Foo Bar", 5, "Foo B", "ar")]
|
||||
[InlineData("Foo Bar", 6, "Foo Ba", "r")]
|
||||
[InlineData("Foo Bar", 7, "Foo Bar", null)]
|
||||
[InlineData("Foo 测试 Bar", 0, "", "Foo 测试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 1, "F", "oo 测试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 2, "Fo", "o 测试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 3, "Foo", " 测试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 4, "Foo ", "测试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 5, "Foo 测", "试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 6, "Foo 测", "试 Bar")]
|
||||
[InlineData("Foo 测试 Bar", 7, "Foo 测试", " Bar")]
|
||||
[InlineData("Foo 测试 Bar", 8, "Foo 测试", " Bar")]
|
||||
[InlineData("Foo 测试 Bar", 9, "Foo 测试 ", "Bar")]
|
||||
[InlineData("Foo 测试 Bar", 10, "Foo 测试 B", "ar")]
|
||||
[InlineData("Foo 测试 Bar", 11, "Foo 测试 Ba", "r")]
|
||||
[InlineData("Foo 测试 Bar", 12, "Foo 测试 Bar", null)]
|
||||
public void Should_Split_Segment_Correctly(string text, int offset, string expectedFirst, string expectedSecond)
|
||||
{
|
||||
// Given
|
||||
var style = new Style(Color.Red, Color.Green, Decoration.Bold);
|
||||
var segment = new Segment(text, style);
|
||||
// Given
|
||||
var style = new Style(Color.Red, Color.Green, Decoration.Bold);
|
||||
var segment = new Segment(text, style);
|
||||
|
||||
// When
|
||||
var (first, second) = segment.Split(offset);
|
||||
// When
|
||||
var (first, second) = segment.Split(offset);
|
||||
|
||||
// Then
|
||||
first.Text.ShouldBe(expectedFirst);
|
||||
first.Style.ShouldBe(style);
|
||||
second?.Text?.ShouldBe(expectedSecond);
|
||||
second?.Style?.ShouldBe(style);
|
||||
}
|
||||
// Then
|
||||
first.Text.ShouldBe(expectedFirst);
|
||||
first.Style.ShouldBe(style);
|
||||
second?.Text?.ShouldBe(expectedSecond);
|
||||
second?.Style?.ShouldBe(style);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class TheSplitLinesMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Split_Segment()
|
||||
{
|
||||
// Given, When
|
||||
var lines = Segment.SplitLines(
|
||||
new[]
|
||||
{
|
||||
new Segment("Foo"),
|
||||
new Segment("Bar"),
|
||||
new Segment("\n"),
|
||||
new Segment("Baz"),
|
||||
new Segment("Qux"),
|
||||
new Segment("\n"),
|
||||
new Segment("Corgi"),
|
||||
});
|
||||
|
||||
// Then
|
||||
lines.Count.ShouldBe(3);
|
||||
|
||||
lines[0].Count.ShouldBe(2);
|
||||
lines[0][0].Text.ShouldBe("Foo");
|
||||
lines[0][1].Text.ShouldBe("Bar");
|
||||
|
||||
lines[1].Count.ShouldBe(2);
|
||||
lines[1][0].Text.ShouldBe("Baz");
|
||||
lines[1][1].Text.ShouldBe("Qux");
|
||||
|
||||
lines[2].Count.ShouldBe(1);
|
||||
lines[2][0].Text.ShouldBe("Corgi");
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class TheSplitLinesMethod
|
||||
[Fact]
|
||||
public void Should_Split_Segment_With_Windows_LineBreak()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Split_Segment()
|
||||
{
|
||||
// Given, When
|
||||
var lines = Segment.SplitLines(
|
||||
new[]
|
||||
{
|
||||
new Segment("Foo"),
|
||||
new Segment("Bar"),
|
||||
new Segment("\n"),
|
||||
new Segment("Baz"),
|
||||
new Segment("Qux"),
|
||||
new Segment("\n"),
|
||||
new Segment("Corgi"),
|
||||
});
|
||||
|
||||
// Then
|
||||
lines.Count.ShouldBe(3);
|
||||
|
||||
lines[0].Count.ShouldBe(2);
|
||||
lines[0][0].Text.ShouldBe("Foo");
|
||||
lines[0][1].Text.ShouldBe("Bar");
|
||||
|
||||
lines[1].Count.ShouldBe(2);
|
||||
lines[1][0].Text.ShouldBe("Baz");
|
||||
lines[1][1].Text.ShouldBe("Qux");
|
||||
|
||||
lines[2].Count.ShouldBe(1);
|
||||
lines[2][0].Text.ShouldBe("Corgi");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Split_Segment_With_Windows_LineBreak()
|
||||
{
|
||||
// Given, When
|
||||
var lines = Segment.SplitLines(
|
||||
new[]
|
||||
{
|
||||
// Given, When
|
||||
var lines = Segment.SplitLines(
|
||||
new[]
|
||||
{
|
||||
new Segment("Foo"),
|
||||
new Segment("Bar"),
|
||||
new Segment("\r\n"),
|
||||
@ -97,53 +92,52 @@ namespace Spectre.Console.Tests.Unit
|
||||
new Segment("Qux"),
|
||||
new Segment("\r\n"),
|
||||
new Segment("Corgi"),
|
||||
});
|
||||
});
|
||||
|
||||
// Then
|
||||
lines.Count.ShouldBe(3);
|
||||
// Then
|
||||
lines.Count.ShouldBe(3);
|
||||
|
||||
lines[0].Count.ShouldBe(2);
|
||||
lines[0][0].Text.ShouldBe("Foo");
|
||||
lines[0][1].Text.ShouldBe("Bar");
|
||||
lines[0].Count.ShouldBe(2);
|
||||
lines[0][0].Text.ShouldBe("Foo");
|
||||
lines[0][1].Text.ShouldBe("Bar");
|
||||
|
||||
lines[1].Count.ShouldBe(2);
|
||||
lines[1][0].Text.ShouldBe("Baz");
|
||||
lines[1][1].Text.ShouldBe("Qux");
|
||||
lines[1].Count.ShouldBe(2);
|
||||
lines[1][0].Text.ShouldBe("Baz");
|
||||
lines[1][1].Text.ShouldBe("Qux");
|
||||
|
||||
lines[2].Count.ShouldBe(1);
|
||||
lines[2][0].Text.ShouldBe("Corgi");
|
||||
}
|
||||
lines[2].Count.ShouldBe(1);
|
||||
lines[2][0].Text.ShouldBe("Corgi");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Split_Segments_With_Linebreak_In_Text()
|
||||
{
|
||||
// Given, Given
|
||||
var lines = Segment.SplitLines(
|
||||
new[]
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Split_Segments_With_Linebreak_In_Text()
|
||||
{
|
||||
// Given, Given
|
||||
var lines = Segment.SplitLines(
|
||||
new[]
|
||||
{
|
||||
new Segment("Foo\n"),
|
||||
new Segment("Bar\n"),
|
||||
new Segment("Baz"),
|
||||
new Segment("Qux\n"),
|
||||
new Segment("Corgi"),
|
||||
});
|
||||
});
|
||||
|
||||
// Then
|
||||
lines.Count.ShouldBe(4);
|
||||
// Then
|
||||
lines.Count.ShouldBe(4);
|
||||
|
||||
lines[0].Count.ShouldBe(1);
|
||||
lines[0][0].Text.ShouldBe("Foo");
|
||||
lines[0].Count.ShouldBe(1);
|
||||
lines[0][0].Text.ShouldBe("Foo");
|
||||
|
||||
lines[1].Count.ShouldBe(1);
|
||||
lines[1][0].Text.ShouldBe("Bar");
|
||||
lines[1].Count.ShouldBe(1);
|
||||
lines[1][0].Text.ShouldBe("Bar");
|
||||
|
||||
lines[2].Count.ShouldBe(2);
|
||||
lines[2][0].Text.ShouldBe("Baz");
|
||||
lines[2][1].Text.ShouldBe("Qux");
|
||||
lines[2].Count.ShouldBe(2);
|
||||
lines[2][0].Text.ShouldBe("Baz");
|
||||
lines[2][1].Text.ShouldBe("Qux");
|
||||
|
||||
lines[3].Count.ShouldBe(1);
|
||||
lines[3][0].Text.ShouldBe("Corgi");
|
||||
}
|
||||
lines[3].Count.ShouldBe(1);
|
||||
lines[3][0].Text.ShouldBe("Corgi");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,401 +1,396 @@
|
||||
using System;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public sealed class StyleTests
|
||||
{
|
||||
public sealed class StyleTests
|
||||
[Fact]
|
||||
public void Should_Combine_Two_Styles_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var first = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic);
|
||||
var other = new Style(Color.Green, Color.Silver, Decoration.Underline, "https://example.com");
|
||||
|
||||
// When
|
||||
var result = first.Combine(other);
|
||||
|
||||
// Then
|
||||
result.Foreground.ShouldBe(Color.Green);
|
||||
result.Background.ShouldBe(Color.Silver);
|
||||
result.Decoration.ShouldBe(Decoration.Bold | Decoration.Italic | Decoration.Underline);
|
||||
result.Link.ShouldBe("https://example.com");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Consider_Two_Identical_Styles_Equal()
|
||||
{
|
||||
// Given
|
||||
var first = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
var second = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
|
||||
// When
|
||||
var result = first.Equals(second);
|
||||
|
||||
// Then
|
||||
result.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Consider_Two_Styles_With_Different_Foreground_Colors_Equal()
|
||||
{
|
||||
// Given
|
||||
var first = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
var second = new Style(Color.Blue, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
|
||||
// When
|
||||
var result = first.Equals(second);
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Consider_Two_Styles_With_Different_Background_Colors_Equal()
|
||||
{
|
||||
// Given
|
||||
var first = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
var second = new Style(Color.White, Color.Blue, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
|
||||
// When
|
||||
var result = first.Equals(second);
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Consider_Two_Styles_With_Different_Decorations_Equal()
|
||||
{
|
||||
// Given
|
||||
var first = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
var second = new Style(Color.White, Color.Yellow, Decoration.Bold, "http://example.com");
|
||||
|
||||
// When
|
||||
var result = first.Equals(second);
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Consider_Two_Styles_With_Different_Links_Equal()
|
||||
{
|
||||
// Given
|
||||
var first = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
var second = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://foo.com");
|
||||
|
||||
// When
|
||||
var result = first.Equals(second);
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
|
||||
public sealed class TheParseMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Combine_Two_Styles_As_Expected()
|
||||
public void Default_Keyword_Should_Return_Default_Style()
|
||||
{
|
||||
// Given
|
||||
var first = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic);
|
||||
var other = new Style(Color.Green, Color.Silver, Decoration.Underline, "https://example.com");
|
||||
|
||||
// When
|
||||
var result = first.Combine(other);
|
||||
// Given, When
|
||||
var result = Style.Parse("default");
|
||||
|
||||
// Then
|
||||
result.Foreground.ShouldBe(Color.Green);
|
||||
result.Background.ShouldBe(Color.Silver);
|
||||
result.Decoration.ShouldBe(Decoration.Bold | Decoration.Italic | Decoration.Underline);
|
||||
result.ShouldNotBeNull();
|
||||
result.Foreground.ShouldBe(Color.Default);
|
||||
result.Background.ShouldBe(Color.Default);
|
||||
result.Decoration.ShouldBe(Decoration.None);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("bold", Decoration.Bold)]
|
||||
[InlineData("b", Decoration.Bold)]
|
||||
[InlineData("dim", Decoration.Dim)]
|
||||
[InlineData("i", Decoration.Italic)]
|
||||
[InlineData("italic", Decoration.Italic)]
|
||||
[InlineData("underline", Decoration.Underline)]
|
||||
[InlineData("u", Decoration.Underline)]
|
||||
[InlineData("invert", Decoration.Invert)]
|
||||
[InlineData("conceal", Decoration.Conceal)]
|
||||
[InlineData("slowblink", Decoration.SlowBlink)]
|
||||
[InlineData("rapidblink", Decoration.RapidBlink)]
|
||||
[InlineData("strikethrough", Decoration.Strikethrough)]
|
||||
[InlineData("s", Decoration.Strikethrough)]
|
||||
public void Should_Parse_Decoration(string text, Decoration decoration)
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse(text);
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Decoration.ShouldBe(decoration);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Link_Without_Address()
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse("link");
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Link.ShouldBe("https://emptylink");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Link()
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse("link=https://example.com");
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Link.ShouldBe("https://example.com");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Consider_Two_Identical_Styles_Equal()
|
||||
public void Should_Throw_If_Link_Is_Set_Twice()
|
||||
{
|
||||
// Given
|
||||
var first = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
var second = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse("link=https://example.com link=https://example.com"));
|
||||
|
||||
// When
|
||||
var result = first.Equals(second);
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("A link has already been set.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Background_If_Foreground_Is_Set_To_Default()
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse("default on green");
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Decoration.ShouldBe(Decoration.None);
|
||||
result.Foreground.ShouldBe(Color.Default);
|
||||
result.Background.ShouldBe(Color.Green);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Foreground_Is_Set_Twice()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse("green yellow"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("A foreground color has already been set.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Background_Is_Set_Twice()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse("green on blue yellow"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("A background color has already been set.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Color_Name_Could_Not_Be_Found()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse("bold lol"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("Could not find color or style 'lol'.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Background_Color_Name_Could_Not_Be_Found()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse("blue on lol"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("Could not find color 'lol'.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Colors_And_Decoration_And_Link()
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse("link=https://example.com bold underline blue on green");
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Decoration.ShouldBe(Decoration.Bold | Decoration.Underline);
|
||||
result.Foreground.ShouldBe(Color.Blue);
|
||||
result.Background.ShouldBe(Color.Green);
|
||||
result.Link.ShouldBe("https://example.com");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("#FF0000 on #0000FF")]
|
||||
[InlineData("#F00 on #00F")]
|
||||
public void Should_Parse_Hex_Colors_Correctly(string style)
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse(style);
|
||||
|
||||
// Then
|
||||
result.Foreground.ShouldBe(Color.Red);
|
||||
result.Background.ShouldBe(Color.Blue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("#", "Invalid hex color '#'.")]
|
||||
[InlineData("#FF00FF00FF", "Invalid hex color '#FF00FF00FF'.")]
|
||||
[InlineData("#FOO", "Invalid hex color '#FOO'. Could not find any recognizable digits.")]
|
||||
public void Should_Return_Error_If_Hex_Color_Is_Invalid(string style, string expected)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse(style));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Message.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("rgb(255,0,0) on rgb(0,0,255)")]
|
||||
public void Should_Parse_Rgb_Colors_Correctly(string style)
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse(style);
|
||||
|
||||
// Then
|
||||
result.Foreground.ShouldBe(Color.Red);
|
||||
result.Background.ShouldBe(Color.Blue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("12 on 24")]
|
||||
public void Should_Parse_Colors_Numbers_Correctly(string style)
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse(style);
|
||||
|
||||
// Then
|
||||
result.Foreground.ShouldBe(Color.Blue);
|
||||
result.Background.ShouldBe(Color.DeepSkyBlue4_1);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("-12", "Color number must be greater than or equal to 0 (was -12)")]
|
||||
[InlineData("256", "Color number must be less than or equal to 255 (was 256)")]
|
||||
public void Should_Return_Error_If_Color_Number_Is_Invalid(string style, string expected)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse(style));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Message.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("rgb()", "Invalid RGB color 'rgb()'.")]
|
||||
[InlineData("rgb(", "Invalid RGB color 'rgb('.")]
|
||||
[InlineData("rgb(255)", "Invalid RGB color 'rgb(255)'.")]
|
||||
[InlineData("rgb(255,255)", "Invalid RGB color 'rgb(255,255)'.")]
|
||||
[InlineData("rgb(255,255,255", "Invalid RGB color 'rgb(255,255,255'.")]
|
||||
[InlineData("rgb(A,B,C)", "Invalid RGB color 'rgb(A,B,C)'. Input string was not in a correct format.")]
|
||||
public void Should_Return_Error_If_Rgb_Color_Is_Invalid(string style, string expected)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse(style));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Message.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheTryParseMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_True_If_Parsing_Succeeded()
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.TryParse("bold", out var style);
|
||||
|
||||
// Then
|
||||
result.ShouldBeTrue();
|
||||
style.ShouldNotBeNull();
|
||||
style.Decoration.ShouldBe(Decoration.Bold);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Consider_Two_Styles_With_Different_Foreground_Colors_Equal()
|
||||
public void Should_Return_False_If_Parsing_Failed()
|
||||
{
|
||||
// Given
|
||||
var first = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
var second = new Style(Color.Blue, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
|
||||
// When
|
||||
var result = first.Equals(second);
|
||||
// Given, When
|
||||
var result = Style.TryParse("lol", out _);
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Consider_Two_Styles_With_Different_Background_Colors_Equal()
|
||||
{
|
||||
// Given
|
||||
var first = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
var second = new Style(Color.White, Color.Blue, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
|
||||
// When
|
||||
var result = first.Equals(second);
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Consider_Two_Styles_With_Different_Decorations_Equal()
|
||||
{
|
||||
// Given
|
||||
var first = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
var second = new Style(Color.White, Color.Yellow, Decoration.Bold, "http://example.com");
|
||||
|
||||
// When
|
||||
var result = first.Equals(second);
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Consider_Two_Styles_With_Different_Links_Equal()
|
||||
{
|
||||
// Given
|
||||
var first = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://example.com");
|
||||
var second = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic, "http://foo.com");
|
||||
|
||||
// When
|
||||
var result = first.Equals(second);
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
|
||||
public sealed class TheParseMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Default_Keyword_Should_Return_Default_Style()
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse("default");
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Foreground.ShouldBe(Color.Default);
|
||||
result.Background.ShouldBe(Color.Default);
|
||||
result.Decoration.ShouldBe(Decoration.None);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("bold", Decoration.Bold)]
|
||||
[InlineData("b", Decoration.Bold)]
|
||||
[InlineData("dim", Decoration.Dim)]
|
||||
[InlineData("i", Decoration.Italic)]
|
||||
[InlineData("italic", Decoration.Italic)]
|
||||
[InlineData("underline", Decoration.Underline)]
|
||||
[InlineData("u", Decoration.Underline)]
|
||||
[InlineData("invert", Decoration.Invert)]
|
||||
[InlineData("conceal", Decoration.Conceal)]
|
||||
[InlineData("slowblink", Decoration.SlowBlink)]
|
||||
[InlineData("rapidblink", Decoration.RapidBlink)]
|
||||
[InlineData("strikethrough", Decoration.Strikethrough)]
|
||||
[InlineData("s", Decoration.Strikethrough)]
|
||||
public void Should_Parse_Decoration(string text, Decoration decoration)
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse(text);
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Decoration.ShouldBe(decoration);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Link_Without_Address()
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse("link");
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Link.ShouldBe("https://emptylink");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Link()
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse("link=https://example.com");
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Link.ShouldBe("https://example.com");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Link_Is_Set_Twice()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse("link=https://example.com link=https://example.com"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("A link has already been set.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Background_If_Foreground_Is_Set_To_Default()
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse("default on green");
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Decoration.ShouldBe(Decoration.None);
|
||||
result.Foreground.ShouldBe(Color.Default);
|
||||
result.Background.ShouldBe(Color.Green);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Foreground_Is_Set_Twice()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse("green yellow"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("A foreground color has already been set.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Background_Is_Set_Twice()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse("green on blue yellow"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("A background color has already been set.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Color_Name_Could_Not_Be_Found()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse("bold lol"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("Could not find color or style 'lol'.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Background_Color_Name_Could_Not_Be_Found()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse("blue on lol"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("Could not find color 'lol'.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Parse_Colors_And_Decoration_And_Link()
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse("link=https://example.com bold underline blue on green");
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Decoration.ShouldBe(Decoration.Bold | Decoration.Underline);
|
||||
result.Foreground.ShouldBe(Color.Blue);
|
||||
result.Background.ShouldBe(Color.Green);
|
||||
result.Link.ShouldBe("https://example.com");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("#FF0000 on #0000FF")]
|
||||
[InlineData("#F00 on #00F")]
|
||||
public void Should_Parse_Hex_Colors_Correctly(string style)
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse(style);
|
||||
|
||||
// Then
|
||||
result.Foreground.ShouldBe(Color.Red);
|
||||
result.Background.ShouldBe(Color.Blue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("#", "Invalid hex color '#'.")]
|
||||
[InlineData("#FF00FF00FF", "Invalid hex color '#FF00FF00FF'.")]
|
||||
[InlineData("#FOO", "Invalid hex color '#FOO'. Could not find any recognizable digits.")]
|
||||
public void Should_Return_Error_If_Hex_Color_Is_Invalid(string style, string expected)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse(style));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Message.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("rgb(255,0,0) on rgb(0,0,255)")]
|
||||
public void Should_Parse_Rgb_Colors_Correctly(string style)
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse(style);
|
||||
|
||||
// Then
|
||||
result.Foreground.ShouldBe(Color.Red);
|
||||
result.Background.ShouldBe(Color.Blue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("12 on 24")]
|
||||
public void Should_Parse_Colors_Numbers_Correctly(string style)
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.Parse(style);
|
||||
|
||||
// Then
|
||||
result.Foreground.ShouldBe(Color.Blue);
|
||||
result.Background.ShouldBe(Color.DeepSkyBlue4_1);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("-12", "Color number must be greater than or equal to 0 (was -12)")]
|
||||
[InlineData("256", "Color number must be less than or equal to 255 (was 256)")]
|
||||
public void Should_Return_Error_If_Color_Number_Is_Invalid(string style, string expected)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse(style));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Message.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("rgb()", "Invalid RGB color 'rgb()'.")]
|
||||
[InlineData("rgb(", "Invalid RGB color 'rgb('.")]
|
||||
[InlineData("rgb(255)", "Invalid RGB color 'rgb(255)'.")]
|
||||
[InlineData("rgb(255,255)", "Invalid RGB color 'rgb(255,255)'.")]
|
||||
[InlineData("rgb(255,255,255", "Invalid RGB color 'rgb(255,255,255'.")]
|
||||
[InlineData("rgb(A,B,C)", "Invalid RGB color 'rgb(A,B,C)'. Input string was not in a correct format.")]
|
||||
public void Should_Return_Error_If_Rgb_Color_Is_Invalid(string style, string expected)
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Style.Parse(style));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.Message.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheTryParseMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_True_If_Parsing_Succeeded()
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.TryParse("bold", out var style);
|
||||
|
||||
// Then
|
||||
result.ShouldBeTrue();
|
||||
style.ShouldNotBeNull();
|
||||
style.Decoration.ShouldBe(Decoration.Bold);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_False_If_Parsing_Failed()
|
||||
{
|
||||
// Given, When
|
||||
var result = Style.TryParse("lol", out _);
|
||||
|
||||
// Then
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheToMarkupMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Style_With_Foreground_Color()
|
||||
{
|
||||
// Given
|
||||
var style = new Style(Color.Red);
|
||||
|
||||
// When
|
||||
var result = style.ToMarkup();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("red");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Style_With_Foreground_And_Background_Color()
|
||||
{
|
||||
// Given
|
||||
var style = new Style(Color.Red, Color.Green);
|
||||
|
||||
// When
|
||||
var result = style.ToMarkup();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("red on green");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Style_With_Foreground_And_Background_Color_And_Decoration()
|
||||
{
|
||||
// Given
|
||||
var style = new Style(Color.Red, Color.Green, Decoration.Bold | Decoration.Underline);
|
||||
|
||||
// When
|
||||
var result = style.ToMarkup();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("bold underline red on green");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Style_With_Only_Background_Color()
|
||||
{
|
||||
// Given
|
||||
var style = new Style(background: Color.Green);
|
||||
|
||||
// When
|
||||
var result = style.ToMarkup();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("default on green");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheToMarkupMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Style_With_Foreground_Color()
|
||||
{
|
||||
// Given
|
||||
var style = new Style(Color.Red);
|
||||
|
||||
// When
|
||||
var result = style.ToMarkup();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("red");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Style_With_Foreground_And_Background_Color()
|
||||
{
|
||||
// Given
|
||||
var style = new Style(Color.Red, Color.Green);
|
||||
|
||||
// When
|
||||
var result = style.ToMarkup();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("red on green");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Style_With_Foreground_And_Background_Color_And_Decoration()
|
||||
{
|
||||
// Given
|
||||
var style = new Style(Color.Red, Color.Green, Decoration.Bold | Decoration.Underline);
|
||||
|
||||
// When
|
||||
var result = style.ToMarkup();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("bold underline red on green");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Expected_Markup_For_Style_With_Only_Background_Color()
|
||||
{
|
||||
// Given
|
||||
var style = new Style(background: Color.Green);
|
||||
|
||||
// When
|
||||
var result = style.ToMarkup();
|
||||
|
||||
// Then
|
||||
result.ShouldBe("default on green");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,72 +1,64 @@
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/BarChart")]
|
||||
public sealed class BarChartTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/BarChart")]
|
||||
public sealed class BarChartTests
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public async Task Should_Render_Correctly()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public async Task Should_Render_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new BarChart()
|
||||
.Width(60)
|
||||
.Label("Number of fruits")
|
||||
.AddItem("Apple", 12)
|
||||
.AddItem("Orange", 54)
|
||||
.AddItem("Banana", 33));
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Zero_Value")]
|
||||
public async Task Should_Render_Correctly_2()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new BarChart()
|
||||
.Width(60)
|
||||
.Label("Number of fruits")
|
||||
.AddItem("Apple", 0)
|
||||
.AddItem("Orange", 54)
|
||||
.AddItem("Banana", 33));
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Fixed_Max_Value")]
|
||||
public async Task Should_Render_Correctly_3()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new BarChart()
|
||||
.Width(60)
|
||||
.WithMaxValue(100)
|
||||
.Label("Number of fruits")
|
||||
.AddItem("Apple", 12)
|
||||
.AddItem("Orange", 54)
|
||||
.AddItem("Banana", 33));
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
// When
|
||||
console.Write(new BarChart()
|
||||
.Width(60)
|
||||
.Label("Number of fruits")
|
||||
.AddItem("Apple", 12)
|
||||
.AddItem("Orange", 54)
|
||||
.AddItem("Banana", 33));
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Zero_Value")]
|
||||
public async Task Should_Render_Correctly_2()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new BarChart()
|
||||
.Width(60)
|
||||
.Label("Number of fruits")
|
||||
.AddItem("Apple", 0)
|
||||
.AddItem("Orange", 54)
|
||||
.AddItem("Banana", 33));
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Fixed_Max_Value")]
|
||||
public async Task Should_Render_Correctly_3()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new BarChart()
|
||||
.Width(60)
|
||||
.WithMaxValue(100)
|
||||
.Label("Number of fruits")
|
||||
.AddItem("Apple", 12)
|
||||
.AddItem("Orange", 54)
|
||||
.AddItem("Banana", 33));
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
@ -1,150 +1,143 @@
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/BreakdownChart")]
|
||||
public sealed class BreakdownChartTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/BreakdownChart")]
|
||||
public sealed class BreakdownChartTests
|
||||
[Fact]
|
||||
[Expectation("Default")]
|
||||
public async Task Should_Render_Correctly()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Default")]
|
||||
public async Task Should_Render_Correctly()
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart();
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Width")]
|
||||
public async Task Should_Render_With_Specific_Width()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart().Width(60);
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("TagFormat")]
|
||||
public async Task Should_Render_Correctly_With_Specific_Value_Formatter()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart()
|
||||
.Width(60)
|
||||
.Culture("sv-SE")
|
||||
.UseValueFormatter((v, c) => string.Format(c, "{0}%", v));
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("HideTags")]
|
||||
public async Task Should_Render_Correctly_Without_Tags()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart().Width(60).HideTags();
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("HideTagValues")]
|
||||
public async Task Should_Render_Correctly_Without_Tag_Values()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart().Width(60).HideTagValues();
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Culture")]
|
||||
public async Task Should_Render_Correctly_With_Specific_Culture()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart().Width(60).Culture("sv-SE");
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("FullSize")]
|
||||
public async Task Should_Render_FullSize_Mode_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart().Width(60).FullSize();
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Ansi")]
|
||||
public async Task Should_Render_Correct_Ansi()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().EmitAnsiSequences();
|
||||
var chart = Fixture.GetChart().Width(60).FullSize();
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
public static class Fixture
|
||||
{
|
||||
public static BreakdownChart GetChart()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart();
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Width")]
|
||||
public async Task Should_Render_With_Specific_Width()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart().Width(60);
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("TagFormat")]
|
||||
public async Task Should_Render_Correctly_With_Specific_Value_Formatter()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart()
|
||||
.Width(60)
|
||||
.Culture("sv-SE")
|
||||
.UseValueFormatter((v, c) => string.Format(c, "{0}%", v));
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("HideTags")]
|
||||
public async Task Should_Render_Correctly_Without_Tags()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart().Width(60).HideTags();
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("HideTagValues")]
|
||||
public async Task Should_Render_Correctly_Without_Tag_Values()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart().Width(60).HideTagValues();
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Culture")]
|
||||
public async Task Should_Render_Correctly_With_Specific_Culture()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart().Width(60).Culture("sv-SE");
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("FullSize")]
|
||||
public async Task Should_Render_FullSize_Mode_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var chart = Fixture.GetChart().Width(60).FullSize();
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Ansi")]
|
||||
public async Task Should_Render_Correct_Ansi()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().EmitAnsiSequences();
|
||||
var chart = Fixture.GetChart().Width(60).FullSize();
|
||||
|
||||
// When
|
||||
console.Write(chart);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
public static class Fixture
|
||||
{
|
||||
public static BreakdownChart GetChart()
|
||||
{
|
||||
return new BreakdownChart()
|
||||
.AddItem("SCSS", 37, Color.Red)
|
||||
.AddItem("HTML", 28.3, Color.Blue)
|
||||
.AddItem("C#", 22.6, Color.Green)
|
||||
.AddItem("JavaScript", 6, Color.Yellow)
|
||||
.AddItem("Ruby", 6, Color.LightGreen)
|
||||
.AddItem("Shell", 0.1, Color.Aqua);
|
||||
}
|
||||
return new BreakdownChart()
|
||||
.AddItem("SCSS", 37, Color.Red)
|
||||
.AddItem("HTML", 28.3, Color.Blue)
|
||||
.AddItem("C#", 22.6, Color.Green)
|
||||
.AddItem("JavaScript", 6, Color.Yellow)
|
||||
.AddItem("Ruby", 6, Color.LightGreen)
|
||||
.AddItem("Shell", 0.1, Color.Aqua);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,108 +1,100 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Calendar")]
|
||||
public sealed class CalendarTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Calendar")]
|
||||
public sealed class CalendarTests
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Calendar_Correctly()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Calendar_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var calendar = new Calendar(2020, 10)
|
||||
.AddCalendarEvent(new DateTime(2020, 9, 1))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 3))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 12));
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var calendar = new Calendar(2020, 10)
|
||||
.AddCalendarEvent(new DateTime(2020, 9, 1))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 3))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 12));
|
||||
|
||||
// When
|
||||
console.Write(calendar);
|
||||
// When
|
||||
console.Write(calendar);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Centered")]
|
||||
public Task Should_Center_Calendar_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var calendar = new Calendar(2020, 10)
|
||||
.Centered()
|
||||
.AddCalendarEvent(new DateTime(2020, 9, 1))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 3))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 12));
|
||||
|
||||
// When
|
||||
console.Write(calendar);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("LeftAligned")]
|
||||
public Task Should_Left_Align_Calendar_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var calendar = new Calendar(2020, 10)
|
||||
.LeftAligned()
|
||||
.AddCalendarEvent(new DateTime(2020, 9, 1))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 3))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 12));
|
||||
|
||||
// When
|
||||
console.Write(calendar);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("RightAligned")]
|
||||
public Task Should_Right_Align_Calendar_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var calendar = new Calendar(2020, 10)
|
||||
.RightAligned()
|
||||
.AddCalendarEvent(new DateTime(2020, 9, 1))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 3))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 12));
|
||||
|
||||
// When
|
||||
console.Write(calendar);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Culture")]
|
||||
public Task Should_Render_Calendar_Correctly_For_Specific_Culture()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var calendar = new Calendar(2020, 10, 15)
|
||||
.Culture("de-DE")
|
||||
.AddCalendarEvent(new DateTime(2020, 9, 1))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 3))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 12));
|
||||
|
||||
// When
|
||||
console.Write(calendar);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Centered")]
|
||||
public Task Should_Center_Calendar_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var calendar = new Calendar(2020, 10)
|
||||
.Centered()
|
||||
.AddCalendarEvent(new DateTime(2020, 9, 1))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 3))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 12));
|
||||
|
||||
// When
|
||||
console.Write(calendar);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("LeftAligned")]
|
||||
public Task Should_Left_Align_Calendar_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var calendar = new Calendar(2020, 10)
|
||||
.LeftAligned()
|
||||
.AddCalendarEvent(new DateTime(2020, 9, 1))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 3))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 12));
|
||||
|
||||
// When
|
||||
console.Write(calendar);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("RightAligned")]
|
||||
public Task Should_Right_Align_Calendar_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var calendar = new Calendar(2020, 10)
|
||||
.RightAligned()
|
||||
.AddCalendarEvent(new DateTime(2020, 9, 1))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 3))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 12));
|
||||
|
||||
// When
|
||||
console.Write(calendar);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Culture")]
|
||||
public Task Should_Render_Calendar_Correctly_For_Specific_Culture()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var calendar = new Calendar(2020, 10, 15)
|
||||
.Culture("de-DE")
|
||||
.AddCalendarEvent(new DateTime(2020, 9, 1))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 3))
|
||||
.AddCalendarEvent(new DateTime(2020, 10, 12));
|
||||
|
||||
// When
|
||||
console.Write(calendar);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
@ -1,143 +1,134 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Canvas")]
|
||||
public class CanvasTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Canvas")]
|
||||
public class CanvasTests
|
||||
public sealed class TheConstructor
|
||||
{
|
||||
public sealed class TheConstructor
|
||||
[Fact]
|
||||
public void Should_Throw_If_Width_Is_Less_Than_Zero()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Throw_If_Width_Is_Less_Than_Zero()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new Canvas(0, 1));
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new Canvas(0, 1));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<ArgumentException>()
|
||||
.And(ex => ex.ParamName.ShouldBe("width"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Height_Is_Less_Than_Zero()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new Canvas(1, 0));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<ArgumentException>()
|
||||
.And(ex => ex.ParamName.ShouldBe("height"));
|
||||
}
|
||||
// Then
|
||||
result.ShouldBeOfType<ArgumentException>()
|
||||
.And(ex => ex.ParamName.ShouldBe("width"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public async Task Should_Render_Canvas_Correctly()
|
||||
public void Should_Throw_If_Height_Is_Less_Than_Zero()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var canvas = new Canvas(width: 5, height: 5);
|
||||
canvas.SetPixel(0, 0, Color.Red);
|
||||
canvas.SetPixel(4, 0, Color.Green);
|
||||
canvas.SetPixel(0, 4, Color.Blue);
|
||||
canvas.SetPixel(4, 4, Color.Yellow);
|
||||
|
||||
// When
|
||||
console.Write(canvas);
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new Canvas(1, 0));
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Nested")]
|
||||
public async Task Simple_Measure()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var panel = new Panel(new Canvas(width: 2, height: 2)
|
||||
.SetPixel(0, 0, Color.Aqua)
|
||||
.SetPixel(1, 1, Color.Grey));
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_NarrowTerminal")]
|
||||
public async Task Should_Scale_Down_Canvas_Is_Bigger_Than_Terminal()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Width(10)
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var canvas = new Canvas(width: 20, height: 10);
|
||||
canvas.SetPixel(0, 0, Color.Aqua);
|
||||
canvas.SetPixel(19, 9, Color.Grey);
|
||||
|
||||
// When
|
||||
console.Write(canvas);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_MaxWidth")]
|
||||
public async Task Should_Scale_Down_Canvas_If_MaxWidth_Is_Set()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var canvas = new Canvas(width: 20, height: 10) { MaxWidth = 10 };
|
||||
canvas.SetPixel(0, 0, Color.Aqua);
|
||||
canvas.SetPixel(19, 9, Color.Aqua);
|
||||
|
||||
// When
|
||||
console.Write(canvas);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Render_Canvas_If_Canvas_Cannot_Be_Scaled_Down()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Width(10)
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var canvas = new Canvas(width: 20, height: 2);
|
||||
canvas.SetPixel(0, 0, Color.Aqua);
|
||||
canvas.SetPixel(19, 1, Color.Grey);
|
||||
|
||||
// When
|
||||
console.Write(canvas);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBeEmpty();
|
||||
result.ShouldBeOfType<ArgumentException>()
|
||||
.And(ex => ex.ParamName.ShouldBe("height"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public async Task Should_Render_Canvas_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var canvas = new Canvas(width: 5, height: 5);
|
||||
canvas.SetPixel(0, 0, Color.Red);
|
||||
canvas.SetPixel(4, 0, Color.Green);
|
||||
canvas.SetPixel(0, 4, Color.Blue);
|
||||
canvas.SetPixel(4, 4, Color.Yellow);
|
||||
|
||||
// When
|
||||
console.Write(canvas);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Nested")]
|
||||
public async Task Simple_Measure()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var panel = new Panel(new Canvas(width: 2, height: 2)
|
||||
.SetPixel(0, 0, Color.Aqua)
|
||||
.SetPixel(1, 1, Color.Grey));
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_NarrowTerminal")]
|
||||
public async Task Should_Scale_Down_Canvas_Is_Bigger_Than_Terminal()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Width(10)
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var canvas = new Canvas(width: 20, height: 10);
|
||||
canvas.SetPixel(0, 0, Color.Aqua);
|
||||
canvas.SetPixel(19, 9, Color.Grey);
|
||||
|
||||
// When
|
||||
console.Write(canvas);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_MaxWidth")]
|
||||
public async Task Should_Scale_Down_Canvas_If_MaxWidth_Is_Set()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var canvas = new Canvas(width: 20, height: 10) { MaxWidth = 10 };
|
||||
canvas.SetPixel(0, 0, Color.Aqua);
|
||||
canvas.SetPixel(19, 9, Color.Aqua);
|
||||
|
||||
// When
|
||||
console.Write(canvas);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Render_Canvas_If_Canvas_Cannot_Be_Scaled_Down()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole()
|
||||
.Width(10)
|
||||
.Colors(ColorSystem.Standard)
|
||||
.EmitAnsiSequences();
|
||||
|
||||
var canvas = new Canvas(width: 20, height: 2);
|
||||
canvas.SetPixel(0, 0, Color.Aqua);
|
||||
canvas.SetPixel(19, 1, Color.Grey);
|
||||
|
||||
// When
|
||||
console.Write(canvas);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBeEmpty();
|
||||
}
|
||||
}
|
||||
|
@ -1,48 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Columns")]
|
||||
public sealed class ColumnsTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Columns")]
|
||||
public sealed class ColumnsTests
|
||||
private sealed class User
|
||||
{
|
||||
private sealed class User
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Country { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Columns_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(61);
|
||||
var users = new[]
|
||||
{
|
||||
new User { Name = "Savannah Thompson", Country = "Australia" },
|
||||
new User { Name = "Sophie Ramos", Country = "United States" },
|
||||
new User { Name = "Katrin Goldberg", Country = "Germany" },
|
||||
};
|
||||
|
||||
var cards = new List<Panel>();
|
||||
foreach (var user in users)
|
||||
{
|
||||
cards.Add(
|
||||
new Panel($"[b]{user.Name}[/]\n[yellow]{user.Country}[/]")
|
||||
.RoundedBorder().Expand());
|
||||
}
|
||||
|
||||
// When
|
||||
console.Write(new Columns(cards));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
public string Name { get; set; }
|
||||
public string Country { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Columns_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(61);
|
||||
var users = new[]
|
||||
{
|
||||
new User { Name = "Savannah Thompson", Country = "Australia" },
|
||||
new User { Name = "Sophie Ramos", Country = "United States" },
|
||||
new User { Name = "Katrin Goldberg", Country = "Germany" },
|
||||
};
|
||||
|
||||
var cards = new List<Panel>();
|
||||
foreach (var user in users)
|
||||
{
|
||||
cards.Add(
|
||||
new Panel($"[b]{user.Name}[/]\n[yellow]{user.Country}[/]")
|
||||
.RoundedBorder().Expand());
|
||||
}
|
||||
|
||||
// When
|
||||
console.Write(new Columns(cards));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
@ -1,107 +1,100 @@
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Figlet")]
|
||||
public sealed class FigletTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Figlet")]
|
||||
public sealed class FigletTests
|
||||
[Fact]
|
||||
[Expectation("Load_Stream")]
|
||||
public async Task Should_Load_Font_From_Stream()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Load_Stream")]
|
||||
public async Task Should_Load_Font_From_Stream()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(180);
|
||||
var font = FigletFont.Load(EmbeddedResourceReader.LoadResourceStream("Spectre.Console.Tests/Data/starwars.flf"));
|
||||
var text = new FigletText(font, "Patrik was here");
|
||||
// Given
|
||||
var console = new TestConsole().Width(180);
|
||||
var font = FigletFont.Load(EmbeddedResourceReader.LoadResourceStream("Spectre.Console.Tests/Data/starwars.flf"));
|
||||
var text = new FigletText(font, "Patrik was here");
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public async Task Should_Render_Text_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(70);
|
||||
var text = new FigletText(FigletFont.Default, "Patrik was here");
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Wrapped")]
|
||||
public async Task Should_Render_Wrapped_Text_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(70);
|
||||
var text = new FigletText(FigletFont.Default, "Spectre.Console");
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_LeftAligned")]
|
||||
public async Task Should_Render_Left_Aligned_Text_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(120);
|
||||
var text = new FigletText(FigletFont.Default, "Spectre.Console")
|
||||
.Alignment(Justify.Left);
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Centered")]
|
||||
public async Task Should_Render_Centered_Text_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(120);
|
||||
var text = new FigletText(FigletFont.Default, "Spectre.Console")
|
||||
.Alignment(Justify.Center);
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_RightAligned")]
|
||||
public async Task Should_Render_Right_Aligned_Text_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(120);
|
||||
var text = new FigletText(FigletFont.Default, "Spectre.Console")
|
||||
.Alignment(Justify.Right);
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public async Task Should_Render_Text_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(70);
|
||||
var text = new FigletText(FigletFont.Default, "Patrik was here");
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Wrapped")]
|
||||
public async Task Should_Render_Wrapped_Text_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(70);
|
||||
var text = new FigletText(FigletFont.Default, "Spectre.Console");
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_LeftAligned")]
|
||||
public async Task Should_Render_Left_Aligned_Text_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(120);
|
||||
var text = new FigletText(FigletFont.Default, "Spectre.Console")
|
||||
.Alignment(Justify.Left);
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Centered")]
|
||||
public async Task Should_Render_Centered_Text_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(120);
|
||||
var text = new FigletText(FigletFont.Default, "Spectre.Console")
|
||||
.Alignment(Justify.Center);
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_RightAligned")]
|
||||
public async Task Should_Render_Right_Aligned_Text_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(120);
|
||||
var text = new FigletText(FigletFont.Default, "Spectre.Console")
|
||||
.Alignment(Justify.Right);
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
await Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
@ -1,200 +1,91 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Grid")]
|
||||
public sealed class GridTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Grid")]
|
||||
public sealed class GridTests
|
||||
public sealed class TheAddColumnMethod
|
||||
{
|
||||
public sealed class TheAddColumnMethod
|
||||
[Fact]
|
||||
public void Should_Throw_If_Rows_Are_Not_Empty()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Throw_If_Rows_Are_Not_Empty()
|
||||
{
|
||||
// Given
|
||||
var grid = new Grid();
|
||||
grid.AddColumn();
|
||||
grid.AddRow("Hello World!");
|
||||
// Given
|
||||
var grid = new Grid();
|
||||
grid.AddColumn();
|
||||
grid.AddRow("Hello World!");
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => grid.AddColumn());
|
||||
// When
|
||||
var result = Record.Exception(() => grid.AddColumn());
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>()
|
||||
.Message.ShouldBe("Cannot add new columns to grid with existing rows.");
|
||||
}
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>()
|
||||
.Message.ShouldBe("Cannot add new columns to grid with existing rows.");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheAddRowMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Throw_If_Rows_Are_Null()
|
||||
{
|
||||
// Given
|
||||
var grid = new Grid();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => grid.AddRow(null));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<ArgumentNullException>()
|
||||
.ParamName.ShouldBe("columns");
|
||||
}
|
||||
|
||||
public sealed class TheAddRowMethod
|
||||
[Fact]
|
||||
public void Should_Add_Empty_Items_If_User_Provides_Less_Row_Items_Than_Columns()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Throw_If_Rows_Are_Null()
|
||||
{
|
||||
// Given
|
||||
var grid = new Grid();
|
||||
// Given
|
||||
var grid = new Grid();
|
||||
grid.AddColumn();
|
||||
grid.AddColumn();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => grid.AddRow(null));
|
||||
// When
|
||||
grid.AddRow("Foo");
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<ArgumentNullException>()
|
||||
.ParamName.ShouldBe("columns");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Add_Empty_Items_If_User_Provides_Less_Row_Items_Than_Columns()
|
||||
{
|
||||
// Given
|
||||
var grid = new Grid();
|
||||
grid.AddColumn();
|
||||
grid.AddColumn();
|
||||
|
||||
// When
|
||||
grid.AddRow("Foo");
|
||||
|
||||
// Then
|
||||
grid.Rows.Count.ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Row_Columns_Are_Greater_Than_Number_Of_Columns()
|
||||
{
|
||||
// Given
|
||||
var grid = new Grid();
|
||||
grid.AddColumn();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => grid.AddRow("Foo", "Bar"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("The number of row columns are greater than the number of grid columns.");
|
||||
}
|
||||
// Then
|
||||
grid.Rows.Count.ShouldBe(1);
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
[ExpectationPath("AddEmptyRow")]
|
||||
public sealed class TheAddEmptyRowMethod
|
||||
[Fact]
|
||||
public void Should_Throw_If_Row_Columns_Are_Greater_Than_Number_Of_Columns()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Add_Empty_Row()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var grid = new Grid();
|
||||
grid.AddColumns(2);
|
||||
grid.AddRow("Foo", "Bar");
|
||||
grid.AddEmptyRow();
|
||||
grid.AddRow("Qux", "Corgi");
|
||||
grid.AddEmptyRow();
|
||||
// Given
|
||||
var grid = new Grid();
|
||||
grid.AddColumn();
|
||||
|
||||
// When
|
||||
console.Write(grid);
|
||||
// When
|
||||
var result = Record.Exception(() => grid.AddRow("Foo", "Bar"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("The number of row columns are greater than the number of grid columns.");
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
[ExpectationPath("AddEmptyRow")]
|
||||
public sealed class TheAddEmptyRowMethod
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Grid_Correctly()
|
||||
public Task Should_Add_Empty_Row()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var grid = new Grid();
|
||||
grid.AddColumn();
|
||||
grid.AddColumn();
|
||||
grid.AddColumn();
|
||||
grid.AddRow("Qux", "Corgi", "Waldo");
|
||||
grid.AddRow("Grault", "Garply", "Fred");
|
||||
|
||||
// When
|
||||
console.Write(grid);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_2")]
|
||||
public Task Should_Render_Grid_Correctly_2()
|
||||
{
|
||||
var console = new TestConsole();
|
||||
var grid = new Grid();
|
||||
grid.AddColumn(new GridColumn { NoWrap = true });
|
||||
grid.AddColumn(new GridColumn { Padding = new Padding(2, 0, 0, 0) });
|
||||
grid.AddRow("[bold]Options[/]", string.Empty);
|
||||
grid.AddRow(" [blue]-h[/], [blue]--help[/]", "Show command line help.");
|
||||
grid.AddRow(" [blue]-c[/], [blue]--configuration[/]", "The configuration to run for.\nThe default for most projects is [green]Debug[/].");
|
||||
|
||||
// When
|
||||
console.Write(grid);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Alignment")]
|
||||
public Task Should_Render_Grid_Column_Alignment_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var grid = new Grid();
|
||||
grid.AddColumn(new GridColumn { Alignment = Justify.Right });
|
||||
grid.AddColumn(new GridColumn { Alignment = Justify.Center });
|
||||
grid.AddColumn(new GridColumn { Alignment = Justify.Left });
|
||||
grid.AddRow("Foo", "Bar", "Baz");
|
||||
grid.AddRow("Qux", "Corgi", "Waldo");
|
||||
grid.AddRow("Grault", "Garply", "Fred");
|
||||
|
||||
// When
|
||||
console.Write(grid);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Padding")]
|
||||
public Task Should_Use_Default_Padding()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var grid = new Grid();
|
||||
grid.AddColumns(3);
|
||||
grid.AddRow("Foo", "Bar", "Baz");
|
||||
grid.AddRow("Qux", "Corgi", "Waldo");
|
||||
grid.AddRow("Grault", "Garply", "Fred");
|
||||
|
||||
// When
|
||||
console.Write(grid);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_ExplicitPadding")]
|
||||
public Task Should_Render_Explicit_Grid_Column_Padding_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var grid = new Grid();
|
||||
grid.AddColumn(new GridColumn { Padding = new Padding(3, 0, 0, 0) });
|
||||
grid.AddColumn(new GridColumn { Padding = new Padding(0, 0, 0, 0) });
|
||||
grid.AddColumn(new GridColumn { Padding = new Padding(0, 0, 3, 0) });
|
||||
grid.AddRow("Foo", "Bar", "Baz");
|
||||
grid.AddRow("Qux", "Corgi", "Waldo");
|
||||
grid.AddRow("Grault", "Garply", "Fred");
|
||||
grid.AddColumns(2);
|
||||
grid.AddRow("Foo", "Bar");
|
||||
grid.AddEmptyRow();
|
||||
grid.AddRow("Qux", "Corgi");
|
||||
grid.AddEmptyRow();
|
||||
|
||||
// When
|
||||
console.Write(grid);
|
||||
@ -203,4 +94,104 @@ namespace Spectre.Console.Tests.Unit
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Grid_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var grid = new Grid();
|
||||
grid.AddColumn();
|
||||
grid.AddColumn();
|
||||
grid.AddColumn();
|
||||
grid.AddRow("Qux", "Corgi", "Waldo");
|
||||
grid.AddRow("Grault", "Garply", "Fred");
|
||||
|
||||
// When
|
||||
console.Write(grid);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_2")]
|
||||
public Task Should_Render_Grid_Correctly_2()
|
||||
{
|
||||
var console = new TestConsole();
|
||||
var grid = new Grid();
|
||||
grid.AddColumn(new GridColumn { NoWrap = true });
|
||||
grid.AddColumn(new GridColumn { Padding = new Padding(2, 0, 0, 0) });
|
||||
grid.AddRow("[bold]Options[/]", string.Empty);
|
||||
grid.AddRow(" [blue]-h[/], [blue]--help[/]", "Show command line help.");
|
||||
grid.AddRow(" [blue]-c[/], [blue]--configuration[/]", "The configuration to run for.\nThe default for most projects is [green]Debug[/].");
|
||||
|
||||
// When
|
||||
console.Write(grid);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Alignment")]
|
||||
public Task Should_Render_Grid_Column_Alignment_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var grid = new Grid();
|
||||
grid.AddColumn(new GridColumn { Alignment = Justify.Right });
|
||||
grid.AddColumn(new GridColumn { Alignment = Justify.Center });
|
||||
grid.AddColumn(new GridColumn { Alignment = Justify.Left });
|
||||
grid.AddRow("Foo", "Bar", "Baz");
|
||||
grid.AddRow("Qux", "Corgi", "Waldo");
|
||||
grid.AddRow("Grault", "Garply", "Fred");
|
||||
|
||||
// When
|
||||
console.Write(grid);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Padding")]
|
||||
public Task Should_Use_Default_Padding()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var grid = new Grid();
|
||||
grid.AddColumns(3);
|
||||
grid.AddRow("Foo", "Bar", "Baz");
|
||||
grid.AddRow("Qux", "Corgi", "Waldo");
|
||||
grid.AddRow("Grault", "Garply", "Fred");
|
||||
|
||||
// When
|
||||
console.Write(grid);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_ExplicitPadding")]
|
||||
public Task Should_Render_Explicit_Grid_Column_Padding_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var grid = new Grid();
|
||||
grid.AddColumn(new GridColumn { Padding = new Padding(3, 0, 0, 0) });
|
||||
grid.AddColumn(new GridColumn { Padding = new Padding(0, 0, 0, 0) });
|
||||
grid.AddColumn(new GridColumn { Padding = new Padding(0, 0, 3, 0) });
|
||||
grid.AddRow("Foo", "Bar", "Baz");
|
||||
grid.AddRow("Qux", "Corgi", "Waldo");
|
||||
grid.AddRow("Grault", "Garply", "Fred");
|
||||
|
||||
// When
|
||||
console.Write(grid);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
@ -1,143 +1,137 @@
|
||||
using System;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public sealed class MarkupTests
|
||||
{
|
||||
public sealed class MarkupTests
|
||||
public sealed class TheLengthProperty
|
||||
{
|
||||
public sealed class TheLengthProperty
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Hello", 5)]
|
||||
[InlineData("Hello\nWorld", 11)]
|
||||
[InlineData("[yellow]Hello[/]", 5)]
|
||||
public void Should_Return_The_Number_Of_Characters(string input, int expected)
|
||||
{
|
||||
// Given
|
||||
var markup = new Markup(input);
|
||||
|
||||
// When
|
||||
var result = markup.Length;
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheLinesProperty
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Hello", 1)]
|
||||
[InlineData("Hello\nWorld", 2)]
|
||||
[InlineData("[yellow]Hello[/]\nWorld", 2)]
|
||||
public void Should_Return_The_Number_Of_Lines(string input, int expected)
|
||||
{
|
||||
// Given
|
||||
var markup = new Markup(input);
|
||||
|
||||
// When
|
||||
var result = markup.Lines;
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheEscapeMethod
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Hello World", "Hello World")]
|
||||
[InlineData("Hello World [", "Hello World [[")]
|
||||
[InlineData("Hello World ]", "Hello World ]]")]
|
||||
[InlineData("Hello [World]", "Hello [[World]]")]
|
||||
[InlineData("Hello [[World]]", "Hello [[[[World]]]]")]
|
||||
public void Should_Escape_Markup_As_Expected(string input, string expected)
|
||||
{
|
||||
// Given, When
|
||||
var result = Markup.Escape(input);
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheRemoveMethod
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Hello World", "Hello World")]
|
||||
[InlineData("Hello [blue]World", "Hello World")]
|
||||
[InlineData("Hello [blue]World[/]", "Hello World")]
|
||||
public void Should_Remove_Markup_From_Text(string input, string expected)
|
||||
{
|
||||
// Given, When
|
||||
var result = Markup.Remove(input);
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Hello [[ World ]")]
|
||||
[InlineData("Hello [[ World ] !")]
|
||||
public void Should_Throw_If_Closing_Tag_Is_Not_Properly_Escaped(string input)
|
||||
[InlineData("Hello", 5)]
|
||||
[InlineData("Hello\nWorld", 11)]
|
||||
[InlineData("[yellow]Hello[/]", 5)]
|
||||
public void Should_Return_The_Number_Of_Characters(string input, int expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => new Markup(input));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("Encountered unescaped ']' token at position 16");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Escape_Markup_Blocks_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var markup = new Markup("Hello [[ World ]] !");
|
||||
|
||||
// When
|
||||
console.Write(markup);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello [ World ] !");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Hello [link=http://example.com]example.com[/]", "Hello example.com")]
|
||||
[InlineData("Hello [link=http://example.com]http://example.com[/]", "Hello http://example.com")]
|
||||
public void Should_Render_Links_As_Expected(string input, string output)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var markup = new Markup(input);
|
||||
|
||||
// When
|
||||
console.Write(markup);
|
||||
var result = markup.Length;
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Fail_With_Brackets_On_Calls_Without_Args()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.MarkupLine("{");
|
||||
|
||||
// Then
|
||||
console.Output.NormalizeLineEndings()
|
||||
.ShouldBe("{\n");
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheLinesProperty
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Hello", 1)]
|
||||
[InlineData("Hello\nWorld", 2)]
|
||||
[InlineData("[yellow]Hello[/]\nWorld", 2)]
|
||||
public void Should_Return_The_Number_Of_Lines(string input, int expected)
|
||||
{
|
||||
// Given
|
||||
var markup = new Markup(input);
|
||||
|
||||
// When
|
||||
var result = markup.Lines;
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheEscapeMethod
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Hello World", "Hello World")]
|
||||
[InlineData("Hello World [", "Hello World [[")]
|
||||
[InlineData("Hello World ]", "Hello World ]]")]
|
||||
[InlineData("Hello [World]", "Hello [[World]]")]
|
||||
[InlineData("Hello [[World]]", "Hello [[[[World]]]]")]
|
||||
public void Should_Escape_Markup_As_Expected(string input, string expected)
|
||||
{
|
||||
// Given, When
|
||||
var result = Markup.Escape(input);
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheRemoveMethod
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Hello World", "Hello World")]
|
||||
[InlineData("Hello [blue]World", "Hello World")]
|
||||
[InlineData("Hello [blue]World[/]", "Hello World")]
|
||||
public void Should_Remove_Markup_From_Text(string input, string expected)
|
||||
{
|
||||
// Given, When
|
||||
var result = Markup.Remove(input);
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Hello [[ World ]")]
|
||||
[InlineData("Hello [[ World ] !")]
|
||||
public void Should_Throw_If_Closing_Tag_Is_Not_Properly_Escaped(string input)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => new Markup(input));
|
||||
|
||||
// Then
|
||||
result.ShouldNotBeNull();
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("Encountered unescaped ']' token at position 16");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Escape_Markup_Blocks_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var markup = new Markup("Hello [[ World ]] !");
|
||||
|
||||
// When
|
||||
console.Write(markup);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello [ World ] !");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Hello [link=http://example.com]example.com[/]", "Hello example.com")]
|
||||
[InlineData("Hello [link=http://example.com]http://example.com[/]", "Hello http://example.com")]
|
||||
public void Should_Render_Links_As_Expected(string input, string output)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var markup = new Markup(input);
|
||||
|
||||
// When
|
||||
console.Write(markup);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Not_Fail_With_Brackets_On_Calls_Without_Args()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.MarkupLine("{");
|
||||
|
||||
// Then
|
||||
console.Output.NormalizeLineEndings()
|
||||
.ShouldBe("{\n");
|
||||
}
|
||||
}
|
||||
|
@ -1,75 +1,68 @@
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Padder")]
|
||||
public sealed class PadderTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Padder")]
|
||||
public sealed class PadderTests
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Padded_Object_Correctly()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Padded_Object_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(60);
|
||||
var table = new Table();
|
||||
table.AddColumn("Foo");
|
||||
table.AddColumn("Bar");
|
||||
table.AddRow("Baz", "Qux");
|
||||
table.AddRow("Corgi", "Waldo");
|
||||
// Given
|
||||
var console = new TestConsole().Width(60);
|
||||
var table = new Table();
|
||||
table.AddColumn("Foo");
|
||||
table.AddColumn("Bar");
|
||||
table.AddRow("Baz", "Qux");
|
||||
table.AddRow("Corgi", "Waldo");
|
||||
|
||||
// When
|
||||
console.Write(new Padder(table).Padding(1, 2, 3, 4));
|
||||
// When
|
||||
console.Write(new Padder(table).Padding(1, 2, 3, 4));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Expanded")]
|
||||
public Task Should_Render_Expanded_Padded_Object_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(60);
|
||||
var table = new Table();
|
||||
table.AddColumn("Foo");
|
||||
table.AddColumn("Bar");
|
||||
table.AddRow("Baz", "Qux");
|
||||
table.AddRow("Corgi", "Waldo");
|
||||
|
||||
// When
|
||||
console.Write(new Padder(table)
|
||||
.Padding(1, 2, 3, 4)
|
||||
.Expand());
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Nested")]
|
||||
public Task Should_Render_Padded_Object_Correctly_When_Nested_Within_Other_Object()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(60);
|
||||
var table = new Table();
|
||||
table.AddColumn("Foo");
|
||||
table.AddColumn("Bar", c => c.PadLeft(0).PadRight(0));
|
||||
table.AddRow("Baz", "Qux");
|
||||
table.AddRow(new Text("Corgi"), new Padder(new Panel("Waldo"))
|
||||
.Padding(2, 1));
|
||||
|
||||
// When
|
||||
console.Write(new Padder(table)
|
||||
.Padding(1, 2, 3, 4)
|
||||
.Expand());
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Expanded")]
|
||||
public Task Should_Render_Expanded_Padded_Object_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(60);
|
||||
var table = new Table();
|
||||
table.AddColumn("Foo");
|
||||
table.AddColumn("Bar");
|
||||
table.AddRow("Baz", "Qux");
|
||||
table.AddRow("Corgi", "Waldo");
|
||||
|
||||
// When
|
||||
console.Write(new Padder(table)
|
||||
.Padding(1, 2, 3, 4)
|
||||
.Expand());
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Nested")]
|
||||
public Task Should_Render_Padded_Object_Correctly_When_Nested_Within_Other_Object()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(60);
|
||||
var table = new Table();
|
||||
table.AddColumn("Foo");
|
||||
table.AddColumn("Bar", c => c.PadLeft(0).PadRight(0));
|
||||
table.AddRow("Baz", "Qux");
|
||||
table.AddRow(new Text("Corgi"), new Padder(new Panel("Waldo"))
|
||||
.Padding(2, 1));
|
||||
|
||||
// When
|
||||
console.Write(new Padder(table)
|
||||
.Padding(1, 2, 3, 4)
|
||||
.Expand());
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
@ -1,309 +1,300 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Rendering;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Panel")]
|
||||
public sealed class PanelTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Panel")]
|
||||
public sealed class PanelTests
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Panel()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Panel()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel(new Text("Hello World")));
|
||||
// When
|
||||
console.Write(new Panel(new Text("Hello World")));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_ZeroPadding")]
|
||||
public Task Should_Render_Panel_With_Padding_Set_To_Zero()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel(new Text("Hello World"))
|
||||
{
|
||||
Padding = new Padding(0, 0, 0, 0),
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Padding")]
|
||||
public Task Should_Render_Panel_With_Padding()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel(new Text("Hello World"))
|
||||
{
|
||||
Padding = new Padding(3, 1, 5, 2),
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header")]
|
||||
public Task Should_Render_Panel_With_Header()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel("Hello World")
|
||||
{
|
||||
Header = new PanelHeader("Greeting"),
|
||||
Expand = true,
|
||||
Padding = new Padding(2, 0, 2, 0),
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_LeftAligned")]
|
||||
public Task Should_Render_Panel_With_Left_Aligned_Header()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel("Hello World")
|
||||
{
|
||||
Header = new PanelHeader("Greeting").LeftAligned(),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_Centered")]
|
||||
public Task Should_Render_Panel_With_Centered_Header()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel("Hello World")
|
||||
{
|
||||
Header = new PanelHeader("Greeting").Centered(),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_RightAligned")]
|
||||
public Task Should_Render_Panel_With_Right_Aligned_Header()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel("Hello World")
|
||||
{
|
||||
Header = new PanelHeader("Greeting").RightAligned(),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_Collapse")]
|
||||
public Task Should_Collapse_Header_If_It_Will_Not_Fit()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(10);
|
||||
|
||||
// When
|
||||
console.Write(new Panel("Hello World")
|
||||
{
|
||||
Header = new PanelHeader("Greeting"),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Unicode")]
|
||||
public Task Should_Render_Panel_With_Unicode_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel(new Text(" \n💩\n ")));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Multiline")]
|
||||
public Task Should_Render_Panel_With_Multiple_Lines()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel(new Text("Hello World\nFoo Bar")));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_LineEndings")]
|
||||
public Task Should_Preserve_Explicit_Line_Ending()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var text = new Panel(
|
||||
new Markup("I heard [underline on blue]you[/] like 📦\n\n\n\nSo I put a 📦 in a 📦"));
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Expand")]
|
||||
public Task Should_Expand_Panel_If_Enabled()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel(new Text("Hello World"))
|
||||
{
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Child_RightAligned")]
|
||||
public Task Should_Justify_Child_To_Right_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(25);
|
||||
|
||||
// When
|
||||
console.Write(
|
||||
new Panel(new Text("Hello World").RightAligned())
|
||||
{
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Child_Centered")]
|
||||
public Task Should_Center_Child_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(25);
|
||||
|
||||
// When
|
||||
console.Write(
|
||||
new Panel(new Text("Hello World").Centered())
|
||||
{
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Child_Panel")]
|
||||
public Task Should_Render_Panel_Inside_Panel_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel(new Panel(new Text("Hello World"))));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Wrap")]
|
||||
public Task Should_Wrap_Content_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(84);
|
||||
var rows = new List<IRenderable>();
|
||||
var grid = new Grid();
|
||||
grid.AddColumn(new GridColumn().PadLeft(2).PadRight(0));
|
||||
grid.AddColumn(new GridColumn().PadLeft(1).PadRight(0));
|
||||
grid.AddRow("at", "[grey]System.Runtime.CompilerServices.TaskAwaiter.[/][yellow]HandleNonSuccessAndDebuggerNotification[/]([blue]Task[/] task)");
|
||||
rows.Add(grid);
|
||||
|
||||
var panel = new Panel(grid)
|
||||
.Expand().RoundedBorder()
|
||||
.BorderStyle(new Style().Foreground(Color.Grey))
|
||||
.Header("[grey]Short paths[/]");
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_CJK")]
|
||||
public Task Should_Wrap_Table_With_CJK_Tables_In_Panel_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
var table = new Table();
|
||||
table.AddColumn("测试");
|
||||
table.AddRow("测试");
|
||||
var panel = new Panel(table);
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_ZeroPadding")]
|
||||
public Task Should_Render_Panel_With_Padding_Set_To_Zero()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel(new Text("Hello World"))
|
||||
{
|
||||
Padding = new Padding(0, 0, 0, 0),
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Padding")]
|
||||
public Task Should_Render_Panel_With_Padding()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel(new Text("Hello World"))
|
||||
{
|
||||
Padding = new Padding(3, 1, 5, 2),
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header")]
|
||||
public Task Should_Render_Panel_With_Header()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel("Hello World")
|
||||
{
|
||||
Header = new PanelHeader("Greeting"),
|
||||
Expand = true,
|
||||
Padding = new Padding(2, 0, 2, 0),
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_LeftAligned")]
|
||||
public Task Should_Render_Panel_With_Left_Aligned_Header()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel("Hello World")
|
||||
{
|
||||
Header = new PanelHeader("Greeting").LeftAligned(),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_Centered")]
|
||||
public Task Should_Render_Panel_With_Centered_Header()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel("Hello World")
|
||||
{
|
||||
Header = new PanelHeader("Greeting").Centered(),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_RightAligned")]
|
||||
public Task Should_Render_Panel_With_Right_Aligned_Header()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel("Hello World")
|
||||
{
|
||||
Header = new PanelHeader("Greeting").RightAligned(),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_Collapse")]
|
||||
public Task Should_Collapse_Header_If_It_Will_Not_Fit()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(10);
|
||||
|
||||
// When
|
||||
console.Write(new Panel("Hello World")
|
||||
{
|
||||
Header = new PanelHeader("Greeting"),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Unicode")]
|
||||
public Task Should_Render_Panel_With_Unicode_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel(new Text(" \n💩\n ")));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Multiline")]
|
||||
public Task Should_Render_Panel_With_Multiple_Lines()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel(new Text("Hello World\nFoo Bar")));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_LineEndings")]
|
||||
public Task Should_Preserve_Explicit_Line_Ending()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var text = new Panel(
|
||||
new Markup("I heard [underline on blue]you[/] like 📦\n\n\n\nSo I put a 📦 in a 📦"));
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Expand")]
|
||||
public Task Should_Expand_Panel_If_Enabled()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel(new Text("Hello World"))
|
||||
{
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Child_RightAligned")]
|
||||
public Task Should_Justify_Child_To_Right_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(25);
|
||||
|
||||
// When
|
||||
console.Write(
|
||||
new Panel(new Text("Hello World").RightAligned())
|
||||
{
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Child_Centered")]
|
||||
public Task Should_Center_Child_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(25);
|
||||
|
||||
// When
|
||||
console.Write(
|
||||
new Panel(new Text("Hello World").Centered())
|
||||
{
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Child_Panel")]
|
||||
public Task Should_Render_Panel_Inside_Panel_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Panel(new Panel(new Text("Hello World"))));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Wrap")]
|
||||
public Task Should_Wrap_Content_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(84);
|
||||
var rows = new List<IRenderable>();
|
||||
var grid = new Grid();
|
||||
grid.AddColumn(new GridColumn().PadLeft(2).PadRight(0));
|
||||
grid.AddColumn(new GridColumn().PadLeft(1).PadRight(0));
|
||||
grid.AddRow("at", "[grey]System.Runtime.CompilerServices.TaskAwaiter.[/][yellow]HandleNonSuccessAndDebuggerNotification[/]([blue]Task[/] task)");
|
||||
rows.Add(grid);
|
||||
|
||||
var panel = new Panel(grid)
|
||||
.Expand().RoundedBorder()
|
||||
.BorderStyle(new Style().Foreground(Color.Grey))
|
||||
.Header("[grey]Short paths[/]");
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_CJK")]
|
||||
public Task Should_Wrap_Table_With_CJK_Tables_In_Panel_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
var table = new Table();
|
||||
table.AddColumn("测试");
|
||||
table.AddRow("测试");
|
||||
var panel = new Panel(table);
|
||||
|
||||
// When
|
||||
console.Write(panel);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
@ -1,83 +1,75 @@
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Rendering;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Rows")]
|
||||
public sealed class RowsTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Rows")]
|
||||
public sealed class RowsTests
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Rows()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Rows()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(60);
|
||||
var rows = new Rows(
|
||||
new IRenderable[]
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(60);
|
||||
var rows = new Rows(
|
||||
new IRenderable[]
|
||||
{
|
||||
new Markup("Hello"),
|
||||
new Table()
|
||||
.AddColumns("Foo", "Bar")
|
||||
.AddRow("Baz", "Qux"),
|
||||
new Markup("World"),
|
||||
});
|
||||
});
|
||||
|
||||
// When
|
||||
console.Write(rows);
|
||||
// When
|
||||
console.Write(rows);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Nested")]
|
||||
public Task Should_Render_Rows_Correctly_Inside_Other_Widget()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(60);
|
||||
var table = new Table()
|
||||
.AddColumns("Foo", "Bar")
|
||||
.AddRow("HELLO WORLD")
|
||||
.AddRow(
|
||||
new Rows(new IRenderable[]
|
||||
{
|
||||
new Markup("Hello"),
|
||||
new Markup("World"),
|
||||
}), new Text("Qux"));
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Expanded_And_Nested")]
|
||||
public Task Should_Render_Rows_Correctly_Inside_Other_Widget_When_Expanded()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(60);
|
||||
var table = new Table()
|
||||
.AddColumns("Foo", "Bar")
|
||||
.AddRow("HELLO WORLD")
|
||||
.AddRow(
|
||||
new Rows(new IRenderable[]
|
||||
{
|
||||
new Markup("Hello"),
|
||||
new Markup("World"),
|
||||
}).Expand(), new Text("Qux"));
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Nested")]
|
||||
public Task Should_Render_Rows_Correctly_Inside_Other_Widget()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(60);
|
||||
var table = new Table()
|
||||
.AddColumns("Foo", "Bar")
|
||||
.AddRow("HELLO WORLD")
|
||||
.AddRow(
|
||||
new Rows(new IRenderable[]
|
||||
{
|
||||
new Markup("Hello"),
|
||||
new Markup("World"),
|
||||
}), new Text("Qux"));
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Expanded_And_Nested")]
|
||||
public Task Should_Render_Rows_Correctly_Inside_Other_Widget_When_Expanded()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(60);
|
||||
var table = new Table()
|
||||
.AddColumns("Foo", "Bar")
|
||||
.AddRow("HELLO WORLD")
|
||||
.AddRow(
|
||||
new Rows(new IRenderable[]
|
||||
{
|
||||
new Markup("Hello"),
|
||||
new Markup("World"),
|
||||
}).Expand(), new Text("Qux"));
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
@ -1,158 +1,150 @@
|
||||
using System.Threading.Tasks;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Rule")]
|
||||
public sealed class RuleTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Rule")]
|
||||
public sealed class RuleTests
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Default_Rule_Without_Title()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Default_Rule_Without_Title()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule());
|
||||
// When
|
||||
console.Write(new Rule());
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Border_NoHeader")]
|
||||
public Task Should_Render_Default_Rule_With_Specified_Border()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule().DoubleBorder());
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Border_Header")]
|
||||
public Task Should_Render_With_Specified_Box()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule("Hello World").DoubleBorder());
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_DefaultAlignment")]
|
||||
public Task Should_Render_Default_Rule_With_Title_Centered_By_Default()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule("Hello World"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_LeftAligned")]
|
||||
public Task Should_Render_Default_Rule_With_Title_Left_Aligned()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule("Hello World")
|
||||
{
|
||||
Alignment = Justify.Left,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_RightAligned")]
|
||||
public Task Should_Render_Default_Rule_With_Title_Right_Aligned()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule("Hello World")
|
||||
{
|
||||
Alignment = Justify.Right,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Linebreaks")]
|
||||
public Task Should_Convert_Line_Breaks_In_Title_To_Spaces()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule("Hello\nWorld\r\n!"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Truncate")]
|
||||
public Task Should_Truncate_Title()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule(" Hello World "));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1, "Hello World Hello World Hello World Hello World Hello World", "─")]
|
||||
[InlineData(2, "Hello World Hello World Hello World Hello World Hello World", "──")]
|
||||
[InlineData(3, "Hello World Hello World Hello World Hello World Hello World", "───")]
|
||||
[InlineData(4, "Hello World Hello World Hello World Hello World Hello World", "────")]
|
||||
[InlineData(5, "Hello World Hello World Hello World Hello World Hello World", "─────")]
|
||||
[InlineData(6, "Hello World Hello World Hello World Hello World Hello World", "──────")]
|
||||
[InlineData(7, "Hello World Hello World Hello World Hello World Hello World", "───────")]
|
||||
[InlineData(8, "Hello World Hello World Hello World Hello World Hello World", "── H… ──")]
|
||||
[InlineData(8, "A", "── A ───")]
|
||||
[InlineData(8, "AB", "── AB ──")]
|
||||
[InlineData(8, "ABC", "── A… ──")]
|
||||
[InlineData(40, "Hello World Hello World Hello World Hello World Hello World", "──── Hello World Hello World Hello… ────")]
|
||||
public void Should_Truncate_Too_Long_Title(int width, string input, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(width);
|
||||
|
||||
// When
|
||||
console.Write(new Rule(input));
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(1);
|
||||
console.Lines[0].ShouldBe(expected);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Border_NoHeader")]
|
||||
public Task Should_Render_Default_Rule_With_Specified_Border()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule().DoubleBorder());
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Border_Header")]
|
||||
public Task Should_Render_With_Specified_Box()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule("Hello World").DoubleBorder());
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_DefaultAlignment")]
|
||||
public Task Should_Render_Default_Rule_With_Title_Centered_By_Default()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule("Hello World"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_LeftAligned")]
|
||||
public Task Should_Render_Default_Rule_With_Title_Left_Aligned()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule("Hello World")
|
||||
{
|
||||
Alignment = Justify.Left,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Header_RightAligned")]
|
||||
public Task Should_Render_Default_Rule_With_Title_Right_Aligned()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule("Hello World")
|
||||
{
|
||||
Alignment = Justify.Right,
|
||||
});
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Linebreaks")]
|
||||
public Task Should_Convert_Line_Breaks_In_Title_To_Spaces()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule("Hello\nWorld\r\n!"));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_Truncate")]
|
||||
public Task Should_Truncate_Title()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(40);
|
||||
|
||||
// When
|
||||
console.Write(new Rule(" Hello World "));
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1, "Hello World Hello World Hello World Hello World Hello World", "─")]
|
||||
[InlineData(2, "Hello World Hello World Hello World Hello World Hello World", "──")]
|
||||
[InlineData(3, "Hello World Hello World Hello World Hello World Hello World", "───")]
|
||||
[InlineData(4, "Hello World Hello World Hello World Hello World Hello World", "────")]
|
||||
[InlineData(5, "Hello World Hello World Hello World Hello World Hello World", "─────")]
|
||||
[InlineData(6, "Hello World Hello World Hello World Hello World Hello World", "──────")]
|
||||
[InlineData(7, "Hello World Hello World Hello World Hello World Hello World", "───────")]
|
||||
[InlineData(8, "Hello World Hello World Hello World Hello World Hello World", "── H… ──")]
|
||||
[InlineData(8, "A", "── A ───")]
|
||||
[InlineData(8, "AB", "── AB ──")]
|
||||
[InlineData(8, "ABC", "── A… ──")]
|
||||
[InlineData(40, "Hello World Hello World Hello World Hello World Hello World", "──── Hello World Hello World Hello… ────")]
|
||||
public void Should_Truncate_Too_Long_Title(int width, string input, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(width);
|
||||
|
||||
// When
|
||||
console.Write(new Rule(input));
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(1);
|
||||
console.Lines[0].ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
@ -1,131 +1,119 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Table/Rows/Extensions")]
|
||||
public sealed class TableRowCollectionExtensionsTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Table/Rows/Extensions")]
|
||||
public sealed class TableRowCollectionExtensionsTests
|
||||
public sealed class TheAddRowMethod
|
||||
{
|
||||
[UsesVerify]
|
||||
public sealed class TheAddRowMethod
|
||||
[Fact]
|
||||
[Expectation("Add", "Renderables")]
|
||||
public Task Should_Add_Renderables()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Add", "Renderables")]
|
||||
public Task Should_Add_Renderables()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddRow(new[] { new Text("1"), new Text("1-2") });
|
||||
table.AddRow(new[] { new Text("2"), new Text("2-2") });
|
||||
table.AddRow(new[] { new Text("3"), new Text("3-2") });
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddRow(new[] { new Text("1"), new Text("1-2") });
|
||||
table.AddRow(new[] { new Text("2"), new Text("2-2") });
|
||||
table.AddRow(new[] { new Text("3"), new Text("3-2") });
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Add", "Strings")]
|
||||
public Task Should_Add_Strings()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddRow("1", "1-2");
|
||||
table.AddRow("2", "2-2");
|
||||
table.AddRow("3", "3-2");
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class TheInsertRowMethod
|
||||
[Fact]
|
||||
[Expectation("Add", "Strings")]
|
||||
public Task Should_Add_Strings()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Insert", "Renderables")]
|
||||
public Task Should_Insert_Renderables()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddRow(new[] { new Text("1"), new Text("1-2") });
|
||||
table.AddRow(new[] { new Text("2"), new Text("2-2") });
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddRow("1", "1-2");
|
||||
table.AddRow("2", "2-2");
|
||||
table.AddRow("3", "3-2");
|
||||
|
||||
// When
|
||||
table.InsertRow(1, new[] { new Text("3"), new Text("3-2") });
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
console.Write(table);
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Insert", "Strings")]
|
||||
public Task Should_Insert_Strings()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddRow("1", "1-2");
|
||||
table.AddRow("2", "2-2");
|
||||
|
||||
// When
|
||||
table.InsertRow(1, "3", "3-2");
|
||||
|
||||
|
||||
// Then
|
||||
console.Write(table);
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class TheRemoveRowMethod
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Remove")]
|
||||
public Task Should_Remove_Row()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddRow(new[] { new Text("1"), new Text("1-2") });
|
||||
table.AddRow(new[] { new Text("2"), new Text("2-2") });
|
||||
table.AddRow(new[] { new Text("3"), new Text("3-2") });
|
||||
|
||||
// When
|
||||
table.RemoveRow(1);
|
||||
|
||||
// Then
|
||||
console.Write(table);
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class TheInsertRowMethod
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Insert", "Renderables")]
|
||||
public Task Should_Insert_Renderables()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddRow(new[] { new Text("1"), new Text("1-2") });
|
||||
table.AddRow(new[] { new Text("2"), new Text("2-2") });
|
||||
|
||||
// When
|
||||
table.InsertRow(1, new[] { new Text("3"), new Text("3-2") });
|
||||
|
||||
// Then
|
||||
console.Write(table);
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Insert", "Strings")]
|
||||
public Task Should_Insert_Strings()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddRow("1", "1-2");
|
||||
table.AddRow("2", "2-2");
|
||||
|
||||
// When
|
||||
table.InsertRow(1, "3", "3-2");
|
||||
|
||||
// Then
|
||||
console.Write(table);
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class TheRemoveRowMethod
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Remove")]
|
||||
public Task Should_Remove_Row()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddRow(new[] { new Text("1"), new Text("1-2") });
|
||||
table.AddRow(new[] { new Text("2"), new Text("2-2") });
|
||||
table.AddRow(new[] { new Text("3"), new Text("3-2") });
|
||||
|
||||
// When
|
||||
table.RemoveRow(1);
|
||||
|
||||
// Then
|
||||
console.Write(table);
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,366 +1,353 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[ExpectationPath("Widgets/Table/Rows")]
|
||||
public sealed class TableRowCollectionTests
|
||||
{
|
||||
[ExpectationPath("Widgets/Table/Rows")]
|
||||
public sealed class TableRowCollectionTests
|
||||
[UsesVerify]
|
||||
public sealed class TheAddMethod
|
||||
{
|
||||
[UsesVerify]
|
||||
public sealed class TheAddMethod
|
||||
[Fact]
|
||||
public void Should_Throw_If_Columns_Are_Null()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Throw_If_Columns_Are_Null()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
// Given
|
||||
var table = new Table();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.Rows.Add(null));
|
||||
// When
|
||||
var result = Record.Exception(() => table.Rows.Add(null));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<ArgumentNullException>()
|
||||
.ParamName.ShouldBe("columns");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Add_Row_To_Collection()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
|
||||
// When
|
||||
table.Rows.Add(new[] { Text.Empty });
|
||||
|
||||
// Then
|
||||
table.Rows.Count.ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Index_Of_Added_Row()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { Text.Empty });
|
||||
|
||||
// When
|
||||
var result = table.Rows.Add(new[] { Text.Empty });
|
||||
|
||||
// Then
|
||||
result.ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Add")]
|
||||
public Task Should_Add_Item_At_Correct_Place()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3") });
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
// Then
|
||||
result.ShouldBeOfType<ArgumentNullException>()
|
||||
.ParamName.ShouldBe("columns");
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class TheInsertMethod
|
||||
[Fact]
|
||||
public void Should_Add_Row_To_Collection()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Throw_If_Columns_Are_Null()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.Rows.Insert(0, null));
|
||||
// When
|
||||
table.Rows.Add(new[] { Text.Empty });
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<ArgumentNullException>()
|
||||
.ParamName.ShouldBe("columns");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Insert_Row()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { Text.Empty });
|
||||
|
||||
// When
|
||||
table.Rows.Insert(0, new[] { Text.Empty });
|
||||
|
||||
// Then
|
||||
table.Rows.Count.ShouldBe(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Index_Of_Inserted_Row()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
|
||||
// When
|
||||
var result = table.Rows.Insert(1, new[] { new Text("3") });
|
||||
|
||||
// Then
|
||||
result.ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Insert")]
|
||||
public Task Should_Insert_Item_At_Correct_Place()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Insert(1, new[] { new Text("3") });
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
// Then
|
||||
table.Rows.Count.ShouldBe(1);
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class TheRemoveMethod
|
||||
[Fact]
|
||||
public void Should_Return_Index_Of_Added_Row()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Throw_If_Index_Is_Negative()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { Text.Empty });
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.Rows.RemoveAt(-1));
|
||||
// When
|
||||
var result = table.Rows.Add(new[] { Text.Empty });
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<IndexOutOfRangeException>()
|
||||
.Message.ShouldBe("Table row index cannot be negative.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Index_Is_Larger_Than_Number_Of_Rows()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3") });
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.Rows.RemoveAt(3));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<IndexOutOfRangeException>()
|
||||
.Message.ShouldBe("Table row index cannot exceed the number of rows in the table.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Remove")]
|
||||
public Task Should_Remove_Row()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3") });
|
||||
table.Rows.RemoveAt(1);
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
// Then
|
||||
result.ShouldBe(1);
|
||||
}
|
||||
|
||||
public sealed class TheClearMethod
|
||||
[Fact]
|
||||
[Expectation("Add")]
|
||||
public Task Should_Add_Item_At_Correct_Place()
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Remove_All_Rows()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3") });
|
||||
table.Rows.Clear();
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3") });
|
||||
|
||||
// When
|
||||
var result = table.Rows.Count;
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
result.ShouldBe(0);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class TheUpdateMethod
|
||||
{
|
||||
[Fact]
|
||||
public Task Should_Update_Row_With_String()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddColumn("Column #3");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
|
||||
|
||||
table.UpdateCell(2, 2, "5");
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public Task Should_Update_Row_With_Renderable()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddColumn("Column #3");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
|
||||
|
||||
table.UpdateCell(2, 2, new Markup("5"));
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Index_Is_Larger_Than_Number_Of_Rows()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddColumn("Column #3");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
|
||||
table.UpdateCell(2, 2, "5");
|
||||
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.UpdateCell(5, 2, "5"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<IndexOutOfRangeException>()
|
||||
.Message.ShouldBe("Table row index cannot exceed the number of rows in the table.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Index_Is_Larger_Than_Number_Of_Columns()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddColumn("Column #3");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
|
||||
table.UpdateCell(2, 2, "5");
|
||||
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.UpdateCell(2, 5, "5"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<IndexOutOfRangeException>()
|
||||
.Message.ShouldBe("Table column index cannot exceed the number of rows in the table.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Index_Row_Is_Negative()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddColumn("Column #3");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
|
||||
table.UpdateCell(2, 2, "5");
|
||||
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.UpdateCell(-1, 2, "5"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<IndexOutOfRangeException>()
|
||||
.Message.ShouldBe("Table row index cannot be negative.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Index_Column_Is_Negative()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddColumn("Column #3");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
|
||||
table.UpdateCell(2, 2, "5");
|
||||
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.UpdateCell(2, -1, "5"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<IndexOutOfRangeException>()
|
||||
.Message.ShouldBe("Table column index cannot be negative.");
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class TheInsertMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Throw_If_Columns_Are_Null()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.Rows.Insert(0, null));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<ArgumentNullException>()
|
||||
.ParamName.ShouldBe("columns");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Insert_Row()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { Text.Empty });
|
||||
|
||||
// When
|
||||
table.Rows.Insert(0, new[] { Text.Empty });
|
||||
|
||||
// Then
|
||||
table.Rows.Count.ShouldBe(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Return_Index_Of_Inserted_Row()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
|
||||
// When
|
||||
var result = table.Rows.Insert(1, new[] { new Text("3") });
|
||||
|
||||
// Then
|
||||
result.ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Insert")]
|
||||
public Task Should_Insert_Item_At_Correct_Place()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Insert(1, new[] { new Text("3") });
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class TheRemoveMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Throw_If_Index_Is_Negative()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.Rows.RemoveAt(-1));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<IndexOutOfRangeException>()
|
||||
.Message.ShouldBe("Table row index cannot be negative.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Index_Is_Larger_Than_Number_Of_Rows()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3") });
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.Rows.RemoveAt(3));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<IndexOutOfRangeException>()
|
||||
.Message.ShouldBe("Table row index cannot exceed the number of rows in the table.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Remove")]
|
||||
public Task Should_Remove_Row()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3") });
|
||||
table.Rows.RemoveAt(1);
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheClearMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Remove_All_Rows()
|
||||
{
|
||||
// Given
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3") });
|
||||
table.Rows.Clear();
|
||||
|
||||
// When
|
||||
var result = table.Rows.Count;
|
||||
|
||||
// Then
|
||||
result.ShouldBe(0);
|
||||
}
|
||||
}
|
||||
|
||||
[UsesVerify]
|
||||
public sealed class TheUpdateMethod
|
||||
{
|
||||
[Fact]
|
||||
public Task Should_Update_Row_With_String()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddColumn("Column #3");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
|
||||
|
||||
table.UpdateCell(2, 2, "5");
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public Task Should_Update_Row_With_Renderable()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddColumn("Column #3");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
|
||||
|
||||
table.UpdateCell(2, 2, new Markup("5"));
|
||||
|
||||
// When
|
||||
console.Write(table);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Index_Is_Larger_Than_Number_Of_Rows()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddColumn("Column #3");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
|
||||
table.UpdateCell(2, 2, "5");
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.UpdateCell(5, 2, "5"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<IndexOutOfRangeException>()
|
||||
.Message.ShouldBe("Table row index cannot exceed the number of rows in the table.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Index_Is_Larger_Than_Number_Of_Columns()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddColumn("Column #3");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
|
||||
table.UpdateCell(2, 2, "5");
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.UpdateCell(2, 5, "5"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<IndexOutOfRangeException>()
|
||||
.Message.ShouldBe("Table column index cannot exceed the number of rows in the table.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Index_Row_Is_Negative()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddColumn("Column #3");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
|
||||
table.UpdateCell(2, 2, "5");
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.UpdateCell(-1, 2, "5"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<IndexOutOfRangeException>()
|
||||
.Message.ShouldBe("Table row index cannot be negative.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Index_Column_Is_Negative()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var table = new Table();
|
||||
table.AddColumn("Column #1");
|
||||
table.AddColumn("Column #2");
|
||||
table.AddColumn("Column #3");
|
||||
table.Rows.Add(new[] { new Text("1") });
|
||||
table.Rows.Add(new[] { new Text("2") });
|
||||
table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
|
||||
table.UpdateCell(2, 2, "5");
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => table.UpdateCell(2, -1, "5"));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<IndexOutOfRangeException>()
|
||||
.Message.ShouldBe("Table column index cannot be negative.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,158 +1,152 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Rendering;
|
||||
using Spectre.Console.Testing;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
public sealed class TextTests
|
||||
{
|
||||
public sealed class TextTests
|
||||
public sealed class TheLengthProperty
|
||||
{
|
||||
public sealed class TheLengthProperty
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Hello", 5)]
|
||||
[InlineData("Hello\nWorld", 11)]
|
||||
public void Should_Return_The_Number_Of_Characters(string input, int expected)
|
||||
{
|
||||
// Given
|
||||
var markup = new Text(input);
|
||||
|
||||
// When
|
||||
var result = markup.Length;
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheLinesProperty
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Hello", 1)]
|
||||
[InlineData("Hello\nWorld", 2)]
|
||||
public void Should_Return_The_Number_Of_Lines(string input, int expected)
|
||||
{
|
||||
// Given
|
||||
var markup = new Text(input);
|
||||
|
||||
// When
|
||||
var result = markup.Lines;
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Consider_The_Longest_Word_As_Minimum_Width()
|
||||
{
|
||||
// Given
|
||||
var caps = new TestCapabilities { Unicode = true };
|
||||
var text = new Text("Foo Bar Baz\nQux\nLol mobile");
|
||||
|
||||
// When
|
||||
var result = ((IRenderable)text).Measure(caps.CreateRenderContext(), 80);
|
||||
|
||||
// Then
|
||||
result.Min.ShouldBe(6);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Consider_The_Longest_Line_As_Maximum_Width()
|
||||
{
|
||||
// Given
|
||||
var caps = new TestCapabilities { Unicode = true };
|
||||
var text = new Text("Foo Bar Baz\nQux\nLol mobile");
|
||||
|
||||
// When
|
||||
var result = ((IRenderable)text).Measure(caps.CreateRenderContext(), 80);
|
||||
|
||||
// Then
|
||||
result.Max.ShouldBe(11);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_Unstyled_Text_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var text = new Text("Hello World");
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello World");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Hello\n\nWorld\n\n")]
|
||||
[InlineData("Hello\r\n\r\nWorld\r\n\r\n")]
|
||||
public void Should_Write_Line_Breaks(string input)
|
||||
[InlineData("Hello", 5)]
|
||||
[InlineData("Hello\nWorld", 11)]
|
||||
public void Should_Return_The_Number_Of_Characters(string input, int expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var text = new Text(input);
|
||||
var markup = new Text(input);
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
var result = markup.Length;
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello\n\nWorld\n\n");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_Panel_2()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Markup("[b]Hello World[/]\n[yellow]Hello World[/]"));
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(2);
|
||||
console.Lines[0].ShouldBe("Hello World");
|
||||
console.Lines[1].ShouldBe("Hello World");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(5, "Hello World", "Hello\nWorld")]
|
||||
[InlineData(10, "Hello Sweet Nice World", "Hello \nSweet Nice\nWorld")]
|
||||
public void Should_Split_Unstyled_Text_To_New_Lines_If_Width_Exceeds_Console_Width(
|
||||
int width, string input, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(width);
|
||||
var text = new Text(input);
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
console.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Overflow.Fold, "foo \npneumonoultram\nicroscopicsili\ncovolcanoconio\nsis bar qux")]
|
||||
[InlineData(Overflow.Crop, "foo \npneumonoultram\nbar qux")]
|
||||
[InlineData(Overflow.Ellipsis, "foo \npneumonoultra…\nbar qux")]
|
||||
public void Should_Overflow_Text_Correctly(Overflow overflow, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(14);
|
||||
var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux")
|
||||
.Overflow(overflow);
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
console.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe(expected);
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TheLinesProperty
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Hello", 1)]
|
||||
[InlineData("Hello\nWorld", 2)]
|
||||
public void Should_Return_The_Number_Of_Lines(string input, int expected)
|
||||
{
|
||||
// Given
|
||||
var markup = new Text(input);
|
||||
|
||||
// When
|
||||
var result = markup.Lines;
|
||||
|
||||
// Then
|
||||
result.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Consider_The_Longest_Word_As_Minimum_Width()
|
||||
{
|
||||
// Given
|
||||
var caps = new TestCapabilities { Unicode = true };
|
||||
var text = new Text("Foo Bar Baz\nQux\nLol mobile");
|
||||
|
||||
// When
|
||||
var result = ((IRenderable)text).Measure(caps.CreateRenderContext(), 80);
|
||||
|
||||
// Then
|
||||
result.Min.ShouldBe(6);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Consider_The_Longest_Line_As_Maximum_Width()
|
||||
{
|
||||
// Given
|
||||
var caps = new TestCapabilities { Unicode = true };
|
||||
var text = new Text("Foo Bar Baz\nQux\nLol mobile");
|
||||
|
||||
// When
|
||||
var result = ((IRenderable)text).Measure(caps.CreateRenderContext(), 80);
|
||||
|
||||
// Then
|
||||
result.Max.ShouldBe(11);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_Unstyled_Text_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var text = new Text("Hello World");
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello World");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Hello\n\nWorld\n\n")]
|
||||
[InlineData("Hello\r\n\r\nWorld\r\n\r\n")]
|
||||
public void Should_Write_Line_Breaks(string input)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var text = new Text(input);
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello\n\nWorld\n\n");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_Panel_2()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
// When
|
||||
console.Write(new Markup("[b]Hello World[/]\n[yellow]Hello World[/]"));
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(2);
|
||||
console.Lines[0].ShouldBe("Hello World");
|
||||
console.Lines[1].ShouldBe("Hello World");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(5, "Hello World", "Hello\nWorld")]
|
||||
[InlineData(10, "Hello Sweet Nice World", "Hello \nSweet Nice\nWorld")]
|
||||
public void Should_Split_Unstyled_Text_To_New_Lines_If_Width_Exceeds_Console_Width(
|
||||
int width, string input, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(width);
|
||||
var text = new Text(input);
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
console.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Overflow.Fold, "foo \npneumonoultram\nicroscopicsili\ncovolcanoconio\nsis bar qux")]
|
||||
[InlineData(Overflow.Crop, "foo \npneumonoultram\nbar qux")]
|
||||
[InlineData(Overflow.Ellipsis, "foo \npneumonoultra…\nbar qux")]
|
||||
public void Should_Overflow_Text_Correctly(Overflow overflow, string expected)
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole().Width(14);
|
||||
var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux")
|
||||
.Overflow(overflow);
|
||||
|
||||
// When
|
||||
console.Write(text);
|
||||
|
||||
// Then
|
||||
console.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
@ -1,85 +1,76 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Testing;
|
||||
using Spectre.Verify.Extensions;
|
||||
using VerifyXunit;
|
||||
using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Tree")]
|
||||
public class TreeTests
|
||||
{
|
||||
[UsesVerify]
|
||||
[ExpectationPath("Widgets/Tree")]
|
||||
public class TreeTests
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Tree_Correctly()
|
||||
{
|
||||
[Fact]
|
||||
[Expectation("Render")]
|
||||
public Task Should_Render_Tree_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
var tree = new Tree(new Text("Root node")).Guide(TreeGuide.DoubleLine);
|
||||
var tree = new Tree(new Text("Root node")).Guide(TreeGuide.DoubleLine);
|
||||
|
||||
var nestedChildren = Enumerable.Range(0, 10).Select(x => new Text($"multiple\nline {x}"));
|
||||
var child2 = new TreeNode(new Text("child2"));
|
||||
var child2Child = new TreeNode(new Text("child2-1"));
|
||||
child2.AddNode(child2Child);
|
||||
child2Child.AddNode(new TreeNode(new Text("Child2-1-1\nchild")));
|
||||
var child3 = new TreeNode(new Text("child3"));
|
||||
var child3Child = new TreeNode(new Text("single leaf\nmultiline"));
|
||||
child3Child.AddNode(new TreeNode(new Calendar(2021, 01)));
|
||||
child3.AddNode(child3Child);
|
||||
var nestedChildren = Enumerable.Range(0, 10).Select(x => new Text($"multiple\nline {x}"));
|
||||
var child2 = new TreeNode(new Text("child2"));
|
||||
var child2Child = new TreeNode(new Text("child2-1"));
|
||||
child2.AddNode(child2Child);
|
||||
child2Child.AddNode(new TreeNode(new Text("Child2-1-1\nchild")));
|
||||
var child3 = new TreeNode(new Text("child3"));
|
||||
var child3Child = new TreeNode(new Text("single leaf\nmultiline"));
|
||||
child3Child.AddNode(new TreeNode(new Calendar(2021, 01)));
|
||||
child3.AddNode(child3Child);
|
||||
|
||||
tree.AddNode("child1").AddNodes(nestedChildren);
|
||||
tree.AddNode(child2);
|
||||
tree.AddNode(child3);
|
||||
tree.AddNode("child4");
|
||||
tree.AddNode("child1").AddNodes(nestedChildren);
|
||||
tree.AddNode(child2);
|
||||
tree.AddNode(child3);
|
||||
tree.AddNode("child4");
|
||||
|
||||
// When
|
||||
console.Write(tree);
|
||||
// When
|
||||
console.Write(tree);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_NoChildren")]
|
||||
public Task Should_Render_Tree_With_No_Child_Nodes_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var tree = new Tree(new Text("Root node"));
|
||||
|
||||
// When
|
||||
console.Write(tree);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Tree_Contains_Cycles()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
var child2 = new TreeNode(new Text("child 2"));
|
||||
var child3 = new TreeNode(new Text("child 3"));
|
||||
var child1 = new TreeNode(new Text("child 1"));
|
||||
child1.AddNodes(child2, child3);
|
||||
var root = new TreeNode(new Text("Branch Node"));
|
||||
root.AddNodes(child1);
|
||||
child2.AddNode(root);
|
||||
|
||||
var tree = new Tree("root node");
|
||||
tree.AddNodes(root);
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => console.Write(tree));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CircularTreeException>();
|
||||
}
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Expectation("Render_NoChildren")]
|
||||
public Task Should_Render_Tree_With_No_Child_Nodes_Correctly()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
var tree = new Tree(new Text("Root node"));
|
||||
|
||||
// When
|
||||
console.Write(tree);
|
||||
|
||||
// Then
|
||||
return Verifier.Verify(console.Output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Tree_Contains_Cycles()
|
||||
{
|
||||
// Given
|
||||
var console = new TestConsole();
|
||||
|
||||
var child2 = new TreeNode(new Text("child 2"));
|
||||
var child3 = new TreeNode(new Text("child 3"));
|
||||
var child1 = new TreeNode(new Text("child 1"));
|
||||
child1.AddNodes(child2, child3);
|
||||
var root = new TreeNode(new Text("Branch Node"));
|
||||
root.AddNodes(child1);
|
||||
child2.AddNode(root);
|
||||
|
||||
var tree = new Tree("root node");
|
||||
tree.AddNodes(root);
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => console.Write(tree));
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<CircularTreeException>();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user