fixed line-endings

This commit is contained in:
Nils Andresen
2023-11-27 12:41:08 +01:00
committed by Patrik Svensson
parent 989c0b9904
commit 44300c871f
79 changed files with 2696 additions and 2696 deletions

View File

@ -5,7 +5,7 @@ public static class SpectreAnalyzerVerifier<TAnalyzer>
{
public static Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource)
=> VerifyCodeFixAsync(source, OutputKind.DynamicallyLinkedLibrary, new[] { expected }, fixedSource);
public static Task VerifyCodeFixAsync(string source, OutputKind outputKind, DiagnosticResult expected, string fixedSource)
=> VerifyCodeFixAsync(source, outputKind, new[] { expected }, fixedSource);
@ -13,10 +13,10 @@ public static class SpectreAnalyzerVerifier<TAnalyzer>
{
var test = new Test
{
TestCode = source,
TestState =
{
OutputKind = outputKind,
TestCode = source,
TestState =
{
OutputKind = outputKind,
},
FixedCode = fixedSource,
};

View File

@ -1,28 +1,28 @@
namespace Spectre.Console.Tests.Data;
public sealed class AsynchronousCommand : AsyncCommand<AsynchronousCommandSettings>
{
private readonly IAnsiConsole _console;
public AsynchronousCommand(IAnsiConsole console)
{
_console = console;
}
public async override Task<int> ExecuteAsync(CommandContext context, AsynchronousCommandSettings settings)
{
// Simulate a long running asynchronous task
await Task.Delay(200);
if (settings.ThrowException)
{
throw new Exception($"Throwing exception asynchronously");
}
else
{
_console.WriteLine($"Finished executing asynchronously");
}
return 0;
}
}
namespace Spectre.Console.Tests.Data;
public sealed class AsynchronousCommand : AsyncCommand<AsynchronousCommandSettings>
{
private readonly IAnsiConsole _console;
public AsynchronousCommand(IAnsiConsole console)
{
_console = console;
}
public async override Task<int> ExecuteAsync(CommandContext context, AsynchronousCommandSettings settings)
{
// Simulate a long running asynchronous task
await Task.Delay(200);
if (settings.ThrowException)
{
throw new Exception($"Throwing exception asynchronously");
}
else
{
_console.WriteLine($"Finished executing asynchronously");
}
return 0;
}
}

View File

@ -1,17 +1,17 @@
using Spectre.Console;
public class GreeterCommand : Command<OptionalArgumentWithDefaultValueSettings>
{
private readonly IAnsiConsole _console;
public GreeterCommand(IAnsiConsole console)
{
_console = console;
}
public override int Execute(CommandContext context, OptionalArgumentWithDefaultValueSettings settings)
{
_console.WriteLine(settings.Greeting);
return 0;
}
using Spectre.Console;
public class GreeterCommand : Command<OptionalArgumentWithDefaultValueSettings>
{
private readonly IAnsiConsole _console;
public GreeterCommand(IAnsiConsole console)
{
_console = console;
}
public override int Execute(CommandContext context, OptionalArgumentWithDefaultValueSettings settings)
{
_console.WriteLine(settings.Greeting);
return 0;
}
}

View File

@ -1,34 +1,34 @@
using Spectre.Console.Rendering;
namespace Spectre.Console.Cli.Tests.Data.Help;
internal class CustomHelpProvider : HelpProvider
{
private readonly string version;
public CustomHelpProvider(ICommandAppSettings settings, string version)
: base(settings)
{
this.version = version;
}
public override IEnumerable<IRenderable> GetHeader(ICommandModel model, ICommandInfo command)
{
return new IRenderable[]
{
new Text("--------------------------------------"), Text.NewLine,
new Text("--- CUSTOM HELP PROVIDER ---"), Text.NewLine,
new Text("--------------------------------------"), Text.NewLine,
Text.NewLine,
};
}
public override IEnumerable<IRenderable> GetFooter(ICommandModel model, ICommandInfo command)
{
return new IRenderable[]
{
Text.NewLine,
new Text($"Version {version}"),
};
}
}
using Spectre.Console.Rendering;
namespace Spectre.Console.Cli.Tests.Data.Help;
internal class CustomHelpProvider : HelpProvider
{
private readonly string version;
public CustomHelpProvider(ICommandAppSettings settings, string version)
: base(settings)
{
this.version = version;
}
public override IEnumerable<IRenderable> GetHeader(ICommandModel model, ICommandInfo command)
{
return new IRenderable[]
{
new Text("--------------------------------------"), Text.NewLine,
new Text("--- CUSTOM HELP PROVIDER ---"), Text.NewLine,
new Text("--------------------------------------"), Text.NewLine,
Text.NewLine,
};
}
public override IEnumerable<IRenderable> GetFooter(ICommandModel model, ICommandInfo command)
{
return new IRenderable[]
{
Text.NewLine,
new Text($"Version {version}"),
};
}
}

View File

@ -1,21 +1,21 @@
using Spectre.Console.Rendering;
namespace Spectre.Console.Cli.Tests.Data.Help;
internal class RedirectHelpProvider : IHelpProvider
{
public virtual IEnumerable<IRenderable> Write(ICommandModel model)
{
return Write(model, null);
}
#nullable enable
public virtual IEnumerable<IRenderable> Write(ICommandModel model, ICommandInfo? command)
#nullable disable
{
return new[]
{
new Text("Help has moved online. Please see: http://www.example.com"),
Text.NewLine,
};
}
using Spectre.Console.Rendering;
namespace Spectre.Console.Cli.Tests.Data.Help;
internal class RedirectHelpProvider : IHelpProvider
{
public virtual IEnumerable<IRenderable> Write(ICommandModel model)
{
return Write(model, null);
}
#nullable enable
public virtual IEnumerable<IRenderable> Write(ICommandModel model, ICommandInfo? command)
#nullable disable
{
return new[]
{
new Text("Help has moved online. Please see: http://www.example.com"),
Text.NewLine,
};
}
}

View File

@ -1,8 +1,8 @@
namespace Spectre.Console.Tests.Data;
public sealed class AsynchronousCommandSettings : CommandSettings
{
[CommandOption("--ThrowException")]
[DefaultValue(false)]
public bool ThrowException { get; set; }
namespace Spectre.Console.Tests.Data;
public sealed class AsynchronousCommandSettings : CommandSettings
{
[CommandOption("--ThrowException")]
[DefaultValue(false)]
public bool ThrowException { get; set; }
}

View File

@ -1,4 +1,4 @@
namespace Spectre.Console.Tests.Data;
namespace Spectre.Console.Tests.Data;
public class ReptileSettings : AnimalSettings
{

View File

@ -1,5 +1,5 @@
namespace Spectre.Console.Tests.Data;
public sealed class ThrowingCommandSettings : CommandSettings
{
}
namespace Spectre.Console.Tests.Data;
public sealed class ThrowingCommandSettings : CommandSettings
{
}

View File

@ -7,7 +7,7 @@ global using System.Linq;
global using System.Runtime.CompilerServices;
global using System.Threading.Tasks;
global using Shouldly;
global using Spectre.Console.Cli;
global using Spectre.Console.Cli;
global using Spectre.Console.Cli.Help;
global using Spectre.Console.Cli.Unsafe;
global using Spectre.Console.Testing;

View File

@ -1,70 +1,70 @@
namespace Spectre.Console.Tests.Unit.Cli;
public sealed partial class CommandAppTests
{
public sealed class Async
{
[Fact]
public async void Should_Execute_Command_Asynchronously()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<AsynchronousCommand>();
app.Configure(config =>
{
config.PropagateExceptions();
});
// When
var result = await app.RunAsync();
// Then
result.ExitCode.ShouldBe(0);
result.Output.ShouldBe("Finished executing asynchronously");
}
[Fact]
public async void Should_Handle_Exception_Asynchronously()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<AsynchronousCommand>();
// When
var result = await app.RunAsync(new[]
{
"--ThrowException",
"true",
});
// Then
result.ExitCode.ShouldBe(-1);
}
[Fact]
public async void Should_Throw_Exception_Asynchronously()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<AsynchronousCommand>();
app.Configure(config =>
{
config.PropagateExceptions();
});
// When
var result = await Record.ExceptionAsync(async () =>
await app.RunAsync(new[]
{
"--ThrowException",
"true",
}));
// Then
result.ShouldBeOfType<Exception>().And(ex =>
{
ex.Message.ShouldBe("Throwing exception asynchronously");
});
}
}
namespace Spectre.Console.Tests.Unit.Cli;
public sealed partial class CommandAppTests
{
public sealed class Async
{
[Fact]
public async void Should_Execute_Command_Asynchronously()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<AsynchronousCommand>();
app.Configure(config =>
{
config.PropagateExceptions();
});
// When
var result = await app.RunAsync();
// Then
result.ExitCode.ShouldBe(0);
result.Output.ShouldBe("Finished executing asynchronously");
}
[Fact]
public async void Should_Handle_Exception_Asynchronously()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<AsynchronousCommand>();
// When
var result = await app.RunAsync(new[]
{
"--ThrowException",
"true",
});
// Then
result.ExitCode.ShouldBe(-1);
}
[Fact]
public async void Should_Throw_Exception_Asynchronously()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<AsynchronousCommand>();
app.Configure(config =>
{
config.PropagateExceptions();
});
// When
var result = await Record.ExceptionAsync(async () =>
await app.RunAsync(new[]
{
"--ThrowException",
"true",
}));
// Then
result.ShouldBeOfType<Exception>().And(ex =>
{
ex.Message.ShouldBe("Throwing exception asynchronously");
});
}
}
}

View File

@ -3,133 +3,133 @@ namespace Spectre.Console.Tests.Unit.Cli;
public sealed partial class CommandAppTests
{
public sealed class Branches
{
{
[Fact]
public void Should_Run_The_Default_Command_On_Branch()
{
// Given
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
{
config.PropagateExceptions();
config.AddBranch<AnimalSettings>("animal", animal =>
{
animal.SetDefaultCommand<CatCommand>();
animal.SetDefaultCommand<CatCommand>();
});
});
// When
var result = app.Run(new[]
});
// When
var result = app.Run(new[]
{
"animal", "4",
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<CatSettings>();
}
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<CatSettings>();
}
[Fact]
public void Should_Throw_When_No_Default_Command_On_Branch()
{
// Given
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
{
config.PropagateExceptions();
config.AddBranch<AnimalSettings>("animal", animal => { });
});
// When
var result = Record.Exception(() =>
{
app.Run(new[]
{
"animal", "4",
});
});
// Then
result.ShouldBeOfType<CommandConfigurationException>().And(ex =>
{
ex.Message.ShouldBe("The branch 'animal' does not define any commands.");
});
}
[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1515:SingleLineCommentMustBePrecededByBlankLine", Justification = "Helps to illustrate the expected behaviour of this unit test.")]
[SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1005:SingleLineCommentsMustBeginWithSingleSpace", Justification = "Helps to illustrate the expected behaviour of this unit test.")]
[Fact]
});
// When
var result = Record.Exception(() =>
{
app.Run(new[]
{
"animal", "4",
});
});
// Then
result.ShouldBeOfType<CommandConfigurationException>().And(ex =>
{
ex.Message.ShouldBe("The branch 'animal' does not define any commands.");
});
}
[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1515:SingleLineCommentMustBePrecededByBlankLine", Justification = "Helps to illustrate the expected behaviour of this unit test.")]
[SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1005:SingleLineCommentsMustBeginWithSingleSpace", Justification = "Helps to illustrate the expected behaviour of this unit test.")]
[Fact]
public void Should_Be_Unable_To_Parse_Default_Command_Arguments_Relaxed_Parsing()
{
// Given
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
{
config.PropagateExceptions();
config.AddBranch<AnimalSettings>("animal", animal =>
{
animal.SetDefaultCommand<CatCommand>();
animal.SetDefaultCommand<CatCommand>();
});
});
// When
var result = app.Run(new[]
{
// The CommandTreeParser should be unable to determine which command line
// arguments belong to the branch and which belong to the branch's
});
// When
var result = app.Run(new[]
{
// The CommandTreeParser should be unable to determine which command line
// arguments belong to the branch and which belong to the branch's
// default command (once inserted).
"animal", "4", "--name", "Kitty",
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<CatSettings>().And(cat =>
{
cat.Legs.ShouldBe(4);
//cat.Name.ShouldBe("Kitty"); //<-- Should normally be correct, but instead name will be added to the remaining arguments (see below).
});
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<CatSettings>().And(cat =>
{
cat.Legs.ShouldBe(4);
//cat.Name.ShouldBe("Kitty"); //<-- Should normally be correct, but instead name will be added to the remaining arguments (see below).
});
result.Context.Remaining.Parsed.Count.ShouldBe(1);
result.Context.ShouldHaveRemainingArgument("name", values: new[] { "Kitty", });
}
[Fact]
result.Context.ShouldHaveRemainingArgument("name", values: new[] { "Kitty", });
}
[Fact]
public void Should_Be_Unable_To_Parse_Default_Command_Arguments_Strict_Parsing()
{
// Given
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
config.UseStrictParsing();
{
config.UseStrictParsing();
config.PropagateExceptions();
config.AddBranch<AnimalSettings>("animal", animal =>
{
animal.SetDefaultCommand<CatCommand>();
animal.SetDefaultCommand<CatCommand>();
});
});
// When
var result = Record.Exception(() =>
{
app.Run(new[]
{
// The CommandTreeParser should be unable to determine which command line
// arguments belong to the branch and which belong to the branch's
});
// When
var result = Record.Exception(() =>
{
app.Run(new[]
{
// The CommandTreeParser should be unable to determine which command line
// arguments belong to the branch and which belong to the branch's
// default command (once inserted).
"animal", "4", "--name", "Kitty",
});
});
// Then
result.ShouldBeOfType<CommandParseException>().And(ex =>
{
ex.Message.ShouldBe("Unknown option 'name'.");
});
}
"animal", "4", "--name", "Kitty",
});
});
// Then
result.ShouldBeOfType<CommandParseException>().And(ex =>
{
ex.Message.ShouldBe("Unknown option 'name'.");
});
}
[Fact]
public void Should_Run_The_Default_Command_On_Branch_On_Branch()
{
// Given
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
@ -141,23 +141,23 @@ public sealed partial class CommandAppTests
mammal.SetDefaultCommand<CatCommand>();
});
});
});
// When
var result = app.Run(new[]
});
// When
var result = app.Run(new[]
{
"animal", "4", "mammal",
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<CatSettings>();
}
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<CatSettings>();
}
[Fact]
public void Should_Run_The_Default_Command_On_Branch_On_Branch_With_Arguments()
{
// Given
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
@ -169,83 +169,83 @@ public sealed partial class CommandAppTests
mammal.SetDefaultCommand<CatCommand>();
});
});
});
// When
var result = app.Run(new[]
});
// When
var result = app.Run(new[]
{
"animal", "4", "mammal", "--name", "Kitty",
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<CatSettings>().And(cat =>
{
cat.Legs.ShouldBe(4);
cat.Name.ShouldBe("Kitty");
});
}
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<CatSettings>().And(cat =>
{
cat.Legs.ShouldBe(4);
cat.Name.ShouldBe("Kitty");
});
}
[Fact]
public void Should_Run_The_Default_Command_Not_The_Named_Command_On_Branch()
{
// Given
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
{
config.PropagateExceptions();
config.AddBranch<AnimalSettings>("animal", animal =>
{
animal.AddCommand<DogCommand>("dog");
animal.AddCommand<DogCommand>("dog");
animal.SetDefaultCommand<CatCommand>();
animal.SetDefaultCommand<CatCommand>();
});
});
// When
var result = app.Run(new[]
});
// When
var result = app.Run(new[]
{
"animal", "4",
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<CatSettings>();
}
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<CatSettings>();
}
[Fact]
public void Should_Run_The_Named_Command_Not_The_Default_Command_On_Branch()
{
// Given
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
config.PropagateExceptions();
config.AddBranch<AnimalSettings>("animal", animal =>
{
animal.AddCommand<DogCommand>("dog");
animal.AddCommand<DogCommand>("dog");
animal.SetDefaultCommand<LionCommand>();
animal.SetDefaultCommand<LionCommand>();
});
});
// When
var result = app.Run(new[]
});
// When
var result = app.Run(new[]
{
"animal", "4", "dog", "12", "--good-boy", "--name", "Rufus",
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
{
dog.Legs.ShouldBe(4);
dog.Age.ShouldBe(12);
dog.GoodBoy.ShouldBe(true);
dog.Name.ShouldBe("Rufus");
});
}
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
{
dog.Legs.ShouldBe(4);
dog.Age.ShouldBe(12);
dog.GoodBoy.ShouldBe(true);
dog.Name.ShouldBe("Rufus");
});
}
[Fact]
public void Should_Allow_Multiple_Branches_Multiple_Commands()
{

View File

@ -1,5 +1,5 @@
using Spectre.Console.Cli.Tests.Data.Help;
using Spectre.Console.Cli.Tests.Data.Help;
namespace Spectre.Console.Tests.Unit.Cli;
public sealed partial class CommandAppTests
@ -93,12 +93,12 @@ public sealed partial class CommandAppTests
});
// When
var result = fixture.Run("cat", "--help");
var result = fixture.Run("cat", "--help");
// Then
return Verifier.Verify(result.Output);
}
}
[Fact]
[Expectation("Branch_Called_Without_Help")]
public Task Should_Output_Branch_When_Called_Without_Help_Option()
@ -110,27 +110,27 @@ public sealed partial class CommandAppTests
configurator.SetApplicationName("myapp");
configurator.AddBranch<CatSettings>("cat", animal =>
{
animal.SetDescription("Contains settings for a cat.");
animal.SetDescription("Contains settings for a cat.");
animal.AddCommand<LionCommand>("lion");
});
});
// When
var result = fixture.Run("cat");
var result = fixture.Run("cat");
// Then
return Verifier.Verify(result.Output);
}
}
[Fact]
[Expectation("Branch_Default_Greeter")]
[Expectation("Branch_Default_Greeter")]
public Task Should_Output_Branch_With_Default_Correctly()
{
// Given
var fixture = new CommandAppTester();
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
configurator.SetApplicationName("myapp");
configurator.AddBranch<OptionalArgumentWithDefaultValueSettings>("branch", animal =>
{
animal.SetDefaultCommand<GreeterCommand>();
@ -138,8 +138,8 @@ public sealed partial class CommandAppTests
});
});
// When
var result = fixture.Run("branch", "--help");
// When
var result = fixture.Run("branch", "--help");
// Then
return Verifier.Verify(result.Output);
@ -186,7 +186,7 @@ public sealed partial class CommandAppTests
});
// When
var result = fixture.Run("cat", "lion", "--help");
var result = fixture.Run("cat", "lion", "--help");
// Then
return Verifier.Verify(result.Output);
@ -233,13 +233,13 @@ public sealed partial class CommandAppTests
[Theory]
[InlineData(null, "EN")]
[InlineData("", "EN")]
[InlineData("en", "EN")]
[InlineData("en", "EN")]
[InlineData("en-EN", "EN")]
[InlineData("fr", "FR")]
[InlineData("fr", "FR")]
[InlineData("fr-FR", "FR")]
[InlineData("sv", "SV")]
[InlineData("sv", "SV")]
[InlineData("sv-SE", "SV")]
[InlineData("de", "DE")]
[InlineData("de", "DE")]
[InlineData("de-DE", "DE")]
[Expectation("Default_Without_Args_Additional")]
public Task Should_Output_Default_Command_And_Additional_Commands_When_Default_Command_Has_Required_Parameters_And_Is_Called_Without_Args_Localised(string culture, string expectationPrefix)
@ -281,106 +281,106 @@ public sealed partial class CommandAppTests
// Then
return Verifier.Verify(result.Output);
}
}
[Fact]
[Expectation("Custom_Help_Registered_By_Instance")]
public Task Should_Output_Custom_Help_When_Registered_By_Instance()
{
var registrar = new DefaultTypeRegistrar();
// Given
var fixture = new CommandAppTester(registrar);
fixture.Configure(configurator =>
{
// Create the custom help provider
var helpProvider = new CustomHelpProvider(configurator.Settings, "1.0");
// Register the custom help provider instance
registrar.RegisterInstance(typeof(IHelpProvider), helpProvider);
configurator.SetApplicationName("myapp");
configurator.AddCommand<DogCommand>("dog");
});
// When
var result = fixture.Run();
// Then
return Verifier.Verify(result.Output);
}
{
var registrar = new DefaultTypeRegistrar();
// Given
var fixture = new CommandAppTester(registrar);
fixture.Configure(configurator =>
{
// Create the custom help provider
var helpProvider = new CustomHelpProvider(configurator.Settings, "1.0");
// Register the custom help provider instance
registrar.RegisterInstance(typeof(IHelpProvider), helpProvider);
configurator.SetApplicationName("myapp");
configurator.AddCommand<DogCommand>("dog");
});
// When
var result = fixture.Run();
// Then
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("Custom_Help_Registered_By_Type")]
public Task Should_Output_Custom_Help_When_Registered_By_Type()
{
var registrar = new DefaultTypeRegistrar();
// Given
var fixture = new CommandAppTester(registrar);
fixture.Configure(configurator =>
{
// Register the custom help provider type
registrar.Register(typeof(IHelpProvider), typeof(RedirectHelpProvider));
configurator.SetApplicationName("myapp");
configurator.AddCommand<DogCommand>("dog");
});
// When
var result = fixture.Run();
// Then
return Verifier.Verify(result.Output);
}
{
var registrar = new DefaultTypeRegistrar();
// Given
var fixture = new CommandAppTester(registrar);
fixture.Configure(configurator =>
{
// Register the custom help provider type
registrar.Register(typeof(IHelpProvider), typeof(RedirectHelpProvider));
configurator.SetApplicationName("myapp");
configurator.AddCommand<DogCommand>("dog");
});
// When
var result = fixture.Run();
// Then
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("Custom_Help_Configured_By_Instance")]
public Task Should_Output_Custom_Help_When_Configured_By_Instance()
{
var registrar = new DefaultTypeRegistrar();
// Given
var fixture = new CommandAppTester(registrar);
fixture.Configure(configurator =>
{
// Configure the custom help provider instance
configurator.SetHelpProvider(new CustomHelpProvider(configurator.Settings, "1.0"));
configurator.SetApplicationName("myapp");
configurator.AddCommand<DogCommand>("dog");
});
// When
var result = fixture.Run();
// Then
return Verifier.Verify(result.Output);
}
{
var registrar = new DefaultTypeRegistrar();
// Given
var fixture = new CommandAppTester(registrar);
fixture.Configure(configurator =>
{
// Configure the custom help provider instance
configurator.SetHelpProvider(new CustomHelpProvider(configurator.Settings, "1.0"));
configurator.SetApplicationName("myapp");
configurator.AddCommand<DogCommand>("dog");
});
// When
var result = fixture.Run();
// Then
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("Custom_Help_Configured_By_Type")]
public Task Should_Output_Custom_Help_When_Configured_By_Type()
{
var registrar = new DefaultTypeRegistrar();
// Given
var fixture = new CommandAppTester(registrar);
fixture.Configure(configurator =>
{
// Configure the custom help provider type
configurator.SetHelpProvider<RedirectHelpProvider>();
configurator.SetApplicationName("myapp");
configurator.AddCommand<DogCommand>("dog");
});
// When
var result = fixture.Run();
// Then
return Verifier.Verify(result.Output);
}
{
var registrar = new DefaultTypeRegistrar();
// Given
var fixture = new CommandAppTester(registrar);
fixture.Configure(configurator =>
{
// Configure the custom help provider type
configurator.SetHelpProvider<RedirectHelpProvider>();
configurator.SetApplicationName("myapp");
configurator.AddCommand<DogCommand>("dog");
});
// When
var result = fixture.Run();
// Then
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("Root_Examples")]
@ -391,20 +391,20 @@ public sealed partial class CommandAppTests
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
// All root examples should be shown
configurator.AddExample("dog", "--name", "Rufus", "--age", "12", "--good-boy");
configurator.AddExample("dog", "--name", "Luna");
configurator.AddExample("dog", "--name", "Charlie");
configurator.AddExample("dog", "--name", "Bella");
configurator.AddExample("dog", "--name", "Daisy");
// All root examples should be shown
configurator.AddExample("dog", "--name", "Rufus", "--age", "12", "--good-boy");
configurator.AddExample("dog", "--name", "Luna");
configurator.AddExample("dog", "--name", "Charlie");
configurator.AddExample("dog", "--name", "Bella");
configurator.AddExample("dog", "--name", "Daisy");
configurator.AddExample("dog", "--name", "Milo");
configurator.AddExample("horse", "--name", "Brutus");
configurator.AddExample("horse", "--name", "Sugar", "--IsAlive", "false");
configurator.AddExample("horse", "--name", "Cash");
configurator.AddExample("horse", "--name", "Dakota");
configurator.AddExample("horse", "--name", "Cisco");
configurator.AddExample("horse", "--name", "Spirit");
configurator.AddExample("horse", "--name", "Brutus");
configurator.AddExample("horse", "--name", "Sugar", "--IsAlive", "false");
configurator.AddExample("horse", "--name", "Cash");
configurator.AddExample("horse", "--name", "Dakota");
configurator.AddExample("horse", "--name", "Cisco");
configurator.AddExample("horse", "--name", "Spirit");
configurator.AddCommand<DogCommand>("dog");
configurator.AddCommand<HorseCommand>("horse");
@ -415,10 +415,10 @@ public sealed partial class CommandAppTests
// Then
return Verifier.Verify(result.Output);
}
}
[Fact]
[Expectation("Root_Examples_Children")]
[Expectation("Root_Examples_Children")]
[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1512:SingleLineCommentsMustNotBeFollowedByBlankLine", Justification = "Single line comment is relevant to several code blocks that follow.")]
public Task Should_Output_Examples_Defined_On_Direct_Children_If_Root_Has_No_Examples()
{
@ -426,135 +426,24 @@ public sealed partial class CommandAppTests
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
// It should be capped to the first 5 examples by default
configurator.SetApplicationName("myapp");
// It should be capped to the first 5 examples by default
configurator.AddCommand<DogCommand>("dog")
.WithExample("dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("dog", "--name", "Luna")
.WithExample("dog", "--name", "Charlie")
.WithExample("dog", "--name", "Bella")
.WithExample("dog", "--name", "Daisy")
.WithExample("dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("dog", "--name", "Luna")
.WithExample("dog", "--name", "Charlie")
.WithExample("dog", "--name", "Bella")
.WithExample("dog", "--name", "Daisy")
.WithExample("dog", "--name", "Milo");
configurator.AddCommand<HorseCommand>("horse")
.WithExample("horse", "--name", "Brutus")
.WithExample("horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("horse", "--name", "Cash")
.WithExample("horse", "--name", "Dakota")
.WithExample("horse", "--name", "Cisco")
.WithExample("horse", "--name", "Spirit");
});
// When
var result = fixture.Run("--help");
// Then
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("Root_Examples_Children_Eight")]
public Task Should_Output_Eight_Examples_Defined_On_Direct_Children_If_Root_Has_No_Examples()
{
// Given
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
// Show the first 8 examples defined on the direct children
configurator.Settings.MaximumIndirectExamples = 8;
configurator.AddCommand<DogCommand>("dog")
.WithExample("dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("dog", "--name", "Luna")
.WithExample("dog", "--name", "Charlie")
.WithExample("dog", "--name", "Bella")
.WithExample("dog", "--name", "Daisy")
.WithExample("dog", "--name", "Milo");
configurator.AddCommand<HorseCommand>("horse")
.WithExample("horse", "--name", "Brutus")
.WithExample("horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("horse", "--name", "Cash")
.WithExample("horse", "--name", "Dakota")
.WithExample("horse", "--name", "Cisco")
.WithExample("horse", "--name", "Spirit");
});
// When
var result = fixture.Run("--help");
// Then
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("Root_Examples_Children_Twelve")]
public Task Should_Output_All_Examples_Defined_On_Direct_Children_If_Root_Has_No_Examples()
{
// Given
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
// Show all examples defined on the direct children
configurator.Settings.MaximumIndirectExamples = int.MaxValue;
configurator.AddCommand<DogCommand>("dog")
.WithExample("dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("dog", "--name", "Luna")
.WithExample("dog", "--name", "Charlie")
.WithExample("dog", "--name", "Bella")
.WithExample("dog", "--name", "Daisy")
.WithExample("dog", "--name", "Milo");
configurator.AddCommand<HorseCommand>("horse")
.WithExample("horse", "--name", "Brutus")
.WithExample("horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("horse", "--name", "Cash")
.WithExample("horse", "--name", "Dakota")
.WithExample("horse", "--name", "Cisco")
.WithExample("horse", "--name", "Spirit");
});
// When
var result = fixture.Run("--help");
// Then
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("Root_Examples_Children_None")]
public Task Should_Not_Output_Examples_Defined_On_Direct_Children_If_Root_Has_No_Examples()
{
// Given
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
// Do not show examples defined on the direct children
configurator.Settings.MaximumIndirectExamples = 0;
configurator.AddCommand<DogCommand>("dog")
.WithExample("dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("dog", "--name", "Luna")
.WithExample("dog", "--name", "Charlie")
.WithExample("dog", "--name", "Bella")
.WithExample("dog", "--name", "Daisy")
.WithExample("dog", "--name", "Milo");
configurator.AddCommand<HorseCommand>("horse")
.WithExample("horse", "--name", "Brutus")
.WithExample("horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("horse", "--name", "Cash")
.WithExample("horse", "--name", "Dakota")
.WithExample("horse", "--name", "Cisco")
.WithExample("horse", "--name", "Brutus")
.WithExample("horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("horse", "--name", "Cash")
.WithExample("horse", "--name", "Dakota")
.WithExample("horse", "--name", "Cisco")
.WithExample("horse", "--name", "Spirit");
});
@ -566,7 +455,118 @@ public sealed partial class CommandAppTests
}
[Fact]
[Expectation("Root_Examples_Leafs")]
[Expectation("Root_Examples_Children_Eight")]
public Task Should_Output_Eight_Examples_Defined_On_Direct_Children_If_Root_Has_No_Examples()
{
// Given
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
// Show the first 8 examples defined on the direct children
configurator.Settings.MaximumIndirectExamples = 8;
configurator.AddCommand<DogCommand>("dog")
.WithExample("dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("dog", "--name", "Luna")
.WithExample("dog", "--name", "Charlie")
.WithExample("dog", "--name", "Bella")
.WithExample("dog", "--name", "Daisy")
.WithExample("dog", "--name", "Milo");
configurator.AddCommand<HorseCommand>("horse")
.WithExample("horse", "--name", "Brutus")
.WithExample("horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("horse", "--name", "Cash")
.WithExample("horse", "--name", "Dakota")
.WithExample("horse", "--name", "Cisco")
.WithExample("horse", "--name", "Spirit");
});
// When
var result = fixture.Run("--help");
// Then
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("Root_Examples_Children_Twelve")]
public Task Should_Output_All_Examples_Defined_On_Direct_Children_If_Root_Has_No_Examples()
{
// Given
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
// Show all examples defined on the direct children
configurator.Settings.MaximumIndirectExamples = int.MaxValue;
configurator.AddCommand<DogCommand>("dog")
.WithExample("dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("dog", "--name", "Luna")
.WithExample("dog", "--name", "Charlie")
.WithExample("dog", "--name", "Bella")
.WithExample("dog", "--name", "Daisy")
.WithExample("dog", "--name", "Milo");
configurator.AddCommand<HorseCommand>("horse")
.WithExample("horse", "--name", "Brutus")
.WithExample("horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("horse", "--name", "Cash")
.WithExample("horse", "--name", "Dakota")
.WithExample("horse", "--name", "Cisco")
.WithExample("horse", "--name", "Spirit");
});
// When
var result = fixture.Run("--help");
// Then
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("Root_Examples_Children_None")]
public Task Should_Not_Output_Examples_Defined_On_Direct_Children_If_Root_Has_No_Examples()
{
// Given
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
// Do not show examples defined on the direct children
configurator.Settings.MaximumIndirectExamples = 0;
configurator.AddCommand<DogCommand>("dog")
.WithExample("dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("dog", "--name", "Luna")
.WithExample("dog", "--name", "Charlie")
.WithExample("dog", "--name", "Bella")
.WithExample("dog", "--name", "Daisy")
.WithExample("dog", "--name", "Milo");
configurator.AddCommand<HorseCommand>("horse")
.WithExample("horse", "--name", "Brutus")
.WithExample("horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("horse", "--name", "Cash")
.WithExample("horse", "--name", "Dakota")
.WithExample("horse", "--name", "Cisco")
.WithExample("horse", "--name", "Spirit");
});
// When
var result = fixture.Run("--help");
// Then
return Verifier.Verify(result.Output);
}
[Fact]
[Expectation("Root_Examples_Leafs")]
[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1512:SingleLineCommentsMustNotBeFollowedByBlankLine", Justification = "Single line comment is relevant to several code blocks that follow.")]
public Task Should_Output_Examples_Defined_On_Leaves_If_No_Other_Examples_Are_Found()
{
@ -577,24 +577,24 @@ public sealed partial class CommandAppTests
configurator.SetApplicationName("myapp");
configurator.AddBranch<AnimalSettings>("animal", animal =>
{
animal.SetDescription("The animal command.");
// It should be capped to the first 5 examples by default
animal.SetDescription("The animal command.");
// It should be capped to the first 5 examples by default
animal.AddCommand<DogCommand>("dog")
.WithExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("animal", "dog", "--name", "Luna")
.WithExample("animal", "dog", "--name", "Charlie")
.WithExample("animal", "dog", "--name", "Bella")
.WithExample("animal", "dog", "--name", "Daisy")
.WithExample("animal", "dog", "--name", "Milo");
.WithExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("animal", "dog", "--name", "Luna")
.WithExample("animal", "dog", "--name", "Charlie")
.WithExample("animal", "dog", "--name", "Bella")
.WithExample("animal", "dog", "--name", "Daisy")
.WithExample("animal", "dog", "--name", "Milo");
animal.AddCommand<HorseCommand>("horse")
.WithExample("animal", "horse", "--name", "Brutus")
.WithExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("animal", "horse", "--name", "Cash")
.WithExample("animal", "horse", "--name", "Dakota")
.WithExample("animal", "horse", "--name", "Cisco")
.WithExample("animal", "horse", "--name", "Brutus")
.WithExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("animal", "horse", "--name", "Cash")
.WithExample("animal", "horse", "--name", "Dakota")
.WithExample("animal", "horse", "--name", "Cisco")
.WithExample("animal", "horse", "--name", "Spirit");
});
});
@ -604,10 +604,10 @@ public sealed partial class CommandAppTests
// Then
return Verifier.Verify(result.Output);
}
}
[Fact]
[Expectation("Root_Examples_Leafs_Eight")]
[Expectation("Root_Examples_Leafs_Eight")]
public Task Should_Output_Eight_Examples_Defined_On_Leaves_If_No_Other_Examples_Are_Found()
{
// Given
@ -617,25 +617,25 @@ public sealed partial class CommandAppTests
configurator.SetApplicationName("myapp");
configurator.AddBranch<AnimalSettings>("animal", animal =>
{
animal.SetDescription("The animal command.");
// Show the first 8 examples defined on the direct children
configurator.Settings.MaximumIndirectExamples = 8;
animal.SetDescription("The animal command.");
// Show the first 8 examples defined on the direct children
configurator.Settings.MaximumIndirectExamples = 8;
animal.AddCommand<DogCommand>("dog")
.WithExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("animal", "dog", "--name", "Luna")
.WithExample("animal", "dog", "--name", "Charlie")
.WithExample("animal", "dog", "--name", "Bella")
.WithExample("animal", "dog", "--name", "Daisy")
.WithExample("animal", "dog", "--name", "Milo");
.WithExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("animal", "dog", "--name", "Luna")
.WithExample("animal", "dog", "--name", "Charlie")
.WithExample("animal", "dog", "--name", "Bella")
.WithExample("animal", "dog", "--name", "Daisy")
.WithExample("animal", "dog", "--name", "Milo");
animal.AddCommand<HorseCommand>("horse")
.WithExample("animal", "horse", "--name", "Brutus")
.WithExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("animal", "horse", "--name", "Cash")
.WithExample("animal", "horse", "--name", "Dakota")
.WithExample("animal", "horse", "--name", "Cisco")
.WithExample("animal", "horse", "--name", "Brutus")
.WithExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("animal", "horse", "--name", "Cash")
.WithExample("animal", "horse", "--name", "Dakota")
.WithExample("animal", "horse", "--name", "Cisco")
.WithExample("animal", "horse", "--name", "Spirit");
});
});
@ -645,10 +645,10 @@ public sealed partial class CommandAppTests
// Then
return Verifier.Verify(result.Output);
}
}
[Fact]
[Expectation("Root_Examples_Leafs_Twelve")]
[Expectation("Root_Examples_Leafs_Twelve")]
public Task Should_Output_All_Examples_Defined_On_Leaves_If_No_Other_Examples_Are_Found()
{
// Given
@ -658,25 +658,25 @@ public sealed partial class CommandAppTests
configurator.SetApplicationName("myapp");
configurator.AddBranch<AnimalSettings>("animal", animal =>
{
animal.SetDescription("The animal command.");
// Show all examples defined on the direct children
configurator.Settings.MaximumIndirectExamples = int.MaxValue;
animal.SetDescription("The animal command.");
// Show all examples defined on the direct children
configurator.Settings.MaximumIndirectExamples = int.MaxValue;
animal.AddCommand<DogCommand>("dog")
.WithExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("animal", "dog", "--name", "Luna")
.WithExample("animal", "dog", "--name", "Charlie")
.WithExample("animal", "dog", "--name", "Bella")
.WithExample("animal", "dog", "--name", "Daisy")
.WithExample("animal", "dog", "--name", "Milo");
.WithExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("animal", "dog", "--name", "Luna")
.WithExample("animal", "dog", "--name", "Charlie")
.WithExample("animal", "dog", "--name", "Bella")
.WithExample("animal", "dog", "--name", "Daisy")
.WithExample("animal", "dog", "--name", "Milo");
animal.AddCommand<HorseCommand>("horse")
.WithExample("animal", "horse", "--name", "Brutus")
.WithExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("animal", "horse", "--name", "Cash")
.WithExample("animal", "horse", "--name", "Dakota")
.WithExample("animal", "horse", "--name", "Cisco")
.WithExample("animal", "horse", "--name", "Brutus")
.WithExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("animal", "horse", "--name", "Cash")
.WithExample("animal", "horse", "--name", "Dakota")
.WithExample("animal", "horse", "--name", "Cisco")
.WithExample("animal", "horse", "--name", "Spirit");
});
});
@ -686,10 +686,10 @@ public sealed partial class CommandAppTests
// Then
return Verifier.Verify(result.Output);
}
}
[Fact]
[Expectation("Root_Examples_Leafs_None")]
[Expectation("Root_Examples_Leafs_None")]
public Task Should_Not_Output_Examples_Defined_On_Leaves_If_No_Other_Examples_Are_Found()
{
// Given
@ -699,25 +699,25 @@ public sealed partial class CommandAppTests
configurator.SetApplicationName("myapp");
configurator.AddBranch<AnimalSettings>("animal", animal =>
{
animal.SetDescription("The animal command.");
// Do not show examples defined on the direct children
configurator.Settings.MaximumIndirectExamples = 0;
animal.SetDescription("The animal command.");
// Do not show examples defined on the direct children
configurator.Settings.MaximumIndirectExamples = 0;
animal.AddCommand<DogCommand>("dog")
.WithExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("animal", "dog", "--name", "Luna")
.WithExample("animal", "dog", "--name", "Charlie")
.WithExample("animal", "dog", "--name", "Bella")
.WithExample("animal", "dog", "--name", "Daisy")
.WithExample("animal", "dog", "--name", "Milo");
.WithExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy")
.WithExample("animal", "dog", "--name", "Luna")
.WithExample("animal", "dog", "--name", "Charlie")
.WithExample("animal", "dog", "--name", "Bella")
.WithExample("animal", "dog", "--name", "Daisy")
.WithExample("animal", "dog", "--name", "Milo");
animal.AddCommand<HorseCommand>("horse")
.WithExample("animal", "horse", "--name", "Brutus")
.WithExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("animal", "horse", "--name", "Cash")
.WithExample("animal", "horse", "--name", "Dakota")
.WithExample("animal", "horse", "--name", "Cisco")
.WithExample("animal", "horse", "--name", "Brutus")
.WithExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false")
.WithExample("animal", "horse", "--name", "Cash")
.WithExample("animal", "horse", "--name", "Dakota")
.WithExample("animal", "horse", "--name", "Cisco")
.WithExample("animal", "horse", "--name", "Spirit");
});
});
@ -737,23 +737,23 @@ public sealed partial class CommandAppTests
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
configurator.SetApplicationName("myapp");
configurator.AddBranch<AnimalSettings>("animal", animal =>
{
animal.SetDescription("The animal command.");
// All branch examples should be shown
animal.AddExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy");
animal.AddExample("animal", "dog", "--name", "Luna");
animal.AddExample("animal", "dog", "--name", "Charlie");
animal.AddExample("animal", "dog", "--name", "Bella");
animal.AddExample("animal", "dog", "--name", "Daisy");
animal.AddExample("animal", "dog", "--name", "Milo");
animal.AddExample("animal", "horse", "--name", "Brutus");
animal.AddExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false");
animal.AddExample("animal", "horse", "--name", "Cash");
animal.AddExample("animal", "horse", "--name", "Dakota");
animal.AddExample("animal", "horse", "--name", "Cisco");
animal.SetDescription("The animal command.");
// All branch examples should be shown
animal.AddExample("animal", "dog", "--name", "Rufus", "--age", "12", "--good-boy");
animal.AddExample("animal", "dog", "--name", "Luna");
animal.AddExample("animal", "dog", "--name", "Charlie");
animal.AddExample("animal", "dog", "--name", "Bella");
animal.AddExample("animal", "dog", "--name", "Daisy");
animal.AddExample("animal", "dog", "--name", "Milo");
animal.AddExample("animal", "horse", "--name", "Brutus");
animal.AddExample("animal", "horse", "--name", "Sugar", "--IsAlive", "false");
animal.AddExample("animal", "horse", "--name", "Cash");
animal.AddExample("animal", "horse", "--name", "Dakota");
animal.AddExample("animal", "horse", "--name", "Cisco");
animal.AddExample("animal", "horse", "--name", "Spirit");
animal.AddCommand<DogCommand>("dog")
@ -768,7 +768,7 @@ public sealed partial class CommandAppTests
// Then
return Verifier.Verify(result.Output);
}
}
[Fact]
[Expectation("Default_Examples")]
@ -780,13 +780,13 @@ public sealed partial class CommandAppTests
fixture.Configure(configurator =>
{
configurator.SetApplicationName("myapp");
// All root examples should be shown
configurator.AddExample("--name", "Rufus", "--age", "12", "--good-boy");
configurator.AddExample("--name", "Luna");
configurator.AddExample("--name", "Charlie");
configurator.AddExample("--name", "Bella");
configurator.AddExample("--name", "Daisy");
// All root examples should be shown
configurator.AddExample("--name", "Rufus", "--age", "12", "--good-boy");
configurator.AddExample("--name", "Luna");
configurator.AddExample("--name", "Charlie");
configurator.AddExample("--name", "Bella");
configurator.AddExample("--name", "Daisy");
configurator.AddExample("--name", "Milo");
});

View File

@ -352,8 +352,8 @@ public sealed partial class CommandAppTests
var result = app.Run("dog", "-u");
// Then
return Verifier.Verify(result.Output);
}
return Verifier.Verify(result.Output);
}
}
[UsesVerify]
@ -584,7 +584,7 @@ public sealed partial class CommandAppTests
// Then
result.Output.ShouldBe("Error: Command 'dog' is missing required argument 'AGE'.");
}
}
}
}
}

View File

@ -3,16 +3,16 @@ namespace Spectre.Console.Tests.Unit.Cli;
public sealed partial class CommandAppTests
{
public sealed class Remaining
{
[Theory]
[InlineData("-a")]
{
[Theory]
[InlineData("-a")]
[InlineData("--alive")]
public void Should_Not_Add_Known_Flags_To_Remaining_Arguments_RelaxedParsing(string knownFlag)
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
{
config.PropagateExceptions();
config.AddCommand<DogCommand>("dog");
});
@ -20,29 +20,29 @@ public sealed partial class CommandAppTests
// When
var result = app.Run(new[]
{
"dog", "12", "4",
knownFlag,
});
// Then
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
{
dog.IsAlive.ShouldBe(true);
});
"dog", "12", "4",
knownFlag,
});
result.Context.Remaining.Parsed.Count.ShouldBe(0);
// Then
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
{
dog.IsAlive.ShouldBe(true);
});
result.Context.Remaining.Parsed.Count.ShouldBe(0);
result.Context.Remaining.Raw.Count.ShouldBe(0);
}
[Theory]
[InlineData("-r")]
}
[Theory]
[InlineData("-r")]
[InlineData("--romeo")]
public void Should_Add_Unknown_Flags_To_Remaining_Arguments_RelaxedParsing(string unknownFlag)
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
{
config.PropagateExceptions();
config.AddCommand<DogCommand>("dog");
});
@ -50,23 +50,23 @@ public sealed partial class CommandAppTests
// When
var result = app.Run(new[]
{
"dog", "12", "4",
unknownFlag,
});
// Then
result.Context.Remaining.Parsed.Count.ShouldBe(1);
result.Context.ShouldHaveRemainingArgument(unknownFlag.TrimStart('-'), values: new[] { (string)null });
"dog", "12", "4",
unknownFlag,
});
// Then
result.Context.Remaining.Parsed.Count.ShouldBe(1);
result.Context.ShouldHaveRemainingArgument(unknownFlag.TrimStart('-'), values: new[] { (string)null });
result.Context.Remaining.Raw.Count.ShouldBe(0);
}
[Fact]
}
[Fact]
public void Should_Add_Unknown_Flags_When_Grouped_To_Remaining_Arguments_RelaxedParsing()
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
{
config.PropagateExceptions();
config.AddCommand<DogCommand>("dog");
});
@ -74,25 +74,25 @@ public sealed partial class CommandAppTests
// When
var result = app.Run(new[]
{
"dog", "12", "4",
"-agr",
});
// Then
result.Context.Remaining.Parsed.Count.ShouldBe(1);
result.Context.ShouldHaveRemainingArgument("r", values: new[] { (string)null });
"dog", "12", "4",
"-agr",
});
// Then
result.Context.Remaining.Parsed.Count.ShouldBe(1);
result.Context.ShouldHaveRemainingArgument("r", values: new[] { (string)null });
result.Context.Remaining.Raw.Count.ShouldBe(0);
}
[Theory]
[InlineData("-a")]
}
[Theory]
[InlineData("-a")]
[InlineData("--alive")]
public void Should_Not_Add_Known_Flags_To_Remaining_Arguments_StrictParsing(string knownFlag)
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
{
config.UseStrictParsing();
config.PropagateExceptions();
config.AddCommand<DogCommand>("dog");
@ -101,68 +101,68 @@ public sealed partial class CommandAppTests
// When
var result = app.Run(new[]
{
"dog", "12", "4",
knownFlag,
});
// Then
result.Context.Remaining.Parsed.Count.ShouldBe(0);
"dog", "12", "4",
knownFlag,
});
// Then
result.Context.Remaining.Parsed.Count.ShouldBe(0);
result.Context.Remaining.Raw.Count.ShouldBe(0);
}
[Theory]
[InlineData("-r")]
}
[Theory]
[InlineData("-r")]
[InlineData("--romeo")]
public void Should_Not_Add_Unknown_Flags_To_Remaining_Arguments_StrictParsing(string unknownFlag)
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
{
config.UseStrictParsing();
config.PropagateExceptions();
config.AddCommand<DogCommand>("dog");
});
// When
// When
var result = Record.Exception(() => app.Run(new[]
{
"dog", "12", "4",
unknownFlag,
}));
// Then
result.ShouldBeOfType<CommandParseException>().And(ex =>
{
ex.Message.ShouldBe($"Unknown option '{unknownFlag.TrimStart('-')}'.");
"dog", "12", "4",
unknownFlag,
}));
// Then
result.ShouldBeOfType<CommandParseException>().And(ex =>
{
ex.Message.ShouldBe($"Unknown option '{unknownFlag.TrimStart('-')}'.");
});
}
[Fact]
}
[Fact]
public void Should_Not_Add_Unknown_Flags_When_Grouped_To_Remaining_Arguments_StrictParsing()
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
{
config.UseStrictParsing();
config.PropagateExceptions();
config.AddCommand<DogCommand>("dog");
});
// When
// When
var result = Record.Exception(() => app.Run(new[]
{
"dog", "12", "4",
"-agr",
}));
// Then
result.ShouldBeOfType<CommandParseException>().And(ex =>
{
ex.Message.ShouldBe($"Unknown option 'r'.");
"dog", "12", "4",
"-agr",
}));
// Then
result.ShouldBeOfType<CommandParseException>().And(ex =>
{
ex.Message.ShouldBe($"Unknown option 'r'.");
});
}
}
[Fact]
public void Should_Register_Remaining_Parsed_Arguments_With_Context()
@ -254,19 +254,19 @@ public sealed partial class CommandAppTests
result.Context.Remaining.Raw[0].ShouldBe("/c");
result.Context.Remaining.Raw[1].ShouldBe("\"set && pause\"");
result.Context.Remaining.Raw[2].ShouldBe("Name=\" -Rufus --' ");
}
[Theory]
[InlineData(true)]
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Should_Convert_Flags_To_Remaining_Arguments_If_Cannot_Be_Assigned(bool useStrictParsing)
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
config.Settings.ConvertFlagsToRemainingArguments = true;
config.Settings.StrictParsing = useStrictParsing;
{
config.Settings.ConvertFlagsToRemainingArguments = true;
config.Settings.StrictParsing = useStrictParsing;
config.PropagateExceptions();
config.AddCommand<DogCommand>("dog");
});
@ -280,8 +280,8 @@ public sealed partial class CommandAppTests
// Then
result.Context.Remaining.Parsed.Count.ShouldBe(1);
result.Context.ShouldHaveRemainingArgument("good-boy", values: new[] { "Please be good Rufus!" });
result.Context.ShouldHaveRemainingArgument("good-boy", values: new[] { "Please be good Rufus!" });
result.Context.Remaining.Raw.Count.ShouldBe(0); // nb. there are no "raw" remaining arguments on the command line
}
}

View File

@ -15,8 +15,8 @@ public sealed partial class CommandAppTests
// Then
result.Output.ShouldStartWith("Spectre.Cli version ");
}
}
[Fact]
public void Should_Output_Application_Version_To_The_Console_With_No_Command()
{
@ -24,7 +24,7 @@ public sealed partial class CommandAppTests
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationVersion("1.0");
configurator.SetApplicationVersion("1.0");
});
// When
@ -32,8 +32,8 @@ public sealed partial class CommandAppTests
// Then
result.Output.ShouldBe("1.0");
}
}
[Fact]
public void Should_Output_Application_Version_To_The_Console_With_Command()
{
@ -41,8 +41,8 @@ public sealed partial class CommandAppTests
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationVersion("1.0");
configurator.SetApplicationVersion("1.0");
configurator.AddCommand<EmptyCommand>("empty");
});
@ -51,8 +51,8 @@ public sealed partial class CommandAppTests
// Then
result.Output.ShouldBe("1.0");
}
}
[Fact]
public void Should_Output_Application_Version_To_The_Console_With_Default_Command()
{
@ -69,8 +69,8 @@ public sealed partial class CommandAppTests
// Then
result.Output.ShouldBe("1.0");
}
}
[Fact]
public void Should_Output_Application_Version_To_The_Console_With_Branch_Default_Command()
{
@ -78,11 +78,11 @@ public sealed partial class CommandAppTests
var fixture = new CommandAppTester();
fixture.Configure(configurator =>
{
configurator.SetApplicationVersion("1.0");
configurator.AddBranch<EmptyCommandSettings>("branch", branch =>
{
branch.SetDefaultCommand<EmptyCommand>();
configurator.SetApplicationVersion("1.0");
configurator.AddBranch<EmptyCommandSettings>("branch", branch =>
{
branch.SetDefaultCommand<EmptyCommand>();
});
});

View File

@ -1041,66 +1041,66 @@ public sealed partial class CommandAppTests
// Then
result.Context.ShouldNotBeNull();
result.Context.Data.ShouldBe(123);
}
}
public sealed class Default_Command
{
[Fact]
public void Should_Be_Able_To_Set_The_Default_Command()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<DogCommand>();
// When
var result = app.Run(new[]
{
[Fact]
public void Should_Be_Able_To_Set_The_Default_Command()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<DogCommand>();
// When
var result = app.Run(new[]
{
"4", "12", "--good-boy", "--name", "Rufus",
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
{
dog.Legs.ShouldBe(4);
dog.Age.ShouldBe(12);
dog.GoodBoy.ShouldBe(true);
dog.Name.ShouldBe("Rufus");
});
}
[Fact]
public void Should_Set_The_Default_Command_Description_Data_CommandApp()
{
// Given
var app = new CommandApp();
app.SetDefaultCommand<DogCommand>()
.WithDescription("The default command")
.WithData(new string[] { "foo", "bar" });
// When
// Then
app.GetConfigurator().DefaultCommand.ShouldNotBeNull();
app.GetConfigurator().DefaultCommand.Description.ShouldBe("The default command");
app.GetConfigurator().DefaultCommand.Data.ShouldBe(new string[] { "foo", "bar" });
}
[Fact]
public void Should_Set_The_Default_Command_Description_Data_CommandAppOfT()
{
// Given
var app = new CommandApp<DogCommand>()
.WithDescription("The default command")
.WithData(new string[] { "foo", "bar" });
// When
// Then
app.GetConfigurator().DefaultCommand.ShouldNotBeNull();
app.GetConfigurator().DefaultCommand.Description.ShouldBe("The default command");
app.GetConfigurator().DefaultCommand.Data.ShouldBe(new string[] { "foo", "bar" });
}
});
// Then
result.ExitCode.ShouldBe(0);
result.Settings.ShouldBeOfType<DogSettings>().And(dog =>
{
dog.Legs.ShouldBe(4);
dog.Age.ShouldBe(12);
dog.GoodBoy.ShouldBe(true);
dog.Name.ShouldBe("Rufus");
});
}
[Fact]
public void Should_Set_The_Default_Command_Description_Data_CommandApp()
{
// Given
var app = new CommandApp();
app.SetDefaultCommand<DogCommand>()
.WithDescription("The default command")
.WithData(new string[] { "foo", "bar" });
// When
// Then
app.GetConfigurator().DefaultCommand.ShouldNotBeNull();
app.GetConfigurator().DefaultCommand.Description.ShouldBe("The default command");
app.GetConfigurator().DefaultCommand.Data.ShouldBe(new string[] { "foo", "bar" });
}
[Fact]
public void Should_Set_The_Default_Command_Description_Data_CommandAppOfT()
{
// Given
var app = new CommandApp<DogCommand>()
.WithDescription("The default command")
.WithData(new string[] { "foo", "bar" });
// When
// Then
app.GetConfigurator().DefaultCommand.ShouldNotBeNull();
app.GetConfigurator().DefaultCommand.Description.ShouldBe("The default command");
app.GetConfigurator().DefaultCommand.Data.ShouldBe(new string[] { "foo", "bar" });
}
}
public sealed class Delegate_Commands
@ -1114,7 +1114,7 @@ public sealed partial class CommandAppTests
var app = new CommandApp();
app.Configure(config =>
{
{
config.PropagateExceptions();
config.AddDelegate<DogSettings>(
"foo", (context, settings) =>
@ -1134,8 +1134,8 @@ public sealed partial class CommandAppTests
dog.Age.ShouldBe(12);
dog.Legs.ShouldBe(4);
data.ShouldBe(2);
}
}
[Fact]
public async void Should_Execute_Async_Delegate_Command_At_Root_Level()
{
@ -1145,7 +1145,7 @@ public sealed partial class CommandAppTests
var app = new CommandApp();
app.Configure(config =>
{
{
config.PropagateExceptions();
config.AddAsyncDelegate<DogSettings>(
"foo", (context, settings) =>
@ -1199,8 +1199,8 @@ public sealed partial class CommandAppTests
dog.Age.ShouldBe(12);
dog.Legs.ShouldBe(4);
data.ShouldBe(2);
}
}
[Fact]
public async void Should_Execute_Nested_Async_Delegate_Command()
{

View File

@ -1,314 +1,314 @@
namespace Spectre.Console.Tests.Unit.Cli.Parsing;
public class CommandTreeTokenizerTests
{
public sealed class ScanString
{
[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData(" ")]
[InlineData("\t")]
[InlineData("\r\n\t")]
[InlineData("👋🏻")]
[InlineData("🐎👋🏻🔥❤️")]
[InlineData("\"🐎👋🏻🔥❤️\" is an emoji sequence")]
public void Should_Preserve_Edgecase_Inputs(string actualAndExpected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(actualAndExpected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String);
}
[Theory]
// Double-quote handling
[InlineData("\"")]
[InlineData("\"\"")]
[InlineData("\"Rufus\"")]
[InlineData("\" Rufus\"")]
[InlineData("\"-R\"")]
[InlineData("\"-Rufus\"")]
[InlineData("\" -Rufus\"")]
// Single-quote handling
[InlineData("'")]
[InlineData("''")]
[InlineData("'Rufus'")]
[InlineData("' Rufus'")]
[InlineData("'-R'")]
[InlineData("'-Rufus'")]
[InlineData("' -Rufus'")]
public void Should_Preserve_Quotes(string actualAndExpected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(actualAndExpected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String);
}
[Theory]
[InlineData("Rufus-")]
[InlineData("Rufus--")]
[InlineData("R-u-f-u-s")]
public void Should_Preserve_Hyphen_Delimiters(string actualAndExpected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(actualAndExpected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String);
}
[Theory]
[InlineData(" Rufus")]
[InlineData("Rufus ")]
[InlineData(" Rufus ")]
public void Should_Preserve_Spaces(string actualAndExpected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(actualAndExpected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String);
}
[Theory]
[InlineData(" \" -Rufus -- ")]
[InlineData("Name=\" -Rufus --' ")]
public void Should_Preserve_Quotes_Hyphen_Delimiters_Spaces(string actualAndExpected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(actualAndExpected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String);
}
}
public sealed class ScanLongOption
{
[Theory]
[InlineData("--Name-", "Name-")]
[InlineData("--Name_", "Name_")]
public void Should_Allow_Hyphens_And_Underscores_In_Option_Name(string actual, string expected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actual });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(expected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.LongOption);
}
[Theory]
[InlineData("-- ")]
[InlineData("--Name ")]
[InlineData("--Name\"")]
[InlineData("--Nam\"e")]
public void Should_Throw_On_Invalid_Option_Name(string actual)
{
// Given
// When
var result = Record.Exception(() => CommandTreeTokenizer.Tokenize(new string[] { actual }));
// Then
result.ShouldBeOfType<CommandParseException>().And(ex =>
{
ex.Message.ShouldBe("Invalid long option name.");
});
}
}
public sealed class ScanShortOptions
{
[Fact]
public void Should_Accept_Option_Without_Value()
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new[] { "-a" });
// Then
result.Remaining.ShouldBeEmpty();
result.Tokens.ShouldHaveSingleItem();
var t = result.Tokens[0];
t.TokenKind.ShouldBe(CommandTreeToken.Kind.ShortOption);
t.IsGrouped.ShouldBe(false);
t.Position.ShouldBe(0);
t.Value.ShouldBe("a");
t.Representation.ShouldBe("-a");
}
[Theory]
[InlineData("-a:foo")]
[InlineData("-a=foo")]
public void Should_Accept_Option_With_Value(string param)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new[] { param });
// Then
result.Remaining.ShouldBeEmpty();
result.Tokens.Count.ShouldBe(2);
var t = result.Tokens.Consume();
t.TokenKind.ShouldBe(CommandTreeToken.Kind.ShortOption);
t.IsGrouped.ShouldBe(false);
t.Position.ShouldBe(0);
t.Value.ShouldBe("a");
t.Representation.ShouldBe("-a");
t = result.Tokens.Consume();
t.TokenKind.ShouldBe(CommandTreeToken.Kind.String);
t.IsGrouped.ShouldBe(false);
t.Position.ShouldBe(3);
t.Value.ShouldBe("foo");
t.Representation.ShouldBe("foo");
}
[Theory]
// Positive values
[InlineData("-a:1.5", null, "1.5")]
[InlineData("-a=1.5", null, "1.5")]
[InlineData("-a", "1.5", "1.5")]
// Negative values
[InlineData("-a:-1.5", null, "-1.5")]
[InlineData("-a=-1.5", null, "-1.5")]
[InlineData("-a", "-1.5", "-1.5")]
public void Should_Accept_Option_With_Numeric_Value(string firstArg, string secondArg, string expectedValue)
{
// Given
List<string> args = new List<string>();
args.Add(firstArg);
if (secondArg != null)
{
args.Add(secondArg);
}
// When
var result = CommandTreeTokenizer.Tokenize(args);
// Then
result.Remaining.ShouldBeEmpty();
result.Tokens.Count.ShouldBe(2);
var t = result.Tokens.Consume();
t.TokenKind.ShouldBe(CommandTreeToken.Kind.ShortOption);
t.IsGrouped.ShouldBe(false);
t.Position.ShouldBe(0);
t.Value.ShouldBe("a");
t.Representation.ShouldBe("-a");
t = result.Tokens.Consume();
t.TokenKind.ShouldBe(CommandTreeToken.Kind.String);
t.IsGrouped.ShouldBe(false);
t.Position.ShouldBe(3);
t.Value.ShouldBe(expectedValue);
t.Representation.ShouldBe(expectedValue);
}
[Fact]
public void Should_Accept_Option_With_Negative_Numeric_Prefixed_String_Value()
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new[] { "-6..2 " });
// Then
result.Remaining.ShouldBeEmpty();
result.Tokens.ShouldHaveSingleItem();
var t = result.Tokens[0];
t.TokenKind.ShouldBe(CommandTreeToken.Kind.String);
t.IsGrouped.ShouldBe(false);
t.Position.ShouldBe(0);
t.Value.ShouldBe("-6..2");
t.Representation.ShouldBe("-6..2");
}
[Theory]
[InlineData("-N ", "N")]
public void Should_Remove_Trailing_Spaces_In_Option_Name(string actual, string expected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actual });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(expected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.ShortOption);
}
[Theory]
[InlineData("-N-")]
[InlineData("-N\"")]
[InlineData("-a1")]
public void Should_Throw_On_Invalid_Option_Name(string actual)
{
// Given
// When
var result = Record.Exception(() => CommandTreeTokenizer.Tokenize(new string[] { actual }));
// Then
result.ShouldBeOfType<CommandParseException>().And(ex =>
{
ex.Message.ShouldBe("Short option does not have a valid name.");
});
}
}
[Theory]
[InlineData("-")]
[InlineData("- ")]
public void Should_Throw_On_Missing_Option_Name(string actual)
{
// Given
// When
var result = Record.Exception(() => CommandTreeTokenizer.Tokenize(new string[] { actual }));
// Then
result.ShouldBeOfType<CommandParseException>().And(ex =>
{
ex.Message.ShouldBe("Option does not have a name.");
});
}
}
namespace Spectre.Console.Tests.Unit.Cli.Parsing;
public class CommandTreeTokenizerTests
{
public sealed class ScanString
{
[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData(" ")]
[InlineData("\t")]
[InlineData("\r\n\t")]
[InlineData("👋🏻")]
[InlineData("🐎👋🏻🔥❤️")]
[InlineData("\"🐎👋🏻🔥❤️\" is an emoji sequence")]
public void Should_Preserve_Edgecase_Inputs(string actualAndExpected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(actualAndExpected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String);
}
[Theory]
// Double-quote handling
[InlineData("\"")]
[InlineData("\"\"")]
[InlineData("\"Rufus\"")]
[InlineData("\" Rufus\"")]
[InlineData("\"-R\"")]
[InlineData("\"-Rufus\"")]
[InlineData("\" -Rufus\"")]
// Single-quote handling
[InlineData("'")]
[InlineData("''")]
[InlineData("'Rufus'")]
[InlineData("' Rufus'")]
[InlineData("'-R'")]
[InlineData("'-Rufus'")]
[InlineData("' -Rufus'")]
public void Should_Preserve_Quotes(string actualAndExpected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(actualAndExpected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String);
}
[Theory]
[InlineData("Rufus-")]
[InlineData("Rufus--")]
[InlineData("R-u-f-u-s")]
public void Should_Preserve_Hyphen_Delimiters(string actualAndExpected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(actualAndExpected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String);
}
[Theory]
[InlineData(" Rufus")]
[InlineData("Rufus ")]
[InlineData(" Rufus ")]
public void Should_Preserve_Spaces(string actualAndExpected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(actualAndExpected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String);
}
[Theory]
[InlineData(" \" -Rufus -- ")]
[InlineData("Name=\" -Rufus --' ")]
public void Should_Preserve_Quotes_Hyphen_Delimiters_Spaces(string actualAndExpected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actualAndExpected });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(actualAndExpected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.String);
}
}
public sealed class ScanLongOption
{
[Theory]
[InlineData("--Name-", "Name-")]
[InlineData("--Name_", "Name_")]
public void Should_Allow_Hyphens_And_Underscores_In_Option_Name(string actual, string expected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actual });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(expected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.LongOption);
}
[Theory]
[InlineData("-- ")]
[InlineData("--Name ")]
[InlineData("--Name\"")]
[InlineData("--Nam\"e")]
public void Should_Throw_On_Invalid_Option_Name(string actual)
{
// Given
// When
var result = Record.Exception(() => CommandTreeTokenizer.Tokenize(new string[] { actual }));
// Then
result.ShouldBeOfType<CommandParseException>().And(ex =>
{
ex.Message.ShouldBe("Invalid long option name.");
});
}
}
public sealed class ScanShortOptions
{
[Fact]
public void Should_Accept_Option_Without_Value()
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new[] { "-a" });
// Then
result.Remaining.ShouldBeEmpty();
result.Tokens.ShouldHaveSingleItem();
var t = result.Tokens[0];
t.TokenKind.ShouldBe(CommandTreeToken.Kind.ShortOption);
t.IsGrouped.ShouldBe(false);
t.Position.ShouldBe(0);
t.Value.ShouldBe("a");
t.Representation.ShouldBe("-a");
}
[Theory]
[InlineData("-a:foo")]
[InlineData("-a=foo")]
public void Should_Accept_Option_With_Value(string param)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new[] { param });
// Then
result.Remaining.ShouldBeEmpty();
result.Tokens.Count.ShouldBe(2);
var t = result.Tokens.Consume();
t.TokenKind.ShouldBe(CommandTreeToken.Kind.ShortOption);
t.IsGrouped.ShouldBe(false);
t.Position.ShouldBe(0);
t.Value.ShouldBe("a");
t.Representation.ShouldBe("-a");
t = result.Tokens.Consume();
t.TokenKind.ShouldBe(CommandTreeToken.Kind.String);
t.IsGrouped.ShouldBe(false);
t.Position.ShouldBe(3);
t.Value.ShouldBe("foo");
t.Representation.ShouldBe("foo");
}
[Theory]
// Positive values
[InlineData("-a:1.5", null, "1.5")]
[InlineData("-a=1.5", null, "1.5")]
[InlineData("-a", "1.5", "1.5")]
// Negative values
[InlineData("-a:-1.5", null, "-1.5")]
[InlineData("-a=-1.5", null, "-1.5")]
[InlineData("-a", "-1.5", "-1.5")]
public void Should_Accept_Option_With_Numeric_Value(string firstArg, string secondArg, string expectedValue)
{
// Given
List<string> args = new List<string>();
args.Add(firstArg);
if (secondArg != null)
{
args.Add(secondArg);
}
// When
var result = CommandTreeTokenizer.Tokenize(args);
// Then
result.Remaining.ShouldBeEmpty();
result.Tokens.Count.ShouldBe(2);
var t = result.Tokens.Consume();
t.TokenKind.ShouldBe(CommandTreeToken.Kind.ShortOption);
t.IsGrouped.ShouldBe(false);
t.Position.ShouldBe(0);
t.Value.ShouldBe("a");
t.Representation.ShouldBe("-a");
t = result.Tokens.Consume();
t.TokenKind.ShouldBe(CommandTreeToken.Kind.String);
t.IsGrouped.ShouldBe(false);
t.Position.ShouldBe(3);
t.Value.ShouldBe(expectedValue);
t.Representation.ShouldBe(expectedValue);
}
[Fact]
public void Should_Accept_Option_With_Negative_Numeric_Prefixed_String_Value()
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new[] { "-6..2 " });
// Then
result.Remaining.ShouldBeEmpty();
result.Tokens.ShouldHaveSingleItem();
var t = result.Tokens[0];
t.TokenKind.ShouldBe(CommandTreeToken.Kind.String);
t.IsGrouped.ShouldBe(false);
t.Position.ShouldBe(0);
t.Value.ShouldBe("-6..2");
t.Representation.ShouldBe("-6..2");
}
[Theory]
[InlineData("-N ", "N")]
public void Should_Remove_Trailing_Spaces_In_Option_Name(string actual, string expected)
{
// Given
// When
var result = CommandTreeTokenizer.Tokenize(new string[] { actual });
// Then
result.Tokens.Count.ShouldBe(1);
result.Tokens[0].Value.ShouldBe(expected);
result.Tokens[0].TokenKind.ShouldBe(CommandTreeToken.Kind.ShortOption);
}
[Theory]
[InlineData("-N-")]
[InlineData("-N\"")]
[InlineData("-a1")]
public void Should_Throw_On_Invalid_Option_Name(string actual)
{
// Given
// When
var result = Record.Exception(() => CommandTreeTokenizer.Tokenize(new string[] { actual }));
// Then
result.ShouldBeOfType<CommandParseException>().And(ex =>
{
ex.Message.ShouldBe("Short option does not have a valid name.");
});
}
}
[Theory]
[InlineData("-")]
[InlineData("- ")]
public void Should_Throw_On_Missing_Option_Name(string actual)
{
// Given
// When
var result = Record.Exception(() => CommandTreeTokenizer.Tokenize(new string[] { actual }));
// Then
result.ShouldBeOfType<CommandParseException>().And(ex =>
{
ex.Message.ShouldBe("Option does not have a name.");
});
}
}

View File

@ -1,4 +1,4 @@
namespace Spectre.Console.Tests.Unit.Cli.Testing;
namespace Spectre.Console.Tests.Unit.Cli.Testing;
public class FakeTypeRegistrarTests
{

View File

@ -1,20 +1,20 @@
namespace Spectre.Console.Tests.Unit;
public sealed class StyleTests
{
{
[Fact]
public void Should_Convert_From_Color_As_Expected()
{
// Given
Style style;
// When
style = Color.Red;
// Then
style.Foreground.ShouldBe(Color.Red);
}
{
// Given
Style style;
// When
style = Color.Red;
// Then
style.Foreground.ShouldBe(Color.Red);
}
[Fact]
public void Should_Combine_Two_Styles_As_Expected()
{

View File

@ -1,4 +1,4 @@
namespace Spectre.Console.Tests;
namespace Spectre.Console.Tests;
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class GitHubIssueAttribute : Attribute