diff --git a/src/Spectre.Console.Cli/ConfiguratorExtensions.cs b/src/Spectre.Console.Cli/ConfiguratorExtensions.cs index e4a234fc1..467930203 100644 --- a/src/Spectre.Console.Cli/ConfiguratorExtensions.cs +++ b/src/Spectre.Console.Cli/ConfiguratorExtensions.cs @@ -88,12 +88,12 @@ public static IConfigurator UseStrictParsing(this IConfigurator configurator) configurator.Settings.StrictParsing = true; return configurator; - } - + } + /// /// Tells the help writer whether or not to trim trailing period. /// - /// The configurator. + /// The configurator. /// True to trim trailing period (default), false to not. /// A configurator that can be used to configure the application further. public static IConfigurator TrimTrailingPeriods(this IConfigurator configurator, bool trimTrailingPeriods) @@ -181,7 +181,8 @@ public static IConfigurator SetInterceptor(this IConfigurator configurator, ICom /// The configurator. /// The name of the command branch. /// The command branch configuration. - public static void AddBranch( + /// A branch configurator that can be used to configure the branch further. + public static IBranchConfigurator AddBranch( this IConfigurator configurator, string name, Action> action) @@ -191,7 +192,7 @@ public static void AddBranch( throw new ArgumentNullException(nameof(configurator)); } - configurator.AddBranch(name, action); + return configurator.AddBranch(name, action); } /// @@ -201,7 +202,8 @@ public static void AddBranch( /// The configurator. /// The name of the command branch. /// The command branch configuration. - public static void AddBranch( + /// A branch configurator that can be used to configure the branch further. + public static IBranchConfigurator AddBranch( this IConfigurator configurator, string name, Action> action) @@ -212,7 +214,7 @@ public static void AddBranch( throw new ArgumentNullException(nameof(configurator)); } - configurator.AddBranch(name, action); + return configurator.AddBranch(name, action); } /// diff --git a/src/Spectre.Console.Cli/IBranchConfigurator.cs b/src/Spectre.Console.Cli/IBranchConfigurator.cs new file mode 100644 index 000000000..2b8a44bdf --- /dev/null +++ b/src/Spectre.Console.Cli/IBranchConfigurator.cs @@ -0,0 +1,14 @@ +namespace Spectre.Console.Cli; + +/// +/// Represents a branch configurator. +/// +public interface IBranchConfigurator +{ + /// + /// Adds an alias (an alternative name) to the branch being configured. + /// + /// The alias to add to the branch being configured. + /// The same instance so that multiple calls can be chained. + IBranchConfigurator WithAlias(string name); +} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/IConfigurator.cs b/src/Spectre.Console.Cli/IConfigurator.cs index 565a4f322..f6108b654 100644 --- a/src/Spectre.Console.Cli/IConfigurator.cs +++ b/src/Spectre.Console.Cli/IConfigurator.cs @@ -41,6 +41,7 @@ ICommandConfigurator AddDelegate(string name, FuncThe command setting type. /// The name of the command branch. /// The command branch configurator. - void AddBranch(string name, Action> action) + /// A branch configurator that can be used to configure the branch further. + IBranchConfigurator AddBranch(string name, Action> action) where TSettings : CommandSettings; } \ No newline at end of file diff --git a/src/Spectre.Console.Cli/IConfiguratorOfT.cs b/src/Spectre.Console.Cli/IConfiguratorOfT.cs index 7852aafce..1dabf0c38 100644 --- a/src/Spectre.Console.Cli/IConfiguratorOfT.cs +++ b/src/Spectre.Console.Cli/IConfiguratorOfT.cs @@ -51,6 +51,7 @@ ICommandConfigurator AddDelegate(string name, FuncThe derived command setting type. /// The name of the command branch. /// The command branch configuration. - void AddBranch(string name, Action> action) + /// A branch configurator that can be used to configure the branch further. + IBranchConfigurator AddBranch(string name, Action> action) where TDerivedSettings : TSettings; } \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/BranchConfigurator.cs b/src/Spectre.Console.Cli/Internal/Configuration/BranchConfigurator.cs new file mode 100644 index 000000000..ba26f088c --- /dev/null +++ b/src/Spectre.Console.Cli/Internal/Configuration/BranchConfigurator.cs @@ -0,0 +1,17 @@ +namespace Spectre.Console.Cli; + +internal sealed class BranchConfigurator : IBranchConfigurator +{ + public ConfiguredCommand Command { get; } + + public BranchConfigurator(ConfiguredCommand command) + { + Command = command; + } + + public IBranchConfigurator WithAlias(string alias) + { + Command.Aliases.Add(alias); + return this; + } +} \ No newline at end of file diff --git a/src/Spectre.Console.Cli/Internal/Configuration/Configurator.cs b/src/Spectre.Console.Cli/Internal/Configuration/Configurator.cs index cd1b42d77..e4e503633 100644 --- a/src/Spectre.Console.Cli/Internal/Configuration/Configurator.cs +++ b/src/Spectre.Console.Cli/Internal/Configuration/Configurator.cs @@ -48,12 +48,13 @@ public ICommandConfigurator AddDelegate(string name, Func(string name, Action> action) + public IBranchConfigurator AddBranch(string name, Action> action) where TSettings : CommandSettings { var command = ConfiguredCommand.FromBranch(name); action(new Configurator(command, _registrar)); - Commands.Add(command); + var added = Commands.AddAndReturn(command); + return new BranchConfigurator(added); } ICommandConfigurator IUnsafeConfigurator.AddCommand(string name, Type command) @@ -74,7 +75,7 @@ ICommandConfigurator IUnsafeConfigurator.AddCommand(string name, Type command) return result; } - void IUnsafeConfigurator.AddBranch(string name, Type settings, Action action) + IBranchConfigurator IUnsafeConfigurator.AddBranch(string name, Type settings, Action action) { var command = ConfiguredCommand.FromBranch(settings, name); @@ -86,6 +87,7 @@ void IUnsafeConfigurator.AddBranch(string name, Type settings, Action(string name, Func(string name, Action> action) + public IBranchConfigurator AddBranch(string name, Action> action) where TDerivedSettings : TSettings { var command = ConfiguredCommand.FromBranch(name); action(new Configurator(command, _registrar)); - _command.Children.Add(command); + var added = _command.Children.AddAndReturn(command); + return new BranchConfigurator(added); } ICommandConfigurator IUnsafeConfigurator.AddCommand(string name, Type command) @@ -73,7 +74,7 @@ ICommandConfigurator IUnsafeConfigurator.AddCommand(string name, Type command) return result; } - void IUnsafeConfigurator.AddBranch(string name, Type settings, Action action) + IBranchConfigurator IUnsafeConfigurator.AddBranch(string name, Type settings, Action action) { var command = ConfiguredCommand.FromBranch(settings, name); @@ -85,6 +86,7 @@ void IUnsafeConfigurator.AddBranch(string name, Type settings, ActionThe name of the command branch. /// The command setting type. /// The command branch configurator. - void AddBranch(string name, Type settings, Action action); + /// A branch configurator that can be used to configure the branch further. + IBranchConfigurator AddBranch(string name, Type settings, Action action); } \ No newline at end of file diff --git a/test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.cs b/test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.cs index 2f69a6bf9..65c152517 100644 --- a/test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.cs +++ b/test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.cs @@ -132,8 +132,8 @@ public void Should_Pass_Case_4() dog.IsAlive.ShouldBe(false); dog.Name.ShouldBe("Rufus"); }); - } - + } + [Fact] public void Should_Pass_Case_5() { @@ -165,7 +165,7 @@ public void Should_Pass_Case_5() dog.IsAlive.ShouldBe(true); dog.Name.ShouldBe("Rufus"); }); - } + } [Fact] public void Should_Pass_Case_6() @@ -237,10 +237,10 @@ public void Should_Preserve_Quotes_Hyphen_Delimiters_Spaces() var result = app.Run(new[] { "dog", "12", "4", - "--name=\" -Rufus --' ", - "--", - "--order-by", "\"-size\"", - "--order-by", " ", + "--name=\" -Rufus --' ", + "--", + "--order-by", "\"-size\"", + "--order-by", " ", "--order-by", string.Empty, }); @@ -249,8 +249,8 @@ public void Should_Preserve_Quotes_Hyphen_Delimiters_Spaces() result.Settings.ShouldBeOfType().And(dog => { dog.Name.ShouldBe("\" -Rufus --' "); - }); - result.Context.Remaining.Parsed.Count.ShouldBe(1); + }); + result.Context.Remaining.Parsed.Count.ShouldBe(1); result.Context.ShouldHaveRemainingArgument("order-by", values: new[] { "\"-size\"", " ", string.Empty }); } @@ -280,6 +280,65 @@ public void Should_Be_Able_To_Use_Command_Alias() }); } + [Fact] + public void Should_Be_Able_To_Use_Branch_Alias() + { + // Given + var app = new CommandAppTester(); + app.Configure(config => + { + config.PropagateExceptions(); + config.AddBranch("animal", animal => + { + animal.AddCommand("dog"); + animal.AddCommand("horse"); + }).WithAlias("a"); + }); + + // When + var result = app.Run(new[] + { + "a", "dog", "12", "--good-boy", + "--name", "Rufus", + }); + + // Then + result.ExitCode.ShouldBe(0); + result.Settings.ShouldBeOfType().And(dog => + { + dog.Age.ShouldBe(12); + dog.GoodBoy.ShouldBe(true); + dog.Name.ShouldBe("Rufus"); + dog.IsAlive.ShouldBe(false); + }); + } + + [Fact] + public void Should_Throw_If_Branch_Alias_Conflicts_With_Another_Command() + { + // Given + var app = new CommandApp(); + app.Configure(config => + { + config.PropagateExceptions(); + config.AddCommand("a"); + config.AddBranch("animal", animal => + { + animal.AddCommand("dog"); + animal.AddCommand("horse"); + }).WithAlias("a"); + }); + + // When + var result = Record.Exception(() => app.Run(new[] { "a", "0", "12" })); + + // Then + result.ShouldBeOfType().And(ex => + { + ex.Message.ShouldBe("The alias 'a' for 'animal' conflicts with another command."); + }); + } + [Fact] public void Should_Assign_Default_Value_To_Optional_Argument() { @@ -554,181 +613,181 @@ public void Should_Accept_Explicit_Boolan_Flag(string value, bool expected) { dog.IsAlive.ShouldBe(expected); }); - } - - [Fact] - public void Should_Set_Short_Option_Before_Argument() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] { "dog", "-a", "-n=Rufus", "4", "12", }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { - settings.IsAlive.ShouldBeTrue(); - settings.Name.ShouldBe("Rufus"); - settings.Legs.ShouldBe(4); - settings.Age.ShouldBe(12); - }); - } - + } + + [Fact] + public void Should_Set_Short_Option_Before_Argument() + { + // Given + var app = new CommandAppTester(); + app.Configure(config => + { + config.PropagateExceptions(); + config.AddCommand("dog"); + }); + + // When + var result = app.Run(new[] { "dog", "-a", "-n=Rufus", "4", "12", }); + + // Then + result.ExitCode.ShouldBe(0); + result.Settings.ShouldBeOfType().And(settings => + { + settings.IsAlive.ShouldBeTrue(); + settings.Name.ShouldBe("Rufus"); + settings.Legs.ShouldBe(4); + settings.Age.ShouldBe(12); + }); + } + [Theory] [InlineData("true", true)] [InlineData("True", true)] [InlineData("false", false)] - [InlineData("False", false)] - public void Should_Set_Short_Option_With_Explicit_Boolan_Flag_Before_Argument(string value, bool expected) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] { "dog", "-a", value, "4", "12", }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { - settings.IsAlive.ShouldBe(expected); - settings.Legs.ShouldBe(4); - settings.Age.ShouldBe(12); - }); - } - - [Fact] - public void Should_Set_Long_Option_Before_Argument() - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] { "dog", "--alive", "--name=Rufus", "4", "12" }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { - settings.IsAlive.ShouldBeTrue(); - settings.Name.ShouldBe("Rufus"); - settings.Legs.ShouldBe(4); - settings.Age.ShouldBe(12); - }); - } - + [InlineData("False", false)] + public void Should_Set_Short_Option_With_Explicit_Boolan_Flag_Before_Argument(string value, bool expected) + { + // Given + var app = new CommandAppTester(); + app.Configure(config => + { + config.PropagateExceptions(); + config.AddCommand("dog"); + }); + + // When + var result = app.Run(new[] { "dog", "-a", value, "4", "12", }); + + // Then + result.ExitCode.ShouldBe(0); + result.Settings.ShouldBeOfType().And(settings => + { + settings.IsAlive.ShouldBe(expected); + settings.Legs.ShouldBe(4); + settings.Age.ShouldBe(12); + }); + } + + [Fact] + public void Should_Set_Long_Option_Before_Argument() + { + // Given + var app = new CommandAppTester(); + app.Configure(config => + { + config.PropagateExceptions(); + config.AddCommand("dog"); + }); + + // When + var result = app.Run(new[] { "dog", "--alive", "--name=Rufus", "4", "12" }); + + // Then + result.ExitCode.ShouldBe(0); + result.Settings.ShouldBeOfType().And(settings => + { + settings.IsAlive.ShouldBeTrue(); + settings.Name.ShouldBe("Rufus"); + settings.Legs.ShouldBe(4); + settings.Age.ShouldBe(12); + }); + } + [Theory] [InlineData("true", true)] [InlineData("True", true)] [InlineData("false", false)] - [InlineData("False", false)] - public void Should_Set_Long_Option_With_Explicit_Boolan_Flag_Before_Argument(string value, bool expected) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(new[] { "dog", "--alive", value, "4", "12", }); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { - settings.IsAlive.ShouldBe(expected); - settings.Legs.ShouldBe(4); - settings.Age.ShouldBe(12); - }); - } - - [Theory] - + [InlineData("False", false)] + public void Should_Set_Long_Option_With_Explicit_Boolan_Flag_Before_Argument(string value, bool expected) + { + // Given + var app = new CommandAppTester(); + app.Configure(config => + { + config.PropagateExceptions(); + config.AddCommand("dog"); + }); + + // When + var result = app.Run(new[] { "dog", "--alive", value, "4", "12", }); + + // Then + result.ExitCode.ShouldBe(0); + result.Settings.ShouldBeOfType().And(settings => + { + settings.IsAlive.ShouldBe(expected); + settings.Legs.ShouldBe(4); + settings.Age.ShouldBe(12); + }); + } + + [Theory] + // Long options - [InlineData("dog --alive 4 12 --name Rufus", 4, 12, false, true, "Rufus")] - [InlineData("dog --alive=true 4 12 --name Rufus", 4, 12, false, true, "Rufus")] - [InlineData("dog --alive:true 4 12 --name Rufus", 4, 12, false, true, "Rufus")] - [InlineData("dog --alive --good-boy 4 12 --name Rufus", 4, 12, true, true, "Rufus")] - [InlineData("dog --alive=true --good-boy=true 4 12 --name Rufus", 4, 12, true, true, "Rufus")] - [InlineData("dog --alive:true --good-boy:true 4 12 --name Rufus", 4, 12, true, true, "Rufus")] - [InlineData("dog --alive --good-boy --name Rufus 4 12", 4, 12, true, true, "Rufus")] - [InlineData("dog --alive=true --good-boy=true --name Rufus 4 12", 4, 12, true, true, "Rufus")] - [InlineData("dog --alive:true --good-boy:true --name Rufus 4 12", 4, 12, true, true, "Rufus")] - - // Short options - [InlineData("dog -a 4 12 --name Rufus", 4, 12, false, true, "Rufus")] - [InlineData("dog -a=true 4 12 --name Rufus", 4, 12, false, true, "Rufus")] - [InlineData("dog -a:true 4 12 --name Rufus", 4, 12, false, true, "Rufus")] - [InlineData("dog -a --good-boy 4 12 --name Rufus", 4, 12, true, true, "Rufus")] - [InlineData("dog -a=true -g=true 4 12 --name Rufus", 4, 12, true, true, "Rufus")] - [InlineData("dog -a:true -g:true 4 12 --name Rufus", 4, 12, true, true, "Rufus")] - [InlineData("dog -a -g --name Rufus 4 12", 4, 12, true, true, "Rufus")] - [InlineData("dog -a=true -g=true --name Rufus 4 12", 4, 12, true, true, "Rufus")] - [InlineData("dog -a:true -g:true --name Rufus 4 12", 4, 12, true, true, "Rufus")] - - // Switch around ordering of the options - [InlineData("dog --good-boy:true --name Rufus --alive:true 4 12", 4, 12, true, true, "Rufus")] - [InlineData("dog --name Rufus --alive:true --good-boy:true 4 12", 4, 12, true, true, "Rufus")] - [InlineData("dog --name Rufus --good-boy:true --alive:true 4 12", 4, 12, true, true, "Rufus")] - - // Inject the command arguments in between the options - [InlineData("dog 4 12 --good-boy:true --name Rufus --alive:true", 4, 12, true, true, "Rufus")] - [InlineData("dog 4 --good-boy:true 12 --name Rufus --alive:true", 4, 12, true, true, "Rufus")] - [InlineData("dog --good-boy:true 4 12 --name Rufus --alive:true", 4, 12, true, true, "Rufus")] - [InlineData("dog --good-boy:true 4 --name Rufus 12 --alive:true", 4, 12, true, true, "Rufus")] - [InlineData("dog --name Rufus --alive:true 4 12 --good-boy:true", 4, 12, true, true, "Rufus")] - [InlineData("dog --name Rufus --alive:true 4 --good-boy:true 12", 4, 12, true, true, "Rufus")] - - // Inject the command arguments in between the options (all flag values set to false) - [InlineData("dog 4 12 --good-boy:false --name Rufus --alive:false", 4, 12, false, false, "Rufus")] - [InlineData("dog 4 --good-boy:false 12 --name Rufus --alive:false", 4, 12, false, false, "Rufus")] - [InlineData("dog --good-boy:false 4 12 --name Rufus --alive:false", 4, 12, false, false, "Rufus")] - [InlineData("dog --good-boy:false 4 --name Rufus 12 --alive:false", 4, 12, false, false, "Rufus")] - [InlineData("dog --name Rufus --alive:false 4 12 --good-boy:false", 4, 12, false, false, "Rufus")] - [InlineData("dog --name Rufus --alive:false 4 --good-boy:false 12", 4, 12, false, false, "Rufus")] - public void Should_Set_Option_Before_Argument(string arguments, int legs, int age, bool goodBoy, bool isAlive, string name) - { - // Given - var app = new CommandAppTester(); - app.Configure(config => - { - config.PropagateExceptions(); - config.AddCommand("dog"); - }); - - // When - var result = app.Run(arguments.Split(' ')); - - // Then - result.ExitCode.ShouldBe(0); - result.Settings.ShouldBeOfType().And(settings => - { + [InlineData("dog --alive 4 12 --name Rufus", 4, 12, false, true, "Rufus")] + [InlineData("dog --alive=true 4 12 --name Rufus", 4, 12, false, true, "Rufus")] + [InlineData("dog --alive:true 4 12 --name Rufus", 4, 12, false, true, "Rufus")] + [InlineData("dog --alive --good-boy 4 12 --name Rufus", 4, 12, true, true, "Rufus")] + [InlineData("dog --alive=true --good-boy=true 4 12 --name Rufus", 4, 12, true, true, "Rufus")] + [InlineData("dog --alive:true --good-boy:true 4 12 --name Rufus", 4, 12, true, true, "Rufus")] + [InlineData("dog --alive --good-boy --name Rufus 4 12", 4, 12, true, true, "Rufus")] + [InlineData("dog --alive=true --good-boy=true --name Rufus 4 12", 4, 12, true, true, "Rufus")] + [InlineData("dog --alive:true --good-boy:true --name Rufus 4 12", 4, 12, true, true, "Rufus")] + + // Short options + [InlineData("dog -a 4 12 --name Rufus", 4, 12, false, true, "Rufus")] + [InlineData("dog -a=true 4 12 --name Rufus", 4, 12, false, true, "Rufus")] + [InlineData("dog -a:true 4 12 --name Rufus", 4, 12, false, true, "Rufus")] + [InlineData("dog -a --good-boy 4 12 --name Rufus", 4, 12, true, true, "Rufus")] + [InlineData("dog -a=true -g=true 4 12 --name Rufus", 4, 12, true, true, "Rufus")] + [InlineData("dog -a:true -g:true 4 12 --name Rufus", 4, 12, true, true, "Rufus")] + [InlineData("dog -a -g --name Rufus 4 12", 4, 12, true, true, "Rufus")] + [InlineData("dog -a=true -g=true --name Rufus 4 12", 4, 12, true, true, "Rufus")] + [InlineData("dog -a:true -g:true --name Rufus 4 12", 4, 12, true, true, "Rufus")] + + // Switch around ordering of the options + [InlineData("dog --good-boy:true --name Rufus --alive:true 4 12", 4, 12, true, true, "Rufus")] + [InlineData("dog --name Rufus --alive:true --good-boy:true 4 12", 4, 12, true, true, "Rufus")] + [InlineData("dog --name Rufus --good-boy:true --alive:true 4 12", 4, 12, true, true, "Rufus")] + + // Inject the command arguments in between the options + [InlineData("dog 4 12 --good-boy:true --name Rufus --alive:true", 4, 12, true, true, "Rufus")] + [InlineData("dog 4 --good-boy:true 12 --name Rufus --alive:true", 4, 12, true, true, "Rufus")] + [InlineData("dog --good-boy:true 4 12 --name Rufus --alive:true", 4, 12, true, true, "Rufus")] + [InlineData("dog --good-boy:true 4 --name Rufus 12 --alive:true", 4, 12, true, true, "Rufus")] + [InlineData("dog --name Rufus --alive:true 4 12 --good-boy:true", 4, 12, true, true, "Rufus")] + [InlineData("dog --name Rufus --alive:true 4 --good-boy:true 12", 4, 12, true, true, "Rufus")] + + // Inject the command arguments in between the options (all flag values set to false) + [InlineData("dog 4 12 --good-boy:false --name Rufus --alive:false", 4, 12, false, false, "Rufus")] + [InlineData("dog 4 --good-boy:false 12 --name Rufus --alive:false", 4, 12, false, false, "Rufus")] + [InlineData("dog --good-boy:false 4 12 --name Rufus --alive:false", 4, 12, false, false, "Rufus")] + [InlineData("dog --good-boy:false 4 --name Rufus 12 --alive:false", 4, 12, false, false, "Rufus")] + [InlineData("dog --name Rufus --alive:false 4 12 --good-boy:false", 4, 12, false, false, "Rufus")] + [InlineData("dog --name Rufus --alive:false 4 --good-boy:false 12", 4, 12, false, false, "Rufus")] + public void Should_Set_Option_Before_Argument(string arguments, int legs, int age, bool goodBoy, bool isAlive, string name) + { + // Given + var app = new CommandAppTester(); + app.Configure(config => + { + config.PropagateExceptions(); + config.AddCommand("dog"); + }); + + // When + var result = app.Run(arguments.Split(' ')); + + // Then + result.ExitCode.ShouldBe(0); + result.Settings.ShouldBeOfType().And(settings => + { settings.Legs.ShouldBe(legs); settings.Age.ShouldBe(age); settings.GoodBoy.ShouldBe(goodBoy); settings.IsAlive.ShouldBe(isAlive); - settings.Name.ShouldBe(name); - }); + settings.Name.ShouldBe(name); + }); } [Fact]