diff --git a/src/Spectre.Console.Cli/Internal/Binding/CommandConstructorBinder.cs b/src/Spectre.Console.Cli/Internal/Binding/CommandConstructorBinder.cs index 7e1e6c8..83c877e 100644 --- a/src/Spectre.Console.Cli/Internal/Binding/CommandConstructorBinder.cs +++ b/src/Spectre.Console.Cli/Internal/Binding/CommandConstructorBinder.cs @@ -45,6 +45,13 @@ internal static class CommandConstructorBinder } } + // Validate the settings. + var validationResult = settings.Validate(); + if (!validationResult.Successful) + { + throw CommandRuntimeException.ValidationFailed(validationResult); + } + return settings; } } \ No newline at end of file diff --git a/test/Spectre.Console.Cli.Tests/Data/Commands/TurtleCommand.cs b/test/Spectre.Console.Cli.Tests/Data/Commands/TurtleCommand.cs new file mode 100644 index 0000000..30159b5 --- /dev/null +++ b/test/Spectre.Console.Cli.Tests/Data/Commands/TurtleCommand.cs @@ -0,0 +1,11 @@ +namespace Spectre.Console.Tests.Data; + +[Description("The turtle command.")] +public class TurtleCommand : AnimalCommand +{ + public override int Execute(CommandContext context, TurtleSettings settings) + { + DumpSettings(context, settings); + return 0; + } +} diff --git a/test/Spectre.Console.Cli.Tests/Data/Settings/ReptileSettings.cs b/test/Spectre.Console.Cli.Tests/Data/Settings/ReptileSettings.cs new file mode 100644 index 0000000..4ec4314 --- /dev/null +++ b/test/Spectre.Console.Cli.Tests/Data/Settings/ReptileSettings.cs @@ -0,0 +1,7 @@ +namespace Spectre.Console.Tests.Data; + +public class ReptileSettings : AnimalSettings +{ + [CommandOption("-n|-p|--name|--pet-name ")] + public string Name { get; set; } +} \ No newline at end of file diff --git a/test/Spectre.Console.Cli.Tests/Data/Settings/TurtleSettings.cs b/test/Spectre.Console.Cli.Tests/Data/Settings/TurtleSettings.cs new file mode 100644 index 0000000..34b99a3 --- /dev/null +++ b/test/Spectre.Console.Cli.Tests/Data/Settings/TurtleSettings.cs @@ -0,0 +1,16 @@ +namespace Spectre.Console.Tests.Data; + +public sealed class TurtleSettings : ReptileSettings +{ + public TurtleSettings(string name) + { + Name = name; + } + + public override ValidationResult Validate() + { + return Name != "Lonely George" + ? ValidationResult.Error("Only 'Lonely George' is valid name for a turtle!") + : ValidationResult.Success(); + } +} diff --git a/test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Validation.cs b/test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Validation.cs index f4b0b7f..06eac92 100644 --- a/test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Validation.cs +++ b/test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Validation.cs @@ -54,6 +54,30 @@ public sealed partial class CommandAppTests }); } + [Fact] + public void Should_Throw_If_Settings_Validation_Fails_On_Settings_With_ctor() + { + // Given + var app = new CommandApp(); + app.Configure(config => + { + config.PropagateExceptions(); + config.AddBranch("animal", animal => + { + animal.AddCommand("turtle"); + }); + }); + + // When + var result = Record.Exception(() => app.Run(new[] { "animal", "4", "turtle", "--name", "Klaus" })); + + // Then + result.ShouldBeOfType().And(e => + { + e.Message.ShouldBe("Only 'Lonely George' is valid name for a turtle!"); + }); + } + [Fact] public void Should_Throw_If_Command_Validation_Fails() {