fix: complete retail parity stability pass
This commit is contained in:
parent
d3df4cb20a
commit
f7aa8e0eb7
131 changed files with 7765 additions and 1190 deletions
|
|
@ -71,6 +71,10 @@ public sealed class RetailClientCommandCatalogTests
|
|||
[InlineData("/unfilter -combat", ClientCommandId.Unfilter)]
|
||||
[InlineData("/messagetypes", ClientCommandId.ListMessageTypes)]
|
||||
[InlineData("/fillcomps scarabs 500", ClientCommandId.FillComponents)]
|
||||
[InlineData("/day", ClientCommandId.TogglePersistentDaylight)]
|
||||
[InlineData("@day ignored", ClientCommandId.TogglePersistentDaylight)]
|
||||
[InlineData("/render radius 12", ClientCommandId.RenderOption)]
|
||||
[InlineData("@render usage", ClientCommandId.RenderOption)]
|
||||
public void CommandFamilies_ResolveToTypedClientCommands(
|
||||
string input, ClientCommandId expected)
|
||||
{
|
||||
|
|
@ -91,18 +95,46 @@ public sealed class RetailClientCommandCatalogTests
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("/house open")]
|
||||
[InlineData("/house close")]
|
||||
[InlineData("/house guest add Bob")]
|
||||
[InlineData("/house storage add Bob")]
|
||||
[InlineData("/house nope")]
|
||||
[InlineData("/house available")]
|
||||
public void UnsupportedHouseSubcommand_FallsThroughToServerPassthrough(string input)
|
||||
[InlineData("/house open", ClientCommandId.HouseOpenStatus, "open")]
|
||||
[InlineData("/house close ignored", ClientCommandId.HouseOpenStatus, "close")]
|
||||
[InlineData("/house guest add Bob", ClientCommandId.HouseGuests, "add Bob")]
|
||||
[InlineData("/house storage add Lord Bob", ClientCommandId.HouseStorage, "add Lord Bob")]
|
||||
[InlineData("/house remove Bob", ClientCommandId.HouseBoot, "Bob")]
|
||||
[InlineData("/house boot -all", ClientCommandId.HouseBoot, "-all")]
|
||||
[InlineData("/house boot_all ignored", ClientCommandId.HouseBootAll, "ignored")]
|
||||
[InlineData("/house remove_all", ClientCommandId.HouseBootAll, "")]
|
||||
[InlineData("/house available Cottage", ClientCommandId.HouseAvailableList, "Cottage")]
|
||||
[InlineData("/house hooks off", ClientCommandId.HouseHooks, "off")]
|
||||
public void HouseManagementSubcommands_ResolveLocally(
|
||||
string input,
|
||||
ClientCommandId expected,
|
||||
string expectedArguments)
|
||||
{
|
||||
// Campaign CH slice CH4 (2026-08-09), Tier 1 fix #4: unrecognized
|
||||
// house subcommands must reach ACE (TS-68), not be swallowed
|
||||
// locally with a wrong usage message.
|
||||
Assert.False(RetailClientCommandCatalog.TryMatch(input, out _));
|
||||
Assert.True(RetailClientCommandCatalog.TryMatch(input, out var match));
|
||||
Assert.True(match.HasValidArguments);
|
||||
Assert.Equal(expected, match.Command);
|
||||
Assert.Equal(expectedArguments, match.Arguments);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("/house")]
|
||||
[InlineData("/house nope")]
|
||||
public void HouseUnknownOrMissingSubcommand_ShowsRetailRefusalLocally(string input)
|
||||
{
|
||||
Assert.True(RetailClientCommandCatalog.TryMatch(input, out var match));
|
||||
Assert.Equal(ClientCommandId.HouseUnrecognizedSubcommand, match.Command);
|
||||
Assert.False(match.HasValidArguments);
|
||||
Assert.Equal(
|
||||
"Please see @help House for more information on how to use this command.",
|
||||
match.InvalidArgumentsText);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HouseAvailableWithoutType_UsesHslistArgumentValidation()
|
||||
{
|
||||
Assert.True(RetailClientCommandCatalog.TryMatch("/house available", out var match));
|
||||
Assert.Equal(ClientCommandId.HouseAvailableList, match.Command);
|
||||
Assert.False(match.HasValidArguments);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -118,24 +150,38 @@ public sealed class RetailClientCommandCatalogTests
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("/allegiance boot Bob")]
|
||||
[InlineData("/allegiance ban add Bob")]
|
||||
[InlineData("/allegiance motd")]
|
||||
[InlineData("/allegiance")]
|
||||
[InlineData("/all officer add 2 Bob")]
|
||||
public void UnsupportedAllegianceSubcommand_ShowsRetailRefusal_ClientSide(string input)
|
||||
[InlineData("/allegiance boot Bob", ClientCommandId.AllegianceBoot, "Bob")]
|
||||
[InlineData("/allegiance ban add Bob", ClientCommandId.AllegianceBan, "add Bob")]
|
||||
[InlineData("/all chat gag Bob", ClientCommandId.AllegianceChat, "gag Bob")]
|
||||
[InlineData("/all ch off", ClientCommandId.AllegianceChat, "off")]
|
||||
[InlineData("/allegiance broadcast hello", ClientCommandId.AllegianceBroadcast, "hello")]
|
||||
[InlineData("/allegiance br hello", ClientCommandId.AllegianceBroadcast, "hello")]
|
||||
[InlineData("/all officer add 2 Bob", ClientCommandId.AllegianceOfficer, "add 2 Bob")]
|
||||
[InlineData("/all title set 2 Regent", ClientCommandId.AllegianceOfficerTitle, "set 2 Regent")]
|
||||
[InlineData("/allegiance motd", ClientCommandId.AllegianceMotd, "")]
|
||||
[InlineData("/allegiance name set A Name", ClientCommandId.AllegianceName, "set A Name")]
|
||||
[InlineData("/allegiance lock bypass Bob", ClientCommandId.AllegianceLock, "bypass Bob")]
|
||||
[InlineData("/allegiance house guest open", ClientCommandId.AllegianceHouse, "guest open")]
|
||||
[InlineData("/motd set Welcome", ClientCommandId.AllegianceMotd, "set Welcome")]
|
||||
public void AllegianceManagementSubcommands_ResolveLocally(
|
||||
string input,
|
||||
ClientCommandId expected,
|
||||
string expectedArguments)
|
||||
{
|
||||
// CH4 REJECT-review Blocker 1 (2026-08-09): unlike @house (whose
|
||||
// unrecognized subcommands correctly reach ACE, see the test
|
||||
// above), retail's own DoAllegiance NEVER falls through to
|
||||
// DoChannelCommand/the server for an unrecognized subcommand — it
|
||||
// claims the whole verb unconditionally and prints its own
|
||||
// client-local refusal (label_57da4b, 0x0057DA4B). The earlier
|
||||
// "falls through to server passthrough" behavior here was itself
|
||||
// the bug: an unmatched subcommand used to escape all the way to
|
||||
// the unregistered-tag channel fallback and broadcast to the
|
||||
// Allegiance chat channel.
|
||||
Assert.True(RetailClientCommandCatalog.TryMatch(input, out var match));
|
||||
Assert.True(match.HasValidArguments);
|
||||
Assert.Equal(expected, match.Command);
|
||||
Assert.Equal(expectedArguments, match.Arguments);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("/allegiance")]
|
||||
[InlineData("/allegiance nope")]
|
||||
[InlineData("/all nonsense")]
|
||||
public void UnknownAllegianceSubcommand_ShowsRetailRefusal_ClientSide(string input)
|
||||
{
|
||||
Assert.True(RetailClientCommandCatalog.TryMatch(input, out var match));
|
||||
Assert.Equal(ClientCommandId.AllegianceUnrecognizedSubcommand, match.Command);
|
||||
Assert.False(match.HasValidArguments);
|
||||
Assert.Equal(
|
||||
"Please see @help Allegiance for more information on how to use this command.",
|
||||
|
|
@ -150,7 +196,7 @@ public sealed class RetailClientCommandCatalogTests
|
|||
[InlineData("/allegiance info", ClientCommandId.AllegianceInfo, "")]
|
||||
[InlineData("/allegiance info Bob", ClientCommandId.AllegianceInfo, "Bob")]
|
||||
[InlineData("/all info Bob", ClientCommandId.AllegianceInfo, "Bob")]
|
||||
public void AllegianceImplementedSubcommands_Resolve(
|
||||
public void AllegianceSimpleSubcommands_Resolve(
|
||||
string input, ClientCommandId expected, string expectedArguments)
|
||||
{
|
||||
Assert.True(RetailClientCommandCatalog.TryMatch(input, out var match));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue