Beispiel #1
0
        public async Task Help_text_shows_all_valid_values_for_non_scalar_nullable_enum_parameters_and_options()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <WithNullableEnumCollectionArgumentsCommand>();

            // Act
            var(exitCode, stdOut, _) = await builder.BuildAndRunTestAsync(_output, new[] { "--help" });

            // Assert
            exitCode.Should().Be(ExitCodes.Success);
            stdOut.GetString().Should().ContainAll(
                "PARAMETERS",
                "OPTIONS",
                "Foo",
                "bar",
                "wizz",
                "Buzz",
                "fizzz",
                @"""""",
                "Value1", "Value2", "Value3",
                "Value4", "Value5", "Value6",
                "Value7", "Value8", "Value9",
                "ValueA", "ValueB", "ValueC",
                @"(Default: ""ValueD"" ""ValueF"")"
                );
        }
Beispiel #2
0
        public async Task Property_annotated_as_parameter_is_bound_directly_from_argument_value_according_to_the_order_even_if_there_is_a_hyphen()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <WithParametersCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output, new[]
            {
                "cmd", "-", "0", "bar", "-", "baz"
            });

            var commandInstance = stdOut.GetString().DeserializeJson <WithParametersCommand>();

            // Assert
            exitCode.Should().Be(ExitCodes.Success);

            stdErr.GetString().Should().BeNullOrWhiteSpace();

            commandInstance.Should().BeEquivalentTo(new WithParametersCommand
            {
                ParamA = "-",
                ParamB = 0,
                ParamC = new[] { "bar", "-", "baz" }
            });
        }
Beispiel #3
0
        public async Task Help_text_shows_modes()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <WithParametersCommand>()
                          .AddCommand <NamedInteractiveOnlyCommand>()
                          .AddDirective <DebugDirective>()
                          .UseDirectMode(true)
                          .UseInteractiveMode();

            // Act
            var(exitCode, stdOut, _) = await builder.BuildAndRunTestAsync(_output, new[] { "--help" });

            // Assert
            exitCode.Should().Be(ExitCodes.Success);
            stdOut.GetString().Should().ContainAll(
                "USAGE",
                "DIRECTIVES",
                "SUPPORTED MODES",
                typeof(DirectMode).FullName,
                typeof(Modes.InteractiveMode).FullName,
                "@ interactive",
                "@ named-interactive-only",
                "@ [.]",
                "@ [..]",
                "@ [>]",
                "@ [interactive]",
                "[debug]",
                "[!]"
                );
        }
        public async Task Application_should_allow_action_based_prompt_with_service_options_metadata_and_console()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <DefaultCommand>()
                          .AddCommand <ExitCommand>()
                          .UseDirectMode(asStartup: true)
                          .UseTitle("testTitle")
                          .UseExecutableName("otherTitle")
                          .UseInteractiveMode(options: (cfg) =>
            {
                cfg.SetPrompt <ICliApplicationLifetime>((lifetime, interactiveModeOptions, metadata, console) =>
                {
                    console.Output.Write(lifetime.CurrentModeType?.Name);
                    console.Output.Write(interactiveModeOptions.PromptForeground);
                    console.Output.Write(" ");
                    console.Output.Write(metadata.Title);
                    console.Error.Write(metadata.ExecutableName);
                });
            });

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output,
                                                                               commandLine : "interactive",
                                                                               isInputRedirected : true,
                                                                               input : string.Empty);

            // Assert
            exitCode.Should().Be(ExitCodes.Success);
            stdOut.GetString().Should().StartWith($"InteractiveMode{ConsoleColor.Blue} testTitle");
            stdErr.GetString().Should().StartWith("otherTitle");
        }
Beispiel #5
0
        public async Task Custom_throwable_directive_should_throw_exception()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <NamedCommand>()
                          .AddDirective <PreviewDirective>()
                          .AddDirective <CustomThrowableDirective>()
                          .AddDirective <CustomThrowableDirectiveWithMessage>()
                          .AddDirective <CustomThrowableDirectiveWithInnerException>()
                          .AddDirective <CustomDirective>()
                          .AddDirective <CustomStopDirective>()
                          .AddDirective <CustomInteractiveModeOnlyDirective>()
                          .UseDirectMode(true)
                          .UseInteractiveMode();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output,
                                                                               new[] { "[custom-throwable]", "named", "param", "-abc", "--option", "foo" });

            // Assert
            exitCode.Should().Be(CustomThrowableDirective.ExpectedExitCode);
            stdOut.GetString().Should().Be(CustomThrowableDirective.ExpectedOutput);
            stdErr.GetString().Should().ContainEquivalentOf(
                "Exception of type 'Typin.Exceptions.DirectiveException' was thrown."
                );
        }
Beispiel #6
0
        public async Task Custom_throwable_directive_with_message_and_show_help_should_throw_exception()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <NamedCommand>()
                          .AddDirective <PreviewDirective>()
                          .AddDirective <CustomThrowableDirective>()
                          .AddDirective <CustomThrowableDirectiveWithMessage>()
                          .AddDirective <CustomThrowableDirectiveWithInnerException>()
                          .AddDirective <CustomThrowableDirectiveWithMessageAndShowHelp>()
                          .AddDirective <CustomDirective>()
                          .AddDirective <CustomStopDirective>()
                          .AddDirective <CustomInteractiveModeOnlyDirective>()
                          .UseInteractiveMode();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output, "[custom-throwable-with-message-and-show-help] named param -abc --option foo");

            // Assert
            exitCode.Should().Be(CustomThrowableDirectiveWithMessageAndShowHelp.ExpectedExitCode);
            stdOut.GetString().Should().ContainEquivalentOf(CustomThrowableDirectiveWithMessageAndShowHelp.ExpectedOutput);
            stdErr.GetString().Should().ContainEquivalentOf(CustomThrowableDirectiveWithMessageAndShowHelp.ExpectedExceptionMessage);

            stdOut.GetString().Should().ContainAll(
                "  [custom-throwable-with-message-and-show-help]",
                "@ [custom-interactive]",
                "Description".ToUpperInvariant(),
                "Usage".ToUpperInvariant(),
                "Directives".ToUpperInvariant(),
                "[custom]"
                );
        }
Beispiel #7
0
        public async Task Application_should_execute_scoped_command_and_stay_there_without_executing()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <DefaultCommand>()
                          .AddCommand <NamedInteractiveOnlyCommand>()
                          .AddCommand <ExitCommand>()
                          .UseDirectMode(asStartup: true)
                          .UseInteractiveMode();

            string input = new[] { "[>] named-interactive-only", "[>]", "[>] unknown command", "[>] named-interactive-only", "[..]" }.JoinToInteractiveCommand();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output,
                                                                               commandLine : "interactive",
                                                                               isInputRedirected : true,
                                                                               input : input);

            // Assert
            exitCode.Should().Be(ExitCodes.Success);
            stdOut.GetString().Should().Contain("dotnet testhost.dll> ");
            stdOut.GetString().Should().NotContain(NamedInteractiveOnlyCommand.ExpectedOutputText);
            stdErr.GetString().Should().NotContain("Unrecognized parameters provided");
            stdErr.GetString().Should().BeNullOrWhiteSpace();
        }
Beispiel #8
0
        public async Task Help_text_shows_default_values_and_names_for_non_required_options()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <WithDefaultValuesAndNamesCommand>();

            // Act
            var(exitCode, stdOut, _) = await builder.BuildAndRunTestAsync(_output, new[] { "cmd", "--help" });

            // Assert
            exitCode.Should().Be(ExitCodes.Success);
            stdOut.GetString().Should().ContainAll(
                "OPTIONS",
                "--object", "Default: \"42\"",
                "--string", "Default: \"foo\"",
                "--string-empty", "Default: \"\"",
                "--string-array", "Default: \"foo\" \"bar\" \"baz\"",
                "--bool", "Default: \"True\"",
                "--char", "Default: \"t\"",
                "--int", "Default: \"1337\"",
                "--int-nullable", "Default: \"1337\"",
                "--int-array", "Default: \"1\" \"2\" \"3\"",
                "--time-span", "Default: \"02:03:00\"",
                "--enum", "Default: \"Value2\""
                );
        }
Beispiel #9
0
 public static async ValueTask <(int exitCode, MemoryStreamWriter stdOut, MemoryStreamWriter stdErr)> BuildAndRunTestAsync(this CliApplicationBuilder applicationBuilder,
                                                                                                                           ITestOutputHelper testOutput,
                                                                                                                           bool isInputRedirected = true)
 {
     return(await applicationBuilder.BuildAndRunTestAsync(testOutput,
                                                          Array.Empty <string>(),
                                                          new Dictionary <string, string>(),
                                                          isInputRedirected));
 }
Beispiel #10
0
 public static async ValueTask <(int exitCode, MemoryStreamWriter stdOut, MemoryStreamWriter stdErr)> BuildAndRunTestAsync(this CliApplicationBuilder applicationBuilder,
                                                                                                                           ITestOutputHelper testOutput,
                                                                                                                           IReadOnlyList <string> commandLineArguments,
                                                                                                                           bool isInputRedirected = true)
 {
     return(await applicationBuilder.BuildAndRunTestAsync(testOutput,
                                                          commandLineArguments,
                                                          new Dictionary <string, string>(),
                                                          isInputRedirected));
 }
Beispiel #11
0
 public static async ValueTask <(int exitCode, MemoryStreamWriter stdOut, MemoryStreamWriter stdErr)> BuildAndRunTestAsync(this CliApplicationBuilder applicationBuilder,
                                                                                                                           ITestOutputHelper testOutput,
                                                                                                                           string commandLine,
                                                                                                                           bool containsExecutable = false,
                                                                                                                           bool isInputRedirected  = true)
 {
     return(await applicationBuilder.BuildAndRunTestAsync(testOutput,
                                                          commandLine,
                                                          new Dictionary <string, string>(),
                                                          containsExecutable,
                                                          isInputRedirected));
 }
Beispiel #12
0
        public async Task Application_can_be_created_and_executed_with_benchmark_commands()
        {
            // Arrange
            var builder = new CliApplicationBuilder().AddCommand <BenchmarkDefaultCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output, new string[] { "--str", "hello world", "-i", "-13", "-b" });

            // Assert
            exitCode.Should().Be(ExitCodes.Success);
            stdOut.GetString().Should().ContainEquivalentOf("{\"StrOption\":\"hello world\",\"IntOption\":-13,\"BoolOption\":true}");
            stdErr.GetString().Should().BeNullOrWhiteSpace();
        }
        public async Task Command_parameter_can_be_non_scalar_only_if_no_other_such_parameter_is_present()
        {
            var builder = new CliApplicationBuilder()
                          .AddCommand <MultipleNonScalarParametersCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output);

            // Assert
            exitCode.Should().NotBe(ExitCodes.Success);
            stdOut.GetString().Should().BeNullOrWhiteSpace();
            stdErr.GetString().Should().NotBeNullOrWhiteSpace();
        }
        public async Task Command_parameter_can_be_non_scalar_only_if_it_is_the_last_in_order()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <NonLastNonScalarParameterCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output);

            // Assert
            exitCode.Should().NotBe(ExitCodes.Success);
            stdOut.GetString().Should().BeNullOrWhiteSpace();
            stdErr.GetString().Should().NotBeNullOrWhiteSpace();
        }
        public async Task Command_parameters_must_have_unique_names()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <DuplicateParameterNameCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output);

            // Assert
            exitCode.Should().NotBe(ExitCodes.Success);
            stdOut.GetString().Should().BeNullOrWhiteSpace();
            stdErr.GetString().Should().NotBeNullOrWhiteSpace();
        }
Beispiel #16
0
        public async Task Option_alias_should_not_be_available_when_two_dashes_are_specified()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <WithRequiredOptionsCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output, "cmd --a a --c c z \n \b a");

            // Assert
            exitCode.Should().NotBe(ExitCodes.Success);
            stdOut.GetString().Should().BeNullOrWhiteSpace();
            stdErr.GetString().Should().NotBeNullOrWhiteSpace();
        }
Beispiel #17
0
        public async Task Command_options_must_not_have_conflicts_with_the_implicit_version_option()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <ConflictWithVersionOptionCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output);

            // Assert
            exitCode.Should().NotBe(ExitCodes.Success);
            stdOut.GetString().Should().BeNullOrWhiteSpace();
            stdErr.GetString().Should().NotBeNullOrWhiteSpace();
        }
Beispiel #18
0
        public async Task Command_may_throw_a_specialized_exception_which_exits_with_custom_code_and_prints_minimal_error_details(int errorCode)
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <CommandExceptionCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output, new[] { "cmd", "-m", "ErrorTest", "-c", errorCode.ToString() });

            // Assert
            exitCode.Should().Be(errorCode);
            stdOut.GetString().Should().BeEmpty();
            stdErr.GetString().Trim().Should().Be("ErrorTest");
        }
        public async Task Commands_must_be_annotated_by_an_attribute()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <NonAnnotatedCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output);

            // Assert
            exitCode.Should().NotBe(ExitCodes.Success);
            stdOut.GetString().Should().BeNullOrWhiteSpace();
            stdErr.GetString().Should().NotBeNullOrWhiteSpace();
        }
Beispiel #20
0
        public async Task Command_option_must_have_valid_shortnames()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <InvalidOptionShortNameCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output);

            // Assert
            exitCode.Should().NotBe(ExitCodes.Success);
            stdOut.GetString().Should().BeNullOrWhiteSpace();
            stdErr.GetString().Should().NotBeNullOrWhiteSpace();
        }
Beispiel #21
0
        public async Task ShouldRun()
        {
            //Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommandsFrom(typeof(WorldCommand).Assembly);

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output);

            // Assert
            exitCode.Should().Be(0);
            stdOut.GetString().Should().NotBeNullOrWhiteSpace();
            stdErr.GetString().Should().BeNullOrWhiteSpace();
        }
Beispiel #22
0
        public async Task Command_options_must_have_names_that_are_longer_than_one_character()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <SingleCharacterOptionNameCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output);

            // Assert
            exitCode.Should().NotBe(ExitCodes.Success);
            stdOut.GetString().Should().BeNullOrWhiteSpace();
            stdErr.GetString().Should().NotBeNullOrWhiteSpace();
        }
        public async Task Should_not_parse_unknown_char_escape_sequence(string args)
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <SupportedArgumentTypesCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output, args);

            // Assert
            exitCode.Should().NotBe(ExitCodes.Success);
            stdOut.GetString().Should().BeNullOrWhiteSpace();
            stdErr.GetString().Should().NotBeNullOrWhiteSpace();
        }
Beispiel #24
0
        public async Task ShouldRun(string name, int age)
        {
            //Arrange
            var builder = new CliApplicationBuilder()
                          .UseStartup <Startup>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output, $"person {name} {age}");

            // Assert
            exitCode.Should().Be(ExitCodes.Success);
            stdOut.GetString().Trim().Should().Be($"{name} is {age} years old.");
            stdErr.GetString().Should().BeNullOrWhiteSpace();
        }
        public async Task ShouldRun(params string[] args)
        {
            //Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <WorldEndCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output, args);

            // Assert
            exitCode.Should().Be(0);
            stdOut.GetString().Should().NotBeNullOrWhiteSpace();
            stdErr.GetString().Should().BeNullOrWhiteSpace();
        }
Beispiel #26
0
        public async Task Command_may_throw_a_specialized_exception_without_error_message_which_exits_and_prints_full_error_details()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <CommandExceptionCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output, "cmd");

            // Assert
            exitCode.Should().NotBe(ExitCodes.Success);
            stdOut.GetString().Should().BeEmpty();
            stdErr.GetString().Trim().Should().Be("Exception of type 'Typin.Exceptions.CommandException' was thrown.");
        }
Beispiel #27
0
        public async Task ShouldShowError(string args)
        {
            //Arrange
            var builder = new CliApplicationBuilder()
                          .UseStartup <Startup>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output, "email -a " + args);

            // Assert
            exitCode.Should().NotBe(ExitCodes.Success);
            stdOut.GetString().Trim().Should().NotBe(args);
            stdErr.GetString().Should().NotBeNullOrWhiteSpace();
        }
        public async Task At_least_one_command_must_be_defined_in_an_application()
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .UseStartupMessage((metadata) => $"{metadata.Title} CLI {metadata.VersionText} {metadata.ExecutableName} {metadata.Description} Test");

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output);

            // Assert
            exitCode.Should().NotBe(ExitCodes.Success);
            stdOut.GetString().Should().BeNullOrWhiteSpace();
            stdErr.GetString().Should().NotBeNullOrWhiteSpace();
        }
Beispiel #29
0
        public async Task All_provided_parameter_and_option_arguments_must_be_bound_to_corresponding_properties(params string[] args)
        {
            // Arrange
            var builder = new CliApplicationBuilder()
                          .AddCommand <SupportedArgumentTypesCommand>();

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output, args);

            // Assert
            exitCode.Should().NotBe(ExitCodes.Success);
            stdOut.GetString().Should().BeNullOrWhiteSpace();
            stdErr.GetString().Should().NotBeNullOrWhiteSpace();
        }
Beispiel #30
0
        public async Task ShouldRun(string args, string result)
        {
            //Arrange
            var builder = new CliApplicationBuilder()
                          .ConfigureServices((services) => services.AddSingleton <OperationEvaluatorService>())
                          .AddCommandsFrom(typeof(AddCommand).Assembly);

            // Act
            var(exitCode, stdOut, stdErr) = await builder.BuildAndRunTestAsync(_output, args);

            // Assert
            exitCode.Should().Be(ExitCodes.Success);
            stdOut.GetString().Trim().Should().Be(result);
            stdErr.GetString().Should().BeNullOrWhiteSpace();
        }