diff --git a/src/Spectre.Console.Cli/Internal/CommandExecutor.cs b/src/Spectre.Console.Cli/Internal/CommandExecutor.cs index 22eeb2084..dd1a4a0a0 100644 --- a/src/Spectre.Console.Cli/Internal/CommandExecutor.cs +++ b/src/Spectre.Console.Cli/Internal/CommandExecutor.cs @@ -27,24 +27,20 @@ public async Task Execute(IConfiguration configuration, IEnumerable _registrar.RegisterInstance(typeof(CommandModel), model); _registrar.RegisterDependencies(model); - // No default command? - if (model.DefaultCommand == null) + // Got at least one argument? + var firstArgument = arguments.FirstOrDefault(); + if (firstArgument != null) { - // Got at least one argument? - var firstArgument = arguments.FirstOrDefault(); - if (firstArgument != null) + // Asking for version? Kind of a hack, but it's alright. + // We should probably make this a bit better in the future. + if (firstArgument.Equals("--version", StringComparison.OrdinalIgnoreCase) || + firstArgument.Equals("-v", StringComparison.OrdinalIgnoreCase)) { - // Asking for version? Kind of a hack, but it's alright. - // We should probably make this a bit better in the future. - if (firstArgument.Equals("--version", StringComparison.OrdinalIgnoreCase) || - firstArgument.Equals("-v", StringComparison.OrdinalIgnoreCase)) + if (configuration.Settings.ApplicationVersion != null) { - if (configuration.Settings.ApplicationVersion != null) - { - var console = configuration.Settings.Console.GetConsole(); - console.MarkupLine(configuration.Settings.ApplicationVersion); - return 0; - } + var console = configuration.Settings.Console.GetConsole(); + console.MarkupLine(configuration.Settings.ApplicationVersion); + return 0; } } } diff --git a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/VersionSettings.cs b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/VersionSettings.cs index 2b54e8cd2..e84c9e79e 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/VersionSettings.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Data/Settings/VersionSettings.cs @@ -3,5 +3,6 @@ namespace Spectre.Console.Tests.Data; public sealed class VersionSettings : CommandSettings { [CommandOption("-v|--version")] + [Description("The command version")] public string Version { get; set; } } \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.Help.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.Help.cs new file mode 100644 index 000000000..b2cdec014 --- /dev/null +++ b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.Help.cs @@ -0,0 +1,236 @@ +namespace Spectre.Console.Tests.Unit.Cli; + +public sealed partial class CommandAppTests +{ + public sealed partial class Version + { + public sealed class Help + { + [Theory] + [InlineData("-?")] + [InlineData("-h")] + [InlineData("--help")] + public void Help_Should_Include_Application_Version_Flag_With_No_Command(string helpOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + }); + + // When + var result = fixture.Run(helpOption); + + // Then + result.Output.ShouldContain("-v, --version Prints version information"); + } + + [Theory] + [InlineData("-?")] + [InlineData("-h")] + [InlineData("--help")] + public void Help_Should_Not_Include_Application_Version_Flag_If_Not_Specified(string helpOption) + { + // Given + var fixture = new CommandAppTester(); + + // When + var result = fixture.Run(helpOption); + + // Then + result.Output.ShouldNotContain("-v, --version Prints version information"); + } + + [Theory] + [InlineData("-?")] + [InlineData("-h")] + [InlineData("--help")] + public void Help_Should_Include_Application_Version_Flag_For_Default_Command(string helpOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.SetDefaultCommand(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + }); + + // When + var result = fixture.Run(helpOption); + + // Then + result.Output.ShouldContain("-v, --version Prints version information"); + } + + [Theory] + [InlineData("-?")] + [InlineData("-h")] + [InlineData("--help")] + public void Help_Should_Not_Include_Application_Version_Flag_For_Command(string helpOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + configurator.AddCommand("empty"); + }); + + // When + var result = fixture.Run("empty", helpOption); + + // Then + result.Output.ShouldNotContain("-v, --version Prints version information"); + } + + [Theory] + [InlineData("-?")] + [InlineData("-h")] + [InlineData("--help")] + public void Help_Should_Not_Include_Application_Version_Flag_For_Branch_Default_Command(string helpOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + configurator.AddBranch("branch", branch => + { + branch.SetDefaultCommand(); + }); + }); + + // When + var result = fixture.Run("branch", helpOption); + + // Then + result.Output.ShouldNotContain("-v, --version Prints version information"); + } + + [Theory] + [InlineData("-?")] + [InlineData("-h")] + [InlineData("--help")] + public void Help_Should_Not_Include_Application_Version_Flag_For_Branch_Command(string helpOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + configurator.AddBranch("branch", branch => + { + branch.AddCommand("empty"); + }); + }); + + // When + var result = fixture.Run("branch", "empty", helpOption); + + // Then + result.Output.ShouldNotContain("-v, --version Prints version information"); + } + + /// + /// When a command with a version flag in the settings is set as the application default command, + /// then override the in-built Application Version flag with the command version flag instead. + /// Rationale: This behaviour makes the most sense because the other flags for the default command + /// will be shown in the help output and the user can set any of these when executing the application. + /// + [Theory] + [InlineData("-?")] + [InlineData("-h")] + [InlineData("--help")] + public void Help_Should_Include_Command_Version_Flag_For_Default_Command(string helpOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.SetDefaultCommand(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + }); + + // When + var result = fixture.Run(helpOption); + + // Then + result.Output.ShouldContain("-v, --version The command version"); + result.Output.ShouldNotContain("-v, --version Prints version information"); + } + + [Theory] + [InlineData("-?")] + [InlineData("-h")] + [InlineData("--help")] + public void Help_Should_Include_Command_Version_Flag_For_Command(string helpOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + configurator.AddCommand("hello"); + }); + + // When + var result = fixture.Run("hello", helpOption); + + // Then + result.Output.ShouldContain("-v, --version The command version"); + result.Output.ShouldNotContain("-v, --version Prints version information"); + } + + [Theory] + [InlineData("-?")] + [InlineData("-h")] + [InlineData("--help")] + public void Help_Should_Include_Command_Version_Flag_For_Branch_Default_Command(string helpOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + configurator.AddBranch("branch", branch => + { + branch.SetDefaultCommand(); + }); + }); + + // When + var result = fixture.Run("branch", helpOption); + + // Then + result.Output.ShouldContain("-v, --version The command version"); + result.Output.ShouldNotContain("-v, --version Prints version information"); + } + + [Theory] + [InlineData("-?")] + [InlineData("-h")] + [InlineData("--help")] + public void Help_Should_Include_Command_Version_Flag_For_Branch_Command(string helpOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + configurator.AddBranch("branch", branch => + { + branch.AddCommand("hello"); + }); + }); + + // When + var result = fixture.Run("branch", "hello", helpOption); + + // Then + result.Output.ShouldContain("-v, --version The command version"); + result.Output.ShouldNotContain("-v, --version Prints version information"); + } + } + } +} \ No newline at end of file diff --git a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.cs b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.cs index e0a48ee26..d416a89c6 100644 --- a/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.cs +++ b/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Version.cs @@ -2,7 +2,7 @@ namespace Spectre.Console.Tests.Unit.Cli; public sealed partial class CommandAppTests { - public sealed class Version + public sealed partial class Version { [Fact] public void Should_Output_CLI_Version_To_The_Console() @@ -17,8 +17,10 @@ public void Should_Output_CLI_Version_To_The_Console() result.Output.ShouldStartWith("Spectre.Cli version "); } - [Fact] - public void Should_Output_Application_Version_To_The_Console_With_No_Command() + [Theory] + [InlineData("-v")] + [InlineData("--version")] + public void Should_Output_Application_Version_To_The_Console_With_No_Command(string versionOption) { // Given var fixture = new CommandAppTester(); @@ -28,32 +30,52 @@ public void Should_Output_Application_Version_To_The_Console_With_No_Command() }); // When - var result = fixture.Run("--version"); + var result = fixture.Run(versionOption); // Then result.Output.ShouldBe("1.0"); } - [Fact] - public void Should_Not_Display_Version_If_Not_Specified() + [Theory] + [InlineData("-v")] + [InlineData("--version")] + public void Should_Not_Display_Version_If_Not_Specified(string versionOption) { // Given var fixture = new CommandAppTester(); + + // When + var result = fixture.Run(versionOption); + + // Then + result.ExitCode.ShouldNotBe(0); + result.Output.ShouldStartWith($"Error: Unexpected option '{versionOption.Replace("-", "")}'"); + } + + [Theory] + [InlineData("-v")] + [InlineData("--version")] + public void Should_Output_Application_Version_To_The_Console_With_Default_Command(string versionOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.SetDefaultCommand(); fixture.Configure(configurator => { - configurator.AddCommand("empty"); + configurator.SetApplicationVersion("1.0"); }); // When - var result = fixture.Run("--version"); + var result = fixture.Run(versionOption); // Then - result.ExitCode.ShouldNotBe(0); - result.Output.ShouldStartWith("Error: Unexpected option 'version'"); + result.Output.ShouldBe("1.0"); } - [Fact] - public void Should_Execute_Command_Not_Output_Application_Version_To_The_Console() + [Theory] + [InlineData("-v")] + [InlineData("--version")] + public void Should_Execute_Command_Not_Output_Application_Version_To_The_Console(string versionOption) { // Given var fixture = new CommandAppTester(); @@ -64,34 +86,40 @@ public void Should_Execute_Command_Not_Output_Application_Version_To_The_Console }); // When - var result = fixture.Run("empty", "--version"); + var result = fixture.Run("empty", versionOption); // Then result.Output.ShouldBe(string.Empty); - result.Context.ShouldHaveRemainingArgument("--version", new[] { (string)null }); + result.Context.ShouldHaveRemainingArgument(versionOption, new[] { (string)null }); } - [Fact] - public void Should_Execute_Default_Command_Not_Output_Application_Version_To_The_Console() + [Theory] + [InlineData("-v")] + [InlineData("--version")] + public void Should_Output_Application_Version_To_The_Console_With_Branch_Default_Command(string versionOption) { // Given var fixture = new CommandAppTester(); - fixture.SetDefaultCommand(); fixture.Configure(configurator => { configurator.SetApplicationVersion("1.0"); + configurator.AddBranch("branch", branch => + { + branch.SetDefaultCommand(); + }); }); // When - var result = fixture.Run("--version"); + var result = fixture.Run(versionOption); // Then - result.Output.ShouldBe(string.Empty); - result.Context.ShouldHaveRemainingArgument("--version", new[] { (string)null }); + result.Output.ShouldBe("1.0"); } - [Fact] - public void Should_Output_Application_Version_To_The_Console_With_Branch_Default_Command() + [Theory] + [InlineData("-v")] + [InlineData("--version")] + public void Should_Execute_Branch_Default_Command_Not_Output_Application_Version_To_The_Console(string versionOption) { // Given var fixture = new CommandAppTester(); @@ -105,10 +133,125 @@ public void Should_Output_Application_Version_To_The_Console_With_Branch_Default }); // When - var result = fixture.Run("--version"); + var result = fixture.Run("branch", versionOption); // Then - result.Output.ShouldBe("1.0"); + result.Output.ShouldBe(string.Empty); + result.Context.ShouldHaveRemainingArgument(versionOption, new[] { (string)null }); + } + + [Theory] + [InlineData("-v")] + [InlineData("--version")] + public void Should_Execute_Branch_Command_Not_Output_Application_Version_To_The_Console(string versionOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + configurator.AddBranch("branch", branch => + { + branch.AddCommand("empty"); + }); + }); + + // When + var result = fixture.Run("branch", "empty", versionOption); + + // Then + result.Output.ShouldBe(string.Empty); + result.Context.ShouldHaveRemainingArgument(versionOption, new[] { (string)null }); + } + + /// + /// When a command with a version flag in the settings is set as the application default command, + /// then execute this command instead of displaying the explicitly set Application Version. + /// + [Theory] + [InlineData("-v")] + [InlineData("--version")] + public void Should_Execute_Default_VersionCommand_Not_Output_Application_Version_To_The_Console(string versionOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.SetDefaultCommand(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + }); + + // When + var result = fixture.Run(versionOption, "X.Y.Z"); + + // Then + result.Output.ShouldBe("VersionCommand ran, Version: X.Y.Z"); + } + + [Theory] + [InlineData("-v")] + [InlineData("--version")] + public void Should_Execute_VersionCommand_Not_Output_Application_Version_To_The_Console(string versionOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + configurator.AddCommand("hello"); + }); + + // When + var result = fixture.Run("hello", versionOption, "X.Y.Z"); + + // Then + result.Output.ShouldBe("VersionCommand ran, Version: X.Y.Z"); + } + + [Theory] + [InlineData("-v")] + [InlineData("--version")] + public void Should_Execute_Branch_Default_VersionCommand_Not_Output_Application_Version_To_The_Console(string versionOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + configurator.AddBranch("branch", branch => + { + branch.SetDefaultCommand(); + }); + }); + + // When + var result = fixture.Run("branch", versionOption, "X.Y.Z"); + + // Then + result.Output.ShouldBe("VersionCommand ran, Version: X.Y.Z"); + } + + [Theory] + [InlineData("-v")] + [InlineData("--version")] + public void Should_Execute_Branch_VersionCommand_Not_Output_Application_Version_To_The_Console(string versionOption) + { + // Given + var fixture = new CommandAppTester(); + fixture.Configure(configurator => + { + configurator.SetApplicationVersion("1.0"); + configurator.AddBranch("branch", branch => + { + branch.AddCommand("hello"); + }); + }); + + // When + var result = fixture.Run("branch", "hello", versionOption, "X.Y.Z"); + + // Then + result.Output.ShouldBe("VersionCommand ran, Version: X.Y.Z"); } } }