spectre.console/src/Tests/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Remaining.cs
2025-04-08 16:38:37 +02:00

412 lines
13 KiB
C#

namespace Spectre.Console.Tests.Unit.Cli;
public sealed partial class CommandAppTests
{
public sealed class Remaining
{
[Fact]
public void Should_Add_Unknown_Flags_To_Remaining_Arguments_Default_Command()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<EmptyCommand>();
// When
var result = app.Run("--felix");
// Then
result.Output.ShouldBe(string.Empty);
result.Context.ShouldHaveRemainingArgument("--felix", new[] { (string)null });
}
[Fact]
public void Should_Add_Unknown_Flags_To_Remaining_Arguments_Command()
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
config.AddCommand<EmptyCommand>("empty");
});
// When
var result = app.Run("empty", "--felix");
// Then
result.Output.ShouldBe(string.Empty);
result.Context.ShouldHaveRemainingArgument("--felix", new[] { (string)null });
}
[Fact]
public void Should_Add_Unknown_Flags_To_Remaining_Arguments_Branch_Default_Command()
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
config.AddBranch<EmptyCommandSettings>("branch", branch =>
{
branch.SetDefaultCommand<EmptyCommand>();
});
});
// When
var result = app.Run("branch", "--felix");
// Then
result.Output.ShouldBe(string.Empty);
result.Context.ShouldHaveRemainingArgument("--felix", new[] { (string)null });
}
[Fact]
public void Should_Add_Unknown_Flags_To_Remaining_Arguments_Branch_Command()
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
config.AddBranch<EmptyCommandSettings>("branch", branch =>
{
branch.AddCommand<EmptyCommand>("hello");
});
});
// When
var result = app.Run("branch", "hello", "--felix");
// Then
result.Output.ShouldBe(string.Empty);
result.Context.ShouldHaveRemainingArgument("--felix", new[] { (string)null });
}
[Fact]
public void Should_Add_Unknown_Flags_To_Remaining_Arguments_Branch_Branch_Default_Command()
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
config.AddBranch<EmptyCommandSettings>("branch", branch =>
{
branch.AddBranch<EmptyCommandSettings>("hello", hello =>
{
hello.SetDefaultCommand<EmptyCommand>();
});
});
});
// When
var result = app.Run("branch", "hello", "--felix");
// Then
result.Output.ShouldBe(string.Empty);
result.Context.ShouldHaveRemainingArgument("--felix", new[] { (string)null });
}
[Fact]
public void Should_Add_Unknown_Flags_To_Remaining_Arguments_Branch_Branch_Command()
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
config.AddBranch<EmptyCommandSettings>("branch", branch =>
{
branch.AddBranch<EmptyCommandSettings>("hello", hello =>
{
hello.AddCommand<EmptyCommand>("world");
});
});
});
// When
var result = app.Run("branch", "hello", "world", "--felix");
// Then
result.Output.ShouldBe(string.Empty);
result.Context.ShouldHaveRemainingArgument("--felix", new[] { (string)null });
}
[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");
});
// When
var result = app.Run(new[]
{
"dog", "12", "4",
knownFlag,
});
// 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")]
[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");
});
// When
var result = app.Run(new[]
{
"dog", "12", "4",
unknownFlag,
});
// Then
result.Context.Remaining.Parsed.Count.ShouldBe(1);
result.Context.ShouldHaveRemainingArgument(unknownFlag, values: new[] { (string)null });
result.Context.Remaining.Raw.Count.ShouldBe(0);
}
[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");
});
// 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 });
result.Context.Remaining.Raw.Count.ShouldBe(0);
}
[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");
});
// When
var result = app.Run(new[]
{
"dog", "12", "4",
knownFlag,
});
// Then
result.Context.Remaining.Parsed.Count.ShouldBe(0);
result.Context.Remaining.Raw.Count.ShouldBe(0);
}
[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
var result = Record.Exception(() => app.Run(new[]
{
"dog", "12", "4",
unknownFlag,
}));
// Then
result.ShouldBeOfType<CommandParseException>().And(ex =>
{
ex.Message.ShouldBe($"Unknown option '{unknownFlag.TrimStart('-')}'.");
});
}
[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
var result = Record.Exception(() => app.Run(new[]
{
"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()
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
config.PropagateExceptions();
config.AddBranch<AnimalSettings>("animal", animal =>
{
animal.AddCommand<DogCommand>("dog");
});
});
// When
var result = app.Run(new[]
{
"animal", "4", "dog", "12", "--",
"--foo", "bar", "--foo", "baz",
"-bar", "\"baz\"", "qux",
"foo bar baz qux",
});
// Then
result.Context.Remaining.Parsed.Count.ShouldBe(4);
result.Context.ShouldHaveRemainingArgument("--foo", values: new[] { "bar", "baz" });
result.Context.ShouldHaveRemainingArgument("-b", values: new[] { (string)null });
result.Context.ShouldHaveRemainingArgument("-a", values: new[] { (string)null });
result.Context.ShouldHaveRemainingArgument("-r", values: new[] { (string)null });
}
[Fact]
public void Should_Register_Remaining_Raw_Arguments_With_Context()
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
config.PropagateExceptions();
config.AddBranch<AnimalSettings>("animal", animal =>
{
animal.AddCommand<DogCommand>("dog");
});
});
// When
var result = app.Run(new[]
{
"animal", "4", "dog", "12", "--",
"--foo", "bar", "-bar", "\"baz\"", "qux",
"foo bar baz qux",
});
// Then
result.Context.Remaining.Raw.Count.ShouldBe(6);
result.Context.Remaining.Raw[0].ShouldBe("--foo");
result.Context.Remaining.Raw[1].ShouldBe("bar");
result.Context.Remaining.Raw[2].ShouldBe("-bar");
result.Context.Remaining.Raw[3].ShouldBe("\"baz\"");
result.Context.Remaining.Raw[4].ShouldBe("qux");
result.Context.Remaining.Raw[5].ShouldBe("foo bar baz qux");
}
[Fact]
public void Should_Preserve_Quotes_Hyphen_Delimiters()
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
config.PropagateExceptions();
config.AddBranch<AnimalSettings>("animal", animal =>
{
animal.AddCommand<DogCommand>("dog");
});
});
// When
var result = app.Run(new[]
{
"animal", "4", "dog", "12", "--",
"/c", "\"set && pause\"",
"Name=\" -Rufus --' ",
});
// Then
result.Context.Remaining.Raw.Count.ShouldBe(3);
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)]
[InlineData(false)]
public void Should_Convert_Flags_To_Remaining_Arguments_If_Cannot_Be_Assigned(bool strictParsing)
{
// Given
var app = new CommandAppTester();
app.Configure(config =>
{
config.Settings.ConvertFlagsToRemainingArguments = true;
config.Settings.StrictParsing = strictParsing;
config.PropagateExceptions();
config.AddCommand<DogCommand>("dog");
});
// When
var result = app.Run(new[]
{
"dog", "12", "4",
"--good-boy=Please be good Rufus!",
});
// Then
result.Context.Remaining.Parsed.Count.ShouldBe(1);
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
}
}
}