namespace Spectre.Console.Tests.Unit.Cli; public sealed partial class CommandAppTests { [UsesVerify] [ExpectationPath("Parsing")] public sealed class Parsing { [UsesVerify] [ExpectationPath("UnknownCommand")] public sealed class UnknownCommand { [Fact] [Expectation("Test_1")] public Task Should_Return_Correct_Text_When_Command_Is_Unknown() { // Given var fixture = new Fixture(); fixture.Configure(config => { config.AddCommand("dog"); }); // When var result = fixture.Run("cat", "14"); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_2")] public Task Should_Return_Correct_Text_For_Unknown_Command_When_Current_Command_Has_No_Arguments() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("empty"); }); // When var result = fixture.Run("empty", "other"); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_3")] public Task Should_Return_Correct_Text_With_Suggestion_When_Command_Followed_By_Argument_Is_Unknown_And_Distance_Is_Small() { // Given var fixture = new Fixture(); fixture.Configure(config => { config.AddBranch("dog", a => { a.AddCommand("cat"); }); }); // When var result = fixture.Run("dog", "bat", "14"); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_4")] public Task Should_Return_Correct_Text_With_Suggestion_When_Root_Command_Followed_By_Argument_Is_Unknown_And_Distance_Is_Small() { // Given var fixture = new Fixture(); fixture.Configure(config => { config.AddCommand("cat"); }); // When var result = fixture.Run("bat", "14"); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_5")] public Task Should_Return_Correct_Text_With_Suggestion_And_No_Arguments_When_Root_Command_Is_Unknown_And_Distance_Is_Small() { // Given var fixture = new Fixture(); fixture.WithDefaultCommand>(); fixture.Configure(config => { config.AddCommand>("cat"); }); // When var result = fixture.Run("bat"); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_6")] public Task Should_Return_Correct_Text_With_Suggestion_And_No_Arguments_When_Command_Is_Unknown_And_Distance_Is_Small() { // Given var fixture = new Fixture(); fixture.WithDefaultCommand>(); fixture.Configure(configurator => { configurator.AddBranch("dog", a => { a.AddCommand("cat"); }); }); // When var result = fixture.Run("dog", "bat"); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_7")] public Task Should_Return_Correct_Text_With_Suggestion_When_Root_Command_After_Argument_Is_Unknown_And_Distance_Is_Small() { // Given var fixture = new Fixture(); fixture.WithDefaultCommand>(); fixture.Configure(configurator => { configurator.AddCommand>("bar"); }); // When var result = fixture.Run("qux", "bat"); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_8")] public Task Should_Return_Correct_Text_With_Suggestion_When_Command_After_Argument_Is_Unknown_And_Distance_Is_Small() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddBranch("foo", a => { a.AddCommand>("bar"); }); }); // When var result = fixture.Run("foo", "qux", "bat"); // Then return Verifier.Verify(result); } } [UsesVerify] [ExpectationPath("CannotAssignValueToFlag")] public sealed class CannotAssignValueToFlag { [Fact] [Expectation("Test_1")] public Task Should_Return_Correct_Text_For_Long_Option() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", "--alive", "foo"); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_2")] public Task Should_Return_Correct_Text_For_Short_Option() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", "-a", "foo"); // Then return Verifier.Verify(result); } } [UsesVerify] [ExpectationPath("NoValueForOption")] public sealed class NoValueForOption { [Fact] [Expectation("Test_1")] public Task Should_Return_Correct_Text_For_Long_Option() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", "--name"); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_2")] public Task Should_Return_Correct_Text_For_Short_Option() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", "-n"); // Then return Verifier.Verify(result); } } [UsesVerify] [ExpectationPath("NoMatchingArgument")] public sealed class NoMatchingArgument { [Fact] [Expectation("Test_1")] public Task Should_Return_Correct_Text() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("giraffe"); }); // When var result = fixture.Run("giraffe", "foo", "bar", "baz"); // Then return Verifier.Verify(result); } } [UsesVerify] [ExpectationPath("UnexpectedOption")] public sealed class UnexpectedOption { [Fact] [Expectation("Test_1")] public Task Should_Return_Correct_Text_For_Long_Option() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("--foo"); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_2")] public Task Should_Return_Correct_Text_For_Short_Option() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("-f"); // Then return Verifier.Verify(result); } } [UsesVerify] [ExpectationPath("UnknownOption")] public sealed class UnknownOption { [Fact] [Expectation("Test_1")] public Task Should_Return_Correct_Text_For_Long_Option_If_Strict_Mode_Is_Enabled() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.UseStrictParsing(); configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", "--unknown"); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_2")] public Task Should_Return_Correct_Text_For_Short_Option_If_Strict_Mode_Is_Enabled() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.UseStrictParsing(); configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", "-u"); // Then return Verifier.Verify(result); } } [UsesVerify] [ExpectationPath("UnterminatedQuote")] public sealed class UnterminatedQuote { [Fact] [Expectation("Test_1")] public Task Should_Return_Correct_Text() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("--name", "\"Rufus"); // Then return Verifier.Verify(result); } } [UsesVerify] [ExpectationPath("OptionWithoutName")] public sealed class OptionWithoutName { [Fact] [Expectation("Test_1")] public Task Should_Return_Correct_Text_For_Short_Option() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", "-", " "); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_2")] public Task Should_Return_Correct_Text_For_Missing_Long_Option_Value_With_Equality_Separator() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", $"--foo="); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_3")] public Task Should_Return_Correct_Text_For_Missing_Long_Option_Value_With_Colon_Separator() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", $"--foo:"); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_4")] public Task Should_Return_Correct_Text_For_Missing_Short_Option_Value_With_Equality_Separator() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", $"-f="); // Then return Verifier.Verify(result); } [Fact] [Expectation("Test_5")] public Task Should_Return_Correct_Text_For_Missing_Short_Option_Value_With_Colon_Separator() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", $"-f:"); // Then return Verifier.Verify(result); } } [UsesVerify] [ExpectationPath("InvalidShortOptionName")] public sealed class InvalidShortOptionName { [Fact] [Expectation("Test_1")] public Task Should_Return_Correct_Text() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", $"-f0o"); // Then return Verifier.Verify(result); } } [UsesVerify] [ExpectationPath("LongOptionNameIsOneCharacter")] public sealed class LongOptionNameIsOneCharacter { [Fact] [Expectation("Test_1")] public Task Should_Return_Correct_Text() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", $"--f"); // Then return Verifier.Verify(result); } } [UsesVerify] [ExpectationPath("LongOptionNameIsMissing")] public sealed class LongOptionNameIsMissing { [Fact] [Expectation("Test_1")] public Task Should_Return_Correct_Text() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", $"-- "); // Then return Verifier.Verify(result); } } [UsesVerify] [ExpectationPath("LongOptionNameStartWithDigit")] public sealed class LongOptionNameStartWithDigit { [Fact] [Expectation("Test_1")] public Task Should_Return_Correct_Text() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", $"--1foo"); // Then return Verifier.Verify(result); } } [UsesVerify] [ExpectationPath("LongOptionNameContainSymbol")] public sealed class LongOptionNameContainSymbol { [Fact] [Expectation("Test_1")] public Task Should_Return_Correct_Text() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", $"--f€oo"); // Then return Verifier.Verify(result); } [Theory] [InlineData("--f-oo")] [InlineData("--f-o-o")] [InlineData("--f_oo")] [InlineData("--f_o_o")] public void Should_Allow_Special_Symbols_In_Name(string option) { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("dog"); }); // When var result = fixture.Run("dog", option); // Then result.ShouldBe("Error: Command 'dog' is missing required argument 'AGE'."); } } [Fact] [Expectation("Quoted_Strings")] public Task Should_Parse_Quoted_Strings_Correctly() { // Given var fixture = new Fixture(); fixture.Configure(configurator => { configurator.AddCommand("foo"); }); // When var result = fixture.Run("foo", "--", "/c", "\"set && pause\""); // Then return Verifier.Verify(result); } } internal sealed class Fixture { private Action _appConfiguration = _ => { }; private Action _configuration; public void WithDefaultCommand() where T : class, ICommand { _appConfiguration = (app) => app.SetDefaultCommand(); } public void Configure(Action action) { _configuration = action; } public string Run(params string[] args) { using (var console = new TestConsole()) { var app = new CommandApp(); _appConfiguration?.Invoke(app); app.Configure(_configuration); app.Configure(c => c.ConfigureConsole(console)); app.Run(args); return console.Output .NormalizeLineEndings() .TrimLines() .Trim(); } } } }