public async Task Default_type_activator_can_initialize_a_type_if_it_has_a_parameterless_constructor() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { public ValueTask ExecuteAsync(IConsole console) { console.Output.WriteLine(""foo""); return default; } }"); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .UseTypeActivator(new DefaultTypeActivator()) .Build(); // Act var exitCode = await application.RunAsync( Array.Empty <string>(), new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Trim().Should().Be("foo"); }
public async Task Parameter_binding_fails_if_one_of_the_provided_parameters_is_unexpected() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandParameter(0)] public string Foo { get; set; } [CommandParameter(1)] public string Bar { get; set; } public ValueTask ExecuteAsync(IConsole console) => default; }"); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "one", "two", "three" }, new Dictionary <string, string>() ); var stdErr = FakeConsole.ReadErrorString(); // Assert exitCode.Should().NotBe(0); stdErr.Should().Contain("Unexpected parameter(s)"); }
public async Task Default_type_activator_fails_if_the_type_does_not_have_a_parameterless_constructor() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { public Command(string foo) {} public ValueTask ExecuteAsync(IConsole console) => default; }"); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .UseTypeActivator(new DefaultTypeActivator()) .Build(); // Act var exitCode = await application.RunAsync( Array.Empty <string>(), new Dictionary <string, string>() ); var stdErr = FakeConsole.ReadErrorString(); // Assert exitCode.Should().NotBe(0); stdErr.Should().Contain("Failed to create an instance of type"); }
public async Task Parameter_binding_fails_if_a_parameter_of_non_scalar_type_has_not_been_provided_with_at_least_one_value() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandParameter(0)] public string Foo { get; set; } [CommandParameter(1)] public IReadOnlyList<string> Bar { get; set; } public ValueTask ExecuteAsync(IConsole console) => default; }"); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "one" }, new Dictionary <string, string>() ); var stdErr = FakeConsole.ReadErrorString(); // Assert exitCode.Should().NotBe(0); stdErr.Should().Contain("Missing required parameter(s)"); }
public async Task Option_binding_fails_if_one_of_the_provided_option_names_is_not_recognized() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandOption(""foo"")] public string Foo { get; set; } public ValueTask ExecuteAsync(IConsole console) => default; }"); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "--foo", "one", "--bar", "two" }, new Dictionary <string, string>() ); var stdErr = FakeConsole.ReadErrorString(); // Assert exitCode.Should().NotBe(0); stdErr.Should().Contain("Unrecognized option(s)"); }
public async Task Option_binding_fails_if_an_option_of_scalar_type_has_been_provided_with_multiple_values() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandOption(""foo"")] public string Foo { get; set; } public ValueTask ExecuteAsync(IConsole console) => default; }"); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "--foo", "one", "two", "three" }, new Dictionary <string, string>() ); var stdErr = FakeConsole.ReadErrorString(); // Assert exitCode.Should().NotBe(0); stdErr.Should().Contain("expects a single argument, but provided with multiple"); }
public async Task Help_text_shows_command_description() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command(Description = ""Description of the default command."")] public class DefaultCommand : ICommand { public ValueTask ExecuteAsync(IConsole console) => default; } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "--help" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().ContainAllInOrder( "DESCRIPTION", "Description of the default command." ); }
public async Task Option_binding_fails_if_a_required_option_has_been_provided_with_an_empty_value() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandOption(""foo"", IsRequired = true)] public string Foo { get; set; } public ValueTask ExecuteAsync(IConsole console) => default; }"); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "--foo" }, new Dictionary <string, string>() ); var stdErr = FakeConsole.ReadErrorString(); // Assert exitCode.Should().NotBe(0); stdErr.Should().Contain("Missing required option(s)"); }
public async Task Help_text_shows_the_implicit_help_and_version_options_on_the_default_command() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { public ValueTask ExecuteAsync(IConsole console) => default; } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "--help" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().ContainAllInOrder( "OPTIONS", "-h", "--help", "Shows help text", "--version", "Shows version information" ); }
public async Task Help_text_is_printed_if_provided_arguments_contain_the_help_option() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class DefaultCommand : ICommand { public ValueTask ExecuteAsync(IConsole console) => default; } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .SetDescription("This will be in help text") .Build(); // Act var exitCode = await application.RunAsync( new[] { "--help" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().Contain("This will be in help text"); }
public async Task Command_can_throw_a_special_exception_which_exits_with_specified_code_and_message() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { public ValueTask ExecuteAsync(IConsole console) => throw new CommandException(""Something went wrong"", 69); } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( Array.Empty <string>(), new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); var stdErr = FakeConsole.ReadErrorString(); // Assert exitCode.Should().Be(69); stdOut.Should().BeEmpty(); stdErr.Trim().Should().Be("Something went wrong"); }
public async Task Parameter_or_option_value_conversion_fails_if_the_target_type_is_not_supported() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" public class CustomType {} [Command] public class Command : ICommand { [CommandOption('f')] public CustomType Foo { get; set; } public ValueTask ExecuteAsync(IConsole console) => default; } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "-f", "xyz" }, new Dictionary <string, string>() ); var stdErr = FakeConsole.ReadErrorString(); // Assert exitCode.Should().NotBe(0); stdErr.Should().Contain("has an unsupported underlying property type"); }
public async Task Parameter_or_option_value_conversion_fails_if_the_value_cannot_be_converted_to_the_target_type() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandOption('f')] public int Foo { get; set; } public ValueTask ExecuteAsync(IConsole console) => default; } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "-f", "12.34" }, new Dictionary <string, string>() ); var stdErr = FakeConsole.ReadErrorString(); // Assert exitCode.Should().NotBe(0); stdErr.Should().NotBeNullOrWhiteSpace(); }
public async Task Delegate_type_activator_fails_if_the_underlying_function_returns_null() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { public ValueTask ExecuteAsync(IConsole console) { console.Output.WriteLine(""foo""); return default; } }"); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .UseTypeActivator(_ => null !) .Build(); // Act var exitCode = await application.RunAsync( Array.Empty <string>(), new Dictionary <string, string>() ); var stdErr = FakeConsole.ReadErrorString(); // Assert exitCode.Should().NotBe(0); stdErr.Should().Contain("Failed to create an instance of type"); }
public async Task Parameter_of_non_scalar_type_is_bound_from_remaining_non_option_arguments() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandParameter(0)] public string Foo { get; set; } [CommandParameter(1)] public string Bar { get; set; } [CommandParameter(2)] public IReadOnlyList<string> Baz { get; set; } [CommandOption(""boo"")] public string Boo { get; set; } public ValueTask ExecuteAsync(IConsole console) { console.Output.WriteLine(""Foo = "" + Foo); console.Output.WriteLine(""Bar = "" + Bar); foreach (var i in Baz) console.Output.WriteLine(""Baz = "" + i); return default; } }"); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "one", "two", "three", "four", "five", "--boo", "xxx" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().ConsistOfLines( "Foo = one", "Bar = two", "Baz = three", "Baz = four", "Baz = five" ); }
public async Task Fake_console_does_not_leak_to_system_console() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { public ValueTask ExecuteAsync(IConsole console) { console.ResetColor(); console.ForegroundColor = ConsoleColor.DarkMagenta; console.BackgroundColor = ConsoleColor.DarkMagenta; console.CursorLeft = 42; console.CursorTop = 24; console.Output.WriteLine(""Hello ""); console.Error.WriteLine(""world!""); return default; } } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( Array.Empty <string>(), new Dictionary <string, string>() ); // Assert exitCode.Should().Be(0); Console.OpenStandardInput().Should().NotBeSameAs(FakeConsole.Input.BaseStream); Console.OpenStandardOutput().Should().NotBeSameAs(FakeConsole.Output.BaseStream); Console.OpenStandardError().Should().NotBeSameAs(FakeConsole.Error.BaseStream); Console.ForegroundColor.Should().NotBe(ConsoleColor.DarkMagenta); Console.BackgroundColor.Should().NotBe(ConsoleColor.DarkMagenta); // This fails because tests don't spawn a console window //Console.CursorLeft.Should().NotBe(42); //Console.CursorTop.Should().NotBe(24); FakeConsole.IsInputRedirected.Should().BeTrue(); FakeConsole.IsOutputRedirected.Should().BeTrue(); FakeConsole.IsErrorRedirected.Should().BeTrue(); }
public async Task Help_text_shows_usage_format_which_lists_all_parameters_in_specified_order() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" // Base members appear last in reflection order public abstract class CommandBase : ICommand { [CommandParameter(0)] public string Foo { get; set; } public abstract ValueTask ExecuteAsync(IConsole console); } [Command] public class Command : CommandBase { [CommandParameter(2)] public IReadOnlyList<string> Baz { get; set; } [CommandParameter(1)] public string Bar { get; set; } public override ValueTask ExecuteAsync(IConsole console) => default; } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "--help" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().ContainAllInOrder( "USAGE", "<foo>", "<bar>", "<baz...>" ); }
public async Task Command_can_register_to_receive_a_cancellation_signal_from_the_console() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { public async ValueTask ExecuteAsync(IConsole console) { try { await Task.Delay( TimeSpan.FromSeconds(3), console.RegisterCancellationHandler() ); console.Output.WriteLine(""Completed successfully""); } catch (OperationCanceledException) { console.Output.WriteLine(""Cancelled""); throw; } } }"); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act FakeConsole.RequestCancellation(TimeSpan.FromSeconds(0.2)); var exitCode = await application.RunAsync( Array.Empty <string>(), new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().NotBe(0); stdOut.Trim().Should().Be("Cancelled"); }
public async Task Parameter_or_option_value_can_be_converted_to_a_nullable_enum() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" public enum CustomEnum { One = 1, Two = 2, Three = 3 } [Command] public class Command : ICommand { [CommandOption('f')] public CustomEnum? Foo { get; set; } [CommandOption('b')] public CustomEnum? Bar { get; set; } public ValueTask ExecuteAsync(IConsole console) { console.Output.WriteLine(""Foo = "" + (int?) Foo); console.Output.WriteLine(""Bar = "" + (int?) Bar); return default; } } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "-b", "two" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().ConsistOfLines( "Foo = ", "Bar = 2" ); }
public async Task Option_of_non_scalar_type_can_receive_multiple_values_from_an_environment_variable() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandOption(""foo"", EnvironmentVariable = ""ENV_FOO"")] public IReadOnlyList<string> Foo { get; set; } public ValueTask ExecuteAsync(IConsole console) { foreach (var i in Foo) console.Output.WriteLine(i); return default; } } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( Array.Empty <string>(), new Dictionary <string, string> { ["ENV_FOO"] = $"bar{Path.PathSeparator}baz" } ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().ConsistOfLines( "bar", "baz" ); }
public async Task Parameter_or_option_value_can_be_converted_to_a_boolean() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandOption('f')] public bool Foo { get; set; } [CommandOption('b')] public bool Bar { get; set; } public ValueTask ExecuteAsync(IConsole console) { console.Output.WriteLine(""Foo = "" + Foo); console.Output.WriteLine(""Bar = "" + Bar); return default; } } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "-f", "true", "-b", "false" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().ConsistOfLines( "Foo = True", "Bar = False" ); }
public async Task Option_is_not_bound_if_there_are_no_arguments_matching_its_name_or_short_name() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandOption(""foo"")] public string Foo { get; set; } [CommandOption(""bar"")] public string Bar { get; set; } = ""hello""; public ValueTask ExecuteAsync(IConsole console) { console.Output.WriteLine(""Foo = "" + Foo); console.Output.WriteLine(""Bar = "" + Bar); return default; } }"); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "--foo", "one" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().ConsistOfLines( "Foo = one", "Bar = hello" ); }
public async Task Parameter_is_bound_from_an_argument_matching_its_order() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandParameter(0)] public string Foo { get; set; } [CommandParameter(1)] public string Bar { get; set; } public ValueTask ExecuteAsync(IConsole console) { console.Output.WriteLine(""Foo = "" + Foo); console.Output.WriteLine(""Bar = "" + Bar); return default; } }"); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "one", "two" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().ConsistOfLines( "Foo = one", "Bar = two" ); }
public async Task Help_text_shows_all_valid_values_for_enum_parameters_and_options() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" public enum CustomEnum { One, Two, Three } [Command] public class Command : ICommand { [CommandParameter(0)] public CustomEnum Foo { get; set; } [CommandOption(""bar"")] public CustomEnum Bar { get; set; } public ValueTask ExecuteAsync(IConsole console) => default; } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "--help" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().ContainAllInOrder( "PARAMETERS", "foo", "Choices:", "One", "Two", "Three", "OPTIONS", "--bar", "Choices:", "One", "Two", "Three" ); }
public async Task Parameter_or_option_value_can_be_converted_to_a_type_that_has_a_constructor_accepting_a_string() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" public class CustomType { public string Value { get; } public CustomType(string value) => Value = value; } [Command] public class Command : ICommand { [CommandOption('f')] public CustomType Foo { get; set; } public ValueTask ExecuteAsync(IConsole console) { console.Output.WriteLine(Foo.Value); return default; } } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "-f", "xyz" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Trim().Should().Be("xyz"); }
public async Task Parameter_or_option_value_conversion_fails_if_one_of_the_validators_fail() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" public class ValidatorA : BindingValidator<int> { public override BindingValidationError Validate(int value) => Ok(); } public class ValidatorB : BindingValidator<int> { public override BindingValidationError Validate(int value) => Error(""Hello world""); } [Command] public class Command : ICommand { [CommandOption('f', Validators = new[] {typeof(ValidatorA), typeof(ValidatorB)})] public int Foo { get; set; } public ValueTask ExecuteAsync(IConsole console) => default; } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "-f", "12" }, new Dictionary <string, string>() ); var stdErr = FakeConsole.ReadErrorString(); // Assert exitCode.Should().NotBe(0); stdErr.Should().Contain("Hello world"); }
public async Task Help_text_shows_environment_variables_for_options_that_have_them_configured_as_fallback() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" public enum CustomEnum { One, Two, Three } [Command] public class Command : ICommand { [CommandOption(""foo"", EnvironmentVariable = ""ENV_FOO"")] public CustomEnum Foo { get; set; } [CommandOption(""bar"", EnvironmentVariable = ""ENV_BAR"")] public CustomEnum Bar { get; set; } public ValueTask ExecuteAsync(IConsole console) => default; } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "--help" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().ContainAllInOrder( "OPTIONS", "--foo", "Environment variable:", "ENV_FOO", "--bar", "Environment variable:", "ENV_BAR" ); }
public async Task Option_of_non_scalar_type_is_bound_from_multiple_sets_of_arguments_matching_its_name_or_short_name() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandOption(""foo"", 'f')] public IReadOnlyList<string> Foo { get; set; } public ValueTask ExecuteAsync(IConsole console) { foreach (var i in Foo) console.Output.WriteLine(i); return default; } }"); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "--foo", "one", "-f", "two", "--foo", "three" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().ConsistOfLines( "one", "two", "three" ); }
public async Task Help_text_shows_usage_format_which_lists_all_required_options() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandOption(""foo"", IsRequired = true)] public string Foo { get; set; } [CommandOption(""bar"")] public string Bar { get; set; } [CommandOption(""baz"", IsRequired = true)] public IReadOnlyList<string> Baz { get; set; } public ValueTask ExecuteAsync(IConsole console) => default; } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( new[] { "--help" }, new Dictionary <string, string>() ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Should().ContainAllInOrder( "USAGE", "--foo <value>", "--baz <values...>", "[options]" ); }
public async Task Environment_variables_are_matched_case_sensitively() { // Arrange var commandType = DynamicCommandBuilder.Compile( // language=cs @" [Command] public class Command : ICommand { [CommandOption(""foo"", EnvironmentVariable = ""ENV_FOO"")] public string Foo { get; set; } public ValueTask ExecuteAsync(IConsole console) { console.Output.WriteLine(Foo); return default; } } "); var application = new CliApplicationBuilder() .AddCommand(commandType) .UseConsole(FakeConsole) .Build(); // Act var exitCode = await application.RunAsync( Array.Empty <string>(), new Dictionary <string, string> { ["ENV_foo"] = "baz", ["ENV_FOO"] = "bar", ["env_FOO"] = "qop" } ); var stdOut = FakeConsole.ReadOutputString(); // Assert exitCode.Should().Be(0); stdOut.Trim().Should().Be("bar"); }