コード例 #1
0
ファイル: TypeActivationSpecs.cs プロジェクト: Tyrrrz/CliFx
    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");
    }
コード例 #2
0
        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");
        }
コード例 #3
0
        public async Task Help_text_shows_application_metadata()
        {
            // Arrange
            var application = new CliApplicationBuilder()
                              .UseConsole(FakeConsole)
                              .SetTitle("App title")
                              .SetDescription("App description")
                              .SetVersion("App version")
                              .Build();

            // Act
            var exitCode = await application.RunAsync(
                new[] { "--help" },
                new Dictionary <string, string>()
                );

            var stdOut = FakeConsole.ReadOutputString();

            // Assert
            exitCode.Should().Be(0);
            stdOut.Should().ContainAll(
                "App title",
                "App description",
                "App version"
                );
        }
コード例 #4
0
        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."
                );
        }
コード例 #5
0
    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");
    }
コード例 #6
0
        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"
                );
        }
コード例 #7
0
        public async Task Help_text_shows_all_immediate_child_commands_of_each_child_command()
        {
            // Arrange
            var commandTypes = DynamicCommandBuilder.CompileMany(
                // language=cs
                @"
[Command(""cmd1"")]
public class FirstCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console) => default;
}

[Command(""cmd1 child1"")]
public class FirstCommandFirstChildCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console) => default;
}

[Command(""cmd2"")]
public class SecondCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console) => default;
}

[Command(""cmd2 child11"")]
public class SecondCommandFirstChildCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console) => default;
}

[Command(""cmd2 child2"")]
public class SecondCommandSecondChildCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console) => default;
}
");

            var application = new CliApplicationBuilder()
                              .AddCommands(commandTypes)
                              .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(
                "COMMANDS",
                "cmd1", "Subcommands:", "cmd1 child1",
                "cmd2", "Subcommands:", "cmd2 child1", "cmd2 child2"
                );
        }
コード例 #8
0
    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"
            );
    }
コード例 #9
0
        public async Task Specific_named_command_is_executed_if_provided_arguments_match_its_name()
        {
            // Arrange
            var commandTypes = DynamicCommandBuilder.CompileMany(
                // language=cs
                @"
[Command]
public class DefaultCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console)
    {
        console.Output.WriteLine(""default"");
        return default;
    }
}

[Command(""cmd"")]
public class NamedCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console)
    {
        console.Output.WriteLine(""cmd"");
        return default;
    }
}

[Command(""cmd child"")]
public class NamedChildCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console)
    {
        console.Output.WriteLine(""cmd child"");
        return default;
    }
}
");

            var application = new CliApplicationBuilder()
                              .AddCommands(commandTypes)
                              .UseConsole(FakeConsole)
                              .Build();

            // Act
            var exitCode = await application.RunAsync(
                new[] { "cmd" },
                new Dictionary <string, string>()
                );

            var stdOut = FakeConsole.ReadOutputString();

            // Assert
            exitCode.Should().Be(0);
            stdOut.Trim().Should().Be("cmd");
        }
コード例 #10
0
        public async Task Help_text_shows_all_immediate_child_commands()
        {
            // Arrange
            var commandTypes = DynamicCommandBuilder.CompileMany(
                // language=cs
                @"
[Command(""cmd1"", Description = ""Description of one command."")]
public class FirstCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console) => default;
}

[Command(""cmd2"", Description = ""Description of another command."")]
public class SecondCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console) => default;
}

[Command(""cmd2 child"", Description = ""Description of another command's child command."")]
public class SecondCommandChildCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console) => default;
}
");

            var application = new CliApplicationBuilder()
                              .AddCommands(commandTypes)
                              .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(
                "COMMANDS",
                "cmd1", "Description of one command.",
                "cmd2", "Description of another command."
                );

            // `cmd2 child` will still appear in the list of `cmd2` subcommands,
            // but its description will not be seen.
            stdOut.Should().NotContain(
                "Description of another command's child command."
                );
        }
コード例 #11
0
ファイル: HelpTextSpecs.cs プロジェクト: Tyrrrz/CliFx
    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...>"
            );
    }
コード例 #12
0
        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");
        }
コード例 #13
0
ファイル: ConversionSpecs.cs プロジェクト: Tyrrrz/CliFx
    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"
            );
    }
コード例 #14
0
ファイル: EnvironmentSpecs.cs プロジェクト: rcdailey/CliFx
        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"
                );
        }
コード例 #15
0
ファイル: ConversionSpecs.cs プロジェクト: Tyrrrz/CliFx
    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"
            );
    }
コード例 #16
0
ファイル: OptionBindingSpecs.cs プロジェクト: rcdailey/CliFx
        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"
                );
        }
コード例 #17
0
    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"
            );
    }
コード例 #18
0
        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"
                );
        }
コード例 #19
0
ファイル: ConversionSpecs.cs プロジェクト: Tyrrrz/CliFx
    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");
    }
コード例 #20
0
ファイル: EnvironmentSpecs.cs プロジェクト: rcdailey/CliFx
        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");
        }
コード例 #21
0
ファイル: ConversionSpecs.cs プロジェクト: Tyrrrz/CliFx
    public async Task Parameter_or_option_value_can_be_converted_using_a_custom_converter()
    {
        // Arrange
        var commandType = DynamicCommandBuilder.Compile(
            // language=cs
            @"
public class CustomConverter : BindingConverter<int>
{
    public override int Convert(string rawValue) =>
        rawValue.Length;
}

[Command]
public class Command : ICommand
{
    [CommandOption('f', Converter = typeof(CustomConverter))]
    public int 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(
            new[] { "-f", "hello world" },
            new Dictionary <string, string>()
            );

        var stdOut = FakeConsole.ReadOutputString();

        // Assert
        exitCode.Should().Be(0);
        stdOut.Trim().Should().Be("11");
    }
コード例 #22
0
        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"
                );
        }
コード例 #23
0
ファイル: ConversionSpecs.cs プロジェクト: Tyrrrz/CliFx
    public async Task Parameter_or_option_value_can_be_converted_to_an_array_of_integers()
    {
        // Arrange
        var commandType = DynamicCommandBuilder.Compile(
            // language=cs
            @"
[Command]
public class Command : ICommand
{
    [CommandOption('f')]
    public int[] 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[] { "-f", "1", "13", "27" },
            new Dictionary <string, string>()
            );

        var stdOut = FakeConsole.ReadOutputString();

        // Assert
        exitCode.Should().Be(0);
        stdOut.Should().ConsistOfLines(
            "1",
            "13",
            "27"
            );
    }
コード例 #24
0
ファイル: OptionBindingSpecs.cs プロジェクト: rcdailey/CliFx
        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"
                );
        }
コード例 #25
0
        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]"
                );
        }
コード例 #26
0
        public async Task Help_text_for_a_specific_named_child_command_is_printed_if_provided_arguments_match_its_name_and_contain_the_help_option()
        {
            // Arrange
            var commandTypes = DynamicCommandBuilder.CompileMany(
                // language=cs
                @"
[Command]
public class DefaultCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console) => default;
}

[Command(""cmd"")]
public class NamedCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console) => default;
}

[Command(""cmd child"", Description = ""Description of a named child command."")]
public class NamedChildCommand : ICommand
{
    public ValueTask ExecuteAsync(IConsole console) => default;
}
");

            var application = new CliApplicationBuilder()
                              .AddCommands(commandTypes)
                              .UseConsole(FakeConsole)
                              .Build();

            // Act
            var exitCode = await application.RunAsync(
                new[] { "cmd", "sub", "--help" },
                new Dictionary <string, string>()
                );

            var stdOut = FakeConsole.ReadOutputString();

            // Assert
            exitCode.Should().Be(0);
            stdOut.Should().Contain("Description of a named child command.");
        }
コード例 #27
0
        public async Task Help_text_is_printed_if_no_arguments_are_provided_and_the_default_command_is_not_defined()
        {
            // Arrange
            var application = new CliApplicationBuilder()
                              .UseConsole(FakeConsole)
                              .SetDescription("This will be in help text")
                              .Build();

            // Act
            var exitCode = await application.RunAsync(
                Array.Empty <string>(),
                new Dictionary <string, string>()
                );

            var stdOut = FakeConsole.ReadOutputString();

            // Assert
            exitCode.Should().Be(0);
            stdOut.Should().Contain("This will be in help text");
        }
コード例 #28
0
        public async Task Help_text_shows_all_parameters_and_options()
        {
            // Arrange
            var commandType = DynamicCommandBuilder.Compile(
                // language=cs
                @"
[Command]
public class Command : ICommand
{
    [CommandParameter(0, Name = ""foo"", Description = ""Description of foo."")]
    public string Foo { get; set; }
    
    [CommandOption(""bar"", Description = ""Description of bar."")]
    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[] { "--help" },
                new Dictionary <string, string>()
                );

            var stdOut = FakeConsole.ReadOutputString();

            // Assert
            exitCode.Should().Be(0);
            stdOut.Should().ContainAllInOrder(
                "PARAMETERS",
                "foo", "Description of foo.",
                "OPTIONS",
                "--bar", "Description of bar."
                );
        }
コード例 #29
0
ファイル: ConsoleSpecs.cs プロジェクト: Tyrrrz/CliFx
    public async Task Fake_console_can_be_used_with_an_in_memory_backing_store()
    {
        // Arrange
        var commandType = DynamicCommandBuilder.Compile(
            // language=cs
            @"
[Command]
public class Command : ICommand
{   
    public ValueTask ExecuteAsync(IConsole console)
    {
        var input = console.Input.ReadToEnd();
        console.Output.WriteLine(input);
        console.Error.WriteLine(input);

        return default;
    }
}
");

        var application = new CliApplicationBuilder()
                          .AddCommand(commandType)
                          .UseConsole(FakeConsole)
                          .Build();

        // Act
        FakeConsole.WriteInput("Hello world");

        var exitCode = await application.RunAsync(
            Array.Empty <string>(),
            new Dictionary <string, string>()
            );

        var stdOut = FakeConsole.ReadOutputString();
        var stdErr = FakeConsole.ReadErrorString();

        // Assert
        exitCode.Should().Be(0);
        stdOut.Trim().Should().Be("Hello world");
        stdErr.Trim().Should().Be("Hello world");
    }
コード例 #30
0
        public async Task Version_text_is_printed_if_provided_arguments_contain_the_version_option()
        {
            // Arrange
            var application = new CliApplicationBuilder()
                              .AddCommand <NoOpCommand>()
                              .SetVersion("v6.9")
                              .UseConsole(FakeConsole)
                              .Build();

            // Act
            var exitCode = await application.RunAsync(
                new[] { "--version" },
                new Dictionary <string, string>()
                );

            var stdOut = FakeConsole.ReadOutputString();

            // Assert
            exitCode.Should().Be(0);
            stdOut.Trim().Should().Be("v6.9");
        }