Add VirtualConsole.CreateBuffered() for easier testing

This commit is contained in:
Alexey Golub
2020-08-20 16:27:23 +03:00
parent c063251d89
commit 0d32876bad
15 changed files with 341 additions and 499 deletions

View File

@@ -54,8 +54,7 @@ namespace CliFx.Tests
[Fact]
public async Task At_least_one_command_must_be_defined_in_an_application()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.UseConsole(console)
@@ -63,20 +62,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Commands_must_implement_the_corresponding_interface()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand(typeof(NonImplementedCommand))
@@ -85,20 +82,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Commands_must_be_annotated_by_an_attribute()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<NonAnnotatedCommand>()
@@ -107,20 +102,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Commands_must_have_unique_names()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<GenericExceptionCommand>()
@@ -130,20 +123,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_can_be_default_but_only_if_it_is_the_only_such_command()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DefaultCommand>()
@@ -153,20 +144,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_parameters_must_have_unique_order()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DuplicateParameterOrderCommand>()
@@ -175,20 +164,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_parameters_must_have_unique_names()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DuplicateParameterNameCommand>()
@@ -197,20 +184,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_parameter_can_be_non_scalar_only_if_no_other_such_parameter_is_present()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<MultipleNonScalarParametersCommand>()
@@ -219,20 +204,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_parameter_can_be_non_scalar_only_if_it_is_the_last_in_order()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<NonLastNonScalarParameterCommand>()
@@ -241,20 +224,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_options_must_have_names_that_are_not_empty()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<EmptyOptionNameCommand>()
@@ -263,20 +244,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_options_must_have_names_that_are_longer_than_one_character()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SingleCharacterOptionNameCommand>()
@@ -285,20 +264,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_options_must_have_unique_names()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DuplicateOptionNamesCommand>()
@@ -307,20 +284,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_options_must_have_unique_short_names()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DuplicateOptionShortNamesCommand>()
@@ -329,20 +304,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_options_must_have_unique_environment_variable_names()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DuplicateOptionEnvironmentVariableNamesCommand>()
@@ -351,20 +324,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_options_must_not_have_conflicts_with_the_implicit_help_option()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<ConflictWithHelpOptionCommand>()
@@ -373,20 +344,18 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_options_must_not_have_conflicts_with_the_implicit_version_option()
{
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<ConflictWithVersionOptionCommand>()
@@ -395,13 +364,12 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
}
}

View File

@@ -1,9 +1,7 @@
using System.IO;
using System.Threading.Tasks;
using CliFx.Exceptions;
using System.Threading.Tasks;
using CliFx.Tests.Commands;
using CliFx.Tests.Internal;
using FluentAssertions;
using Newtonsoft.Json;
using Xunit;
using Xunit.Abstractions;
@@ -19,8 +17,7 @@ namespace CliFx.Tests
public async Task Property_annotated_as_an_option_can_be_bound_from_multiple_values_even_if_the_inputs_use_mixed_naming()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithStringArrayOptionCommand>()
@@ -33,8 +30,7 @@ namespace CliFx.Tests
"cmd", "--opt", "foo", "-o", "bar", "--opt", "baz"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<WithStringArrayOptionCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<WithStringArrayOptionCommand>();
// Assert
exitCode.Should().Be(0);
@@ -49,8 +45,7 @@ namespace CliFx.Tests
public async Task Property_annotated_as_a_required_option_must_always_be_set()
{
// Arrange
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithSingleRequiredOptionCommand>()
@@ -63,21 +58,18 @@ namespace CliFx.Tests
"cmd", "--opt-a", "foo"
});
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Property_annotated_as_a_required_option_must_always_be_bound_to_some_value()
{
// Arrange
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithSingleRequiredOptionCommand>()
@@ -90,21 +82,18 @@ namespace CliFx.Tests
"cmd", "--opt-a"
});
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Property_annotated_as_a_required_option_must_always_be_bound_to_at_least_one_value_if_it_expects_multiple_values()
{
// Arrange
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithRequiredOptionsCommand>()
@@ -117,21 +106,18 @@ namespace CliFx.Tests
"cmd", "--opt-a", "foo"
});
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Property_annotated_as_parameter_is_bound_directly_from_argument_value_according_to_the_order()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithParametersCommand>()
@@ -144,8 +130,7 @@ namespace CliFx.Tests
"cmd", "foo", "13", "bar", "baz"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<WithParametersCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<WithParametersCommand>();
// Assert
exitCode.Should().Be(0);
@@ -162,8 +147,7 @@ namespace CliFx.Tests
public async Task Property_annotated_as_parameter_must_always_be_bound_to_some_value()
{
// Arrange
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithSingleParameterCommand>()
@@ -176,21 +160,18 @@ namespace CliFx.Tests
"cmd"
});
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Property_annotated_as_parameter_must_always_be_bound_to_at_least_one_value_if_it_expects_multiple_values()
{
// Arrange
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithParametersCommand>()
@@ -203,21 +184,18 @@ namespace CliFx.Tests
"cmd", "foo", "13"
});
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task All_provided_option_arguments_must_be_bound_to_corresponding_properties()
{
// Arrange
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -230,21 +208,18 @@ namespace CliFx.Tests
"cmd", "--non-existing-option", "13"
});
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task All_provided_parameter_arguments_must_be_bound_to_corresponding_properties()
{
// Arrange
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -257,13 +232,11 @@ namespace CliFx.Tests
"cnd", "non-existing-parameter"
});
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
}
}

View File

@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Threading.Tasks;
using CliFx.Tests.Commands;
using CliFx.Tests.Internal;
using FluentAssertions;
using Newtonsoft.Json;
using Xunit;
using Xunit.Abstractions;
@@ -21,8 +20,7 @@ namespace CliFx.Tests
public async Task Property_of_type_object_is_bound_directly_from_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -35,8 +33,7 @@ namespace CliFx.Tests
"cmd", "--obj", "value"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -51,8 +48,7 @@ namespace CliFx.Tests
public async Task Property_of_type_object_array_is_bound_directly_from_the_argument_values()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -65,8 +61,7 @@ namespace CliFx.Tests
"cmd", "--obj-array", "foo", "bar"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -81,8 +76,7 @@ namespace CliFx.Tests
public async Task Property_of_type_string_is_bound_directly_from_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -95,8 +89,7 @@ namespace CliFx.Tests
"cmd", "--str", "value"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -111,8 +104,7 @@ namespace CliFx.Tests
public async Task Property_of_type_string_array_is_bound_directly_from_the_argument_values()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -125,8 +117,7 @@ namespace CliFx.Tests
"cmd", "--str-array", "foo", "bar"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -141,8 +132,7 @@ namespace CliFx.Tests
public async Task Property_of_type_string_IEnumerable_is_bound_directly_from_the_argument_values()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -155,8 +145,7 @@ namespace CliFx.Tests
"cmd", "--str-enumerable", "foo", "bar"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -171,8 +160,7 @@ namespace CliFx.Tests
public async Task Property_of_type_string_IReadOnlyList_is_bound_directly_from_the_argument_values()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -185,8 +173,7 @@ namespace CliFx.Tests
"cmd", "--str-read-only-list", "foo", "bar"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -201,8 +188,7 @@ namespace CliFx.Tests
public async Task Property_of_type_string_List_is_bound_directly_from_the_argument_values()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -215,8 +201,7 @@ namespace CliFx.Tests
"cmd", "--str-list", "foo", "bar"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -231,8 +216,7 @@ namespace CliFx.Tests
public async Task Property_of_type_string_HashSet_is_bound_directly_from_the_argument_values()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -245,8 +229,7 @@ namespace CliFx.Tests
"cmd", "--str-set", "foo", "bar"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -261,8 +244,7 @@ namespace CliFx.Tests
public async Task Property_of_type_bool_is_bound_as_true_if_the_argument_value_is_true()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -275,8 +257,7 @@ namespace CliFx.Tests
"cmd", "--bool", "true"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -291,8 +272,7 @@ namespace CliFx.Tests
public async Task Property_of_type_bool_is_bound_as_false_if_the_argument_value_is_false()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -305,8 +285,7 @@ namespace CliFx.Tests
"cmd", "--bool", "false"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -321,8 +300,7 @@ namespace CliFx.Tests
public async Task Property_of_type_bool_is_bound_as_true_if_the_argument_value_is_not_set()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -335,8 +313,7 @@ namespace CliFx.Tests
"cmd", "--bool"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -351,8 +328,7 @@ namespace CliFx.Tests
public async Task Property_of_type_char_is_bound_directly_from_the_argument_value_if_it_contains_only_one_character()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -365,8 +341,7 @@ namespace CliFx.Tests
"cmd", "--char", "a"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -381,8 +356,7 @@ namespace CliFx.Tests
public async Task Property_of_type_sbyte_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -395,8 +369,7 @@ namespace CliFx.Tests
"cmd", "--sbyte", "15"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -411,8 +384,7 @@ namespace CliFx.Tests
public async Task Property_of_type_byte_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -425,8 +397,7 @@ namespace CliFx.Tests
"cmd", "--byte", "15"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -441,8 +412,7 @@ namespace CliFx.Tests
public async Task Property_of_type_short_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -455,8 +425,7 @@ namespace CliFx.Tests
"cmd", "--short", "15"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -471,8 +440,7 @@ namespace CliFx.Tests
public async Task Property_of_type_ushort_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -485,8 +453,7 @@ namespace CliFx.Tests
"cmd", "--ushort", "15"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -501,8 +468,7 @@ namespace CliFx.Tests
public async Task Property_of_type_int_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -515,8 +481,7 @@ namespace CliFx.Tests
"cmd", "--int", "15"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -531,8 +496,7 @@ namespace CliFx.Tests
public async Task Property_of_type_nullable_int_is_bound_by_parsing_the_argument_value_if_it_is_set()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -545,8 +509,7 @@ namespace CliFx.Tests
"cmd", "--int-nullable", "15"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -561,8 +524,7 @@ namespace CliFx.Tests
public async Task Property_of_type_nullable_int_is_bound_as_null_if_the_argument_value_is_not_set()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -575,8 +537,7 @@ namespace CliFx.Tests
"cmd", "--int-nullable"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -591,8 +552,7 @@ namespace CliFx.Tests
public async Task Property_of_type_int_array_is_bound_by_parsing_the_argument_values()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -605,8 +565,7 @@ namespace CliFx.Tests
"cmd", "--int-array", "3", "15"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -621,8 +580,7 @@ namespace CliFx.Tests
public async Task Property_of_type_nullable_int_array_is_bound_by_parsing_the_argument_values()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -635,8 +593,7 @@ namespace CliFx.Tests
"cmd", "--int-nullable-array", "3", "15"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -651,8 +608,7 @@ namespace CliFx.Tests
public async Task Property_of_type_uint_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -665,8 +621,7 @@ namespace CliFx.Tests
"cmd", "--uint", "15"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -681,8 +636,7 @@ namespace CliFx.Tests
public async Task Property_of_type_long_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -695,8 +649,7 @@ namespace CliFx.Tests
"cmd", "--long", "15"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -711,8 +664,7 @@ namespace CliFx.Tests
public async Task Property_of_type_ulong_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -725,8 +677,7 @@ namespace CliFx.Tests
"cmd", "--ulong", "15"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -741,8 +692,7 @@ namespace CliFx.Tests
public async Task Property_of_type_float_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -755,8 +705,7 @@ namespace CliFx.Tests
"cmd", "--float", "3.14"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -771,8 +720,7 @@ namespace CliFx.Tests
public async Task Property_of_type_double_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -785,8 +733,7 @@ namespace CliFx.Tests
"cmd", "--double", "3.14"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -801,8 +748,7 @@ namespace CliFx.Tests
public async Task Property_of_type_decimal_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -815,8 +761,7 @@ namespace CliFx.Tests
"cmd", "--decimal", "3.14"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -831,8 +776,7 @@ namespace CliFx.Tests
public async Task Property_of_type_DateTime_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -845,8 +789,7 @@ namespace CliFx.Tests
"cmd", "--datetime", "28 Apr 1995"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -861,8 +804,7 @@ namespace CliFx.Tests
public async Task Property_of_type_DateTimeOffset_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -875,8 +817,7 @@ namespace CliFx.Tests
"cmd", "--datetime-offset", "28 Apr 1995"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -891,8 +832,7 @@ namespace CliFx.Tests
public async Task Property_of_type_TimeSpan_is_bound_by_parsing_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -905,8 +845,7 @@ namespace CliFx.Tests
"cmd", "--timespan", "00:14:59"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -921,8 +860,7 @@ namespace CliFx.Tests
public async Task Property_of_type_nullable_TimeSpan_is_bound_by_parsing_the_argument_value_if_it_is_set()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -935,8 +873,7 @@ namespace CliFx.Tests
"cmd", "--timespan-nullable", "00:14:59"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -951,8 +888,7 @@ namespace CliFx.Tests
public async Task Property_of_type_nullable_TimeSpan_is_bound_as_null_if_the_argument_value_is_not_set()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -965,8 +901,7 @@ namespace CliFx.Tests
"cmd", "--timespan-nullable"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -981,8 +916,7 @@ namespace CliFx.Tests
public async Task Property_of_an_enum_type_is_bound_by_parsing_the_argument_value_as_name()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -995,8 +929,7 @@ namespace CliFx.Tests
"cmd", "--enum", "value2"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -1011,8 +944,7 @@ namespace CliFx.Tests
public async Task Property_of_an_enum_type_is_bound_by_parsing_the_argument_value_as_id()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -1025,8 +957,7 @@ namespace CliFx.Tests
"cmd", "--enum", "2"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -1041,8 +972,7 @@ namespace CliFx.Tests
public async Task Property_of_a_nullable_enum_type_is_bound_by_parsing_the_argument_value_as_name_if_it_is_set()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -1055,8 +985,7 @@ namespace CliFx.Tests
"cmd", "--enum-nullable", "value3"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -1071,8 +1000,7 @@ namespace CliFx.Tests
public async Task Property_of_a_nullable_enum_type_is_bound_by_parsing_the_argument_value_as_id_if_it_is_set()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -1085,8 +1013,7 @@ namespace CliFx.Tests
"cmd", "--enum-nullable", "3"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -1101,8 +1028,7 @@ namespace CliFx.Tests
public async Task Property_of_a_nullable_enum_type_is_bound_as_null_if_the_argument_value_is_not_set()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -1115,8 +1041,7 @@ namespace CliFx.Tests
"cmd", "--enum-nullable"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -1131,8 +1056,7 @@ namespace CliFx.Tests
public async Task Property_of_an_enum_array_type_is_bound_by_parsing_the_argument_values_as_names()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -1145,8 +1069,7 @@ namespace CliFx.Tests
"cmd", "--enum-array", "value1", "value3"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -1161,8 +1084,7 @@ namespace CliFx.Tests
public async Task Property_of_an_enum_array_type_is_bound_by_parsing_the_argument_values_as_ids()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -1175,8 +1097,7 @@ namespace CliFx.Tests
"cmd", "--enum-array", "1", "3"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -1191,8 +1112,7 @@ namespace CliFx.Tests
public async Task Property_of_an_enum_array_type_is_bound_by_parsing_the_argument_values_as_either_names_or_ids()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -1205,8 +1125,7 @@ namespace CliFx.Tests
"cmd", "--enum-array", "1", "value3"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -1221,8 +1140,7 @@ namespace CliFx.Tests
public async Task Property_of_a_type_that_has_a_constructor_accepting_a_string_is_bound_by_invoking_the_constructor_with_the_argument_value()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -1235,8 +1153,7 @@ namespace CliFx.Tests
"cmd", "--str-constructible", "foobar"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -1251,8 +1168,7 @@ namespace CliFx.Tests
public async Task Property_of_an_array_of_type_that_has_a_constructor_accepting_a_string_is_bound_by_invoking_the_constructor_with_the_argument_values()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -1265,8 +1181,7 @@ namespace CliFx.Tests
"cmd", "--str-constructible-array", "foo", "bar"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -1285,8 +1200,7 @@ namespace CliFx.Tests
public async Task Property_of_a_type_that_has_a_static_Parse_method_accepting_a_string_is_bound_by_invoking_the_method()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -1299,8 +1213,7 @@ namespace CliFx.Tests
"cmd", "--str-parseable", "foobar"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -1315,8 +1228,7 @@ namespace CliFx.Tests
public async Task Property_of_a_type_that_has_a_static_Parse_method_accepting_a_string_and_format_provider_is_bound_by_invoking_the_method()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -1329,8 +1241,7 @@ namespace CliFx.Tests
"cmd", "--str-parseable-format", "foobar"
});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<SupportedArgumentTypesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<SupportedArgumentTypesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -1346,8 +1257,7 @@ namespace CliFx.Tests
public async Task Property_of_custom_type_must_be_string_initializable_in_order_to_be_bound()
{
// Arrange
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<UnsupportedArgumentTypesCommand>()
@@ -1360,21 +1270,18 @@ namespace CliFx.Tests
"cmd", "--str-non-initializable", "foobar"
});
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Property_of_custom_type_that_implements_IEnumerable_can_only_be_bound_if_that_type_has_a_constructor_accepting_an_array()
{
// Arrange
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<UnsupportedArgumentTypesCommand>()
@@ -1387,21 +1294,18 @@ namespace CliFx.Tests
"cmd", "--str-enumerable-non-initializable", "foobar"
});
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Property_of_non_nullable_type_can_only_be_bound_if_the_argument_value_is_set()
{
// Arrange
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -1414,21 +1318,18 @@ namespace CliFx.Tests
"cmd", "--int"
});
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Property_must_have_a_type_that_implements_IEnumerable_in_order_to_be_bound_from_multiple_argument_values()
{
// Arrange
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(error: stdErr);
var (console, _, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<SupportedArgumentTypesCommand>()
@@ -1441,13 +1342,11 @@ namespace CliFx.Tests
"cmd", "--int", "1", "2", "3"
});
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdErrData.Should().NotBeEmpty();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdErrData);
_output.WriteLine(stdErr.GetString());
}
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using CliFx.Tests.Commands;
@@ -17,9 +16,7 @@ namespace CliFx.Tests
// Arrange
using var cts = new CancellationTokenSource();
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut, cancellationToken: cts.Token);
var (console, stdOut, _) = VirtualConsole.CreateBuffered(cts.Token);
var application = new CliApplicationBuilder()
.AddCommand<CancellableCommand>()
@@ -30,11 +27,10 @@ namespace CliFx.Tests
cts.CancelAfter(TimeSpan.FromSeconds(0.2));
var exitCode = await application.RunAsync(new[] {"cmd"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdOutData.Should().Be(CancellableCommand.CancellationOutputText);
stdOut.GetString().Trim().Should().Be(CancellableCommand.CancellationOutputText);
}
}
}

View File

@@ -3,7 +3,7 @@ using CliFx.Attributes;
namespace CliFx.Tests.Commands
{
[Command(Description = nameof(DefaultCommand))]
[Command(Description = "Default command description")]
public class DefaultCommand : ICommand
{
public const string ExpectedOutputText = nameof(DefaultCommand);

View File

@@ -3,7 +3,7 @@ using CliFx.Attributes;
namespace CliFx.Tests.Commands
{
[Command("named", Description = nameof(NamedCommand))]
[Command("named", Description = "Named command description")]
public class NamedCommand : ICommand
{
public const string ExpectedOutputText = nameof(NamedCommand);

View File

@@ -3,7 +3,7 @@ using CliFx.Attributes;
namespace CliFx.Tests.Commands
{
[Command("named sub", Description = nameof(NamedSubCommand))]
[Command("named sub", Description = "Named sub command description")]
public class NamedSubCommand : ICommand
{
public const string ExpectedOutputText = nameof(NamedSubCommand);

View File

@@ -18,8 +18,7 @@ namespace CliFx.Tests
public async Task Preview_directive_can_be_specified_to_print_provided_arguments_as_they_were_parsed()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<NamedCommand>()
@@ -32,13 +31,13 @@ namespace CliFx.Tests
new[] {"[preview]", "named", "param", "-abc", "--option", "foo"},
new Dictionary<string, string>());
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().ContainAll("named", "<param>", "[-a]", "[-b]", "[-c]", "[--option \"foo\"]");
stdOut.GetString().Should().ContainAll(
"named", "<param>", "[-a]", "[-b]", "[-c]", "[--option \"foo\"]"
);
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
}
}

View File

@@ -2,10 +2,10 @@
using System.IO;
using System.Threading.Tasks;
using CliFx.Tests.Commands;
using CliFx.Tests.Internal;
using CliWrap;
using CliWrap.Buffered;
using FluentAssertions;
using Newtonsoft.Json;
using Xunit;
namespace CliFx.Tests
@@ -27,7 +27,7 @@ namespace CliFx.Tests
var stdOut = await command.ExecuteBufferedAsync().Select(r => r.StandardOutput);
// Assert
stdOut.TrimEnd().Should().Be("Hello Mars!");
stdOut.Trim().Should().Be("Hello Mars!");
}
// This test uses a real application to make sure environment variables are actually read correctly
@@ -47,14 +47,13 @@ namespace CliFx.Tests
var stdOut = await command.ExecuteBufferedAsync().Select(r => r.StandardOutput);
// Assert
stdOut.TrimEnd().Should().Be("Hello Jupiter!");
stdOut.Trim().Should().Be("Hello Jupiter!");
}
[Fact]
public async Task Option_only_uses_an_environment_variable_as_fallback_if_the_name_matches_case_sensitively()
{
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithEnvironmentVariablesCommand>()
@@ -71,8 +70,7 @@ namespace CliFx.Tests
}
);
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<WithEnvironmentVariablesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<WithEnvironmentVariablesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -85,8 +83,7 @@ namespace CliFx.Tests
[Fact]
public async Task Option_of_non_scalar_type_can_use_an_environment_variable_as_fallback_and_extract_multiple_values()
{
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithEnvironmentVariablesCommand>()
@@ -102,8 +99,7 @@ namespace CliFx.Tests
}
);
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<WithEnvironmentVariablesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<WithEnvironmentVariablesCommand>();
// Assert
exitCode.Should().Be(0);
@@ -116,8 +112,7 @@ namespace CliFx.Tests
[Fact]
public async Task Option_of_scalar_type_can_use_an_environment_variable_as_fallback_regardless_of_separators()
{
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithEnvironmentVariablesCommand>()
@@ -133,8 +128,7 @@ namespace CliFx.Tests
}
);
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var commandInstance = JsonConvert.DeserializeObject<WithEnvironmentVariablesCommand>(stdOutData);
var commandInstance = stdOut.GetString().DeserializeJson<WithEnvironmentVariablesCommand>();
// Assert
exitCode.Should().Be(0);

View File

@@ -1,5 +1,4 @@
using System.IO;
using System.Threading.Tasks;
using System.Threading.Tasks;
using CliFx.Tests.Commands;
using FluentAssertions;
using Xunit;
@@ -17,10 +16,7 @@ namespace CliFx.Tests
public async Task Command_may_throw_a_generic_exception_which_exits_and_prints_error_message_and_stack_trace()
{
// Arrange
await using var stdOut = new MemoryStream();
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(output: stdOut, error: stdErr);
var (console, stdOut, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<GenericExceptionCommand>()
@@ -30,30 +26,24 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"cmd", "-m", "Kaput"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdOutData.Should().BeEmpty();
stdErrData.Should().ContainAll(
stdOut.GetString().Should().BeEmpty();
stdErr.GetString().Should().ContainAll(
"System.Exception:",
"Kaput", "at",
"CliFx.Tests"
);
_output.WriteLine(stdOutData);
_output.WriteLine(stdErrData);
_output.WriteLine(stdOut.GetString());
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_may_throw_a_specialized_exception_which_exits_with_custom_code_and_prints_minimal_error_details()
{
// Arrange
await using var stdOut = new MemoryStream();
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(output: stdOut, error: stdErr);
var (console, stdOut, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<CommandExceptionCommand>()
@@ -63,26 +53,20 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"cmd", "-m", "Kaput", "-c", "69"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(69);
stdOutData.Should().BeEmpty();
stdErrData.Should().Be("Kaput");
stdOut.GetString().Should().BeEmpty();
stdErr.GetString().Trim().Should().Be("Kaput");
_output.WriteLine(stdOutData);
_output.WriteLine(stdErrData);
_output.WriteLine(stdOut.GetString());
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_may_throw_a_specialized_exception_without_error_message_which_exits_and_prints_full_error_details()
{
// Arrange
await using var stdOut = new MemoryStream();
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(output: stdOut, error: stdErr);
var (console, stdOut, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<CommandExceptionCommand>()
@@ -92,30 +76,24 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"cmd"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdOutData.Should().BeEmpty();
stdErrData.Should().ContainAll(
stdOut.GetString().Should().BeEmpty();
stdErr.GetString().Should().ContainAll(
"CliFx.Exceptions.CommandException:",
"at",
"CliFx.Tests"
);
_output.WriteLine(stdOutData);
_output.WriteLine(stdErrData);
_output.WriteLine(stdOut.GetString());
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_may_throw_a_specialized_exception_which_exits_and_prints_help_text()
{
// Arrange
await using var stdOut = new MemoryStream();
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(output: stdOut, error: stdErr);
var (console, stdOut, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<CommandExceptionCommand>()
@@ -125,30 +103,24 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"cmd", "-m", "Kaput", "--show-help"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdOutData.Should().ContainAll(
stdOut.GetString().Should().ContainAll(
"Usage",
"Options",
"-h|--help"
);
stdErrData.Should().Be("Kaput");
stdErr.GetString().Trim().Should().Be("Kaput");
_output.WriteLine(stdOutData);
_output.WriteLine(stdErrData);
_output.WriteLine(stdOut.GetString());
_output.WriteLine(stdErr.GetString());
}
[Fact]
public async Task Command_shows_help_text_on_invalid_user_input()
{
// Arrange
await using var stdOut = new MemoryStream();
await using var stdErr = new MemoryStream();
var console = new VirtualConsole(output: stdOut, error: stdErr);
var (console, stdOut, stdErr) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DefaultCommand>()
@@ -158,20 +130,17 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"not-a-valid-command", "-r", "foo"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
var stdErrData = console.Error.Encoding.GetString(stdErr.ToArray()).TrimEnd();
// Assert
exitCode.Should().NotBe(0);
stdOutData.Should().ContainAll(
stdOut.GetString().Should().ContainAll(
"Usage",
"Options",
"-h|--help"
);
stdErrData.Should().NotBeNullOrWhiteSpace();
stdErr.GetString().Should().NotBeNullOrWhiteSpace();
_output.WriteLine(stdOutData);
_output.WriteLine(stdErrData);
_output.WriteLine(stdOut.GetString());
_output.WriteLine(stdErr.GetString());
}
}
}

View File

@@ -1,5 +1,4 @@
using System.IO;
using System.Threading.Tasks;
using System.Threading.Tasks;
using CliFx.Tests.Commands;
using FluentAssertions;
using Xunit;
@@ -17,8 +16,7 @@ namespace CliFx.Tests
public async Task Help_text_shows_usage_format_which_lists_all_parameters()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithParametersCommand>()
@@ -27,24 +25,22 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"cmd", "--help"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().ContainAll(
stdOut.GetString().Should().ContainAll(
"Usage",
"cmd", "<parama>", "<paramb>", "<paramc...>"
);
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
[Fact]
public async Task Help_text_shows_usage_format_which_lists_all_required_options()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithRequiredOptionsCommand>()
@@ -53,11 +49,10 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"cmd", "--help"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().ContainAll(
stdOut.GetString().Should().ContainAll(
"Usage",
"cmd", "--opt-a <value>", "--opt-c <values...>", "[options]",
"Options",
@@ -66,15 +61,14 @@ namespace CliFx.Tests
"* -c|--opt-c"
);
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
[Fact]
public async Task Help_text_shows_all_valid_values_for_enum_arguments()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithEnumArgumentsCommand>()
@@ -83,11 +77,10 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"cmd", "--help"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().ContainAll(
stdOut.GetString().Should().ContainAll(
"Parameters",
"enum", "Valid values: \"Value1\", \"Value2\", \"Value3\".",
"Options",
@@ -95,15 +88,14 @@ namespace CliFx.Tests
"* --required-enum", "Valid values: \"Value1\", \"Value2\", \"Value3\"."
);
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
[Fact]
public async Task Help_text_shows_environment_variable_names_for_options_that_have_them_defined()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithEnvironmentVariablesCommand>()
@@ -112,25 +104,23 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"cmd", "--help"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().ContainAll(
stdOut.GetString().Should().ContainAll(
"Options",
"-a|--opt-a", "Environment variable:", "ENV_OPT_A",
"-b|--opt-b", "Environment variable:", "ENV_OPT_B"
);
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
[Fact]
public async Task Help_text_shows_default_values_for_non_required_options()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<WithDefaultValuesCommand>()
@@ -139,11 +129,10 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"cmd", "--help"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().ContainAll(
stdOut.GetString().Should().ContainAll(
"Options",
"--obj", "Default: \"42\"",
"--str", "Default: \"foo\"",
@@ -158,7 +147,7 @@ namespace CliFx.Tests
"--enum", "Default: \"Value2\""
);
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
}
}

View File

@@ -0,0 +1,10 @@
using Newtonsoft.Json;
namespace CliFx.Tests.Internal
{
internal static class JsonExtensions
{
public static T DeserializeJson<T>(this string json) =>
JsonConvert.DeserializeObject<T>(json);
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.IO;
using System.Threading.Tasks;
using CliFx.Tests.Commands;
using FluentAssertions;
@@ -18,8 +17,7 @@ namespace CliFx.Tests
public async Task Default_command_is_executed_if_provided_arguments_do_not_match_any_named_command()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DefaultCommand>()
@@ -30,21 +28,19 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().Be(DefaultCommand.ExpectedOutputText);
stdOut.GetString().Trim().Should().Be(DefaultCommand.ExpectedOutputText);
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
[Fact]
public async Task Specific_named_command_is_executed_if_provided_arguments_match_its_name()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DefaultCommand>()
@@ -55,21 +51,19 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"named"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().Be(NamedCommand.ExpectedOutputText);
stdOut.GetString().Trim().Should().Be(NamedCommand.ExpectedOutputText);
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
[Fact]
public async Task Specific_named_sub_command_is_executed_if_provided_arguments_match_its_name()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DefaultCommand>()
@@ -80,21 +74,19 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"named", "sub"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().Be(NamedSubCommand.ExpectedOutputText);
stdOut.GetString().Trim().Should().Be(NamedSubCommand.ExpectedOutputText);
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
[Fact]
public async Task Help_text_is_printed_if_no_arguments_were_provided_and_default_command_is_not_defined()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<NamedCommand>()
@@ -105,21 +97,19 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(Array.Empty<string>());
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().Contain("This will be visible in help");
stdOut.GetString().Should().Contain("This will be visible in help");
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
[Fact]
public async Task Help_text_is_printed_if_provided_arguments_contain_the_help_option()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DefaultCommand>()
@@ -130,24 +120,22 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"--help"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().ContainAll(
nameof(DefaultCommand),
stdOut.GetString().Should().ContainAll(
"Default command description",
"Usage"
);
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
[Fact]
public async Task Help_text_is_printed_if_provided_arguments_contain_the_help_option_even_if_default_command_is_not_defined()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<NamedCommand>()
@@ -158,21 +146,19 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"--help"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().Contain("This will be visible in help");
stdOut.GetString().Should().Contain("This will be visible in help");
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
[Fact]
public async Task Help_text_for_a_specific_named_command_is_printed_if_provided_arguments_match_its_name_and_contain_the_help_option()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DefaultCommand>()
@@ -183,25 +169,23 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"named", "--help"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().ContainAll(
nameof(NamedCommand),
stdOut.GetString().Should().ContainAll(
"Named command description",
"Usage",
"named"
);
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
[Fact]
public async Task Help_text_for_a_specific_named_sub_command_is_printed_if_provided_arguments_match_its_name_and_contain_the_help_option()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DefaultCommand>()
@@ -212,25 +196,23 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"named", "sub", "--help"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().ContainAll(
nameof(NamedSubCommand),
stdOut.GetString().Should().ContainAll(
"Named sub command description",
"Usage",
"named", "sub"
);
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
[Fact]
public async Task Version_is_printed_if_the_only_provided_argument_is_the_version_option()
{
// Arrange
await using var stdOut = new MemoryStream();
var console = new VirtualConsole(output: stdOut);
var (console, stdOut, _) = VirtualConsole.CreateBuffered();
var application = new CliApplicationBuilder()
.AddCommand<DefaultCommand>()
@@ -242,13 +224,12 @@ namespace CliFx.Tests
// Act
var exitCode = await application.RunAsync(new[] {"--version"});
var stdOutData = console.Output.Encoding.GetString(stdOut.ToArray()).TrimEnd();
// Assert
exitCode.Should().Be(0);
stdOutData.Should().Be("v6.9");
stdOut.GetString().Trim().Should().Be("v6.9");
_output.WriteLine(stdOutData);
_output.WriteLine(stdOut.GetString());
}
}
}

View File

@@ -0,0 +1,43 @@
using System.IO;
using System.Text;
namespace CliFx.Utilities
{
/// <summary>
/// Implementation of <see cref="StreamWriter"/> with a <see cref="MemoryStream"/> as a backing store.
/// </summary>
public class MemoryStreamWriter : StreamWriter
{
private new MemoryStream BaseStream => (MemoryStream) base.BaseStream;
/// <summary>
/// Initializes an instance of <see cref="MemoryStreamWriter"/>.
/// </summary>
public MemoryStreamWriter(Encoding encoding)
: base(new MemoryStream(), encoding)
{
}
/// <summary>
/// Initializes an instance of <see cref="MemoryStreamWriter"/>.
/// </summary>
public MemoryStreamWriter()
: base(new MemoryStream())
{
}
/// <summary>
/// Gets the bytes written to the underlying stream.
/// </summary>
public byte[] GetBytes()
{
Flush();
return BaseStream.ToArray();
}
/// <summary>
/// Gets the string written to the underlying stream.
/// </summary>
public string GetString() => Encoding.GetString(GetBytes());
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Threading;
using CliFx.Utilities;
namespace CliFx
{
@@ -101,5 +102,25 @@ namespace CliFx
stream != null
? new StreamWriter(Stream.Synchronized(stream), Console.OutputEncoding) {AutoFlush = true}
: StreamWriter.Null;
/// <summary>
/// Creates a <see cref="VirtualConsole"/> that uses in-memory output and error streams.
/// Use the exposed streams to easily get the current output.
/// </summary>
public static (VirtualConsole console, MemoryStreamWriter output, MemoryStreamWriter error) CreateBuffered(
CancellationToken cancellationToken = default)
{
// Memory streams don't need to be disposed
var output = new MemoryStreamWriter(Console.OutputEncoding);
var error = new MemoryStreamWriter(Console.OutputEncoding);
var console = new VirtualConsole(
output: output,
error: error,
cancellationToken: cancellationToken
);
return (console, output, error);
}
}
}