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"")" ); }
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" } }); }
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"); }
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." ); }
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]" ); }
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(); }
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\"" ); }
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)); }
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)); }
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)); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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."); }
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(); }
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(); }
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(); }