acdream/tests/AcDream.Core.Tests/Chat/WeenieErrorMessagesTests.cs
Erik 7b7ffcd278 fix(gameplay): reconcile wield ownership and target facing
Preserve PlayerDescription inventory/equipment ownership across authoritative manifest replacement, make weapon switching and combat/UI consumers read the same canonical object state, and carry the complete outbound player position frame across landblocks.

Route target-facing and mouse-look through the shared MovementManager and MotionInterpreter completion owner. Match retail input aggregation, toggle ordering, turn/sidestep remapping, per-axis hold keys, and synchronous movement publication without render-only heading state.

Initialize the live streaming origin from the first accepted canonical player Position, defer other projections until that origin exists, and retain logical entity identity through hydration.

Advance the project ledger from completed M2 to active M3, synchronize CLAUDE.md/AGENTS.md and durable memory, and record the next cast-lifecycle, spellbook/enchantment, and two-client portal gates.

Co-Authored-By: Codex <noreply@openai.com>
2026-07-15 08:19:23 +02:00

155 lines
5.2 KiB
C#

using AcDream.Core.Chat;
namespace AcDream.Core.Tests.Chat;
/// <summary>
/// Tests for <see cref="WeenieErrorMessages"/>. The retail client showed
/// these as plain-language strings; we mirror that via templated lookup.
/// Filed after the 2026-04-25 live launch where the user saw cryptic
/// "WeenieError 0x051B" in chat for what was actually a friendly login
/// notification.
/// </summary>
public sealed class WeenieErrorMessagesTests
{
// ── known codes — informational, parameterised ───────────────────
[Fact]
public void Format_YouHaveEnteredChannel_SubstitutesParam()
{
// 0x051B = WeenieErrorWithString.YouHaveEnteredThe_Channel.
// Template "You have entered the _ channel." with `_` placeholder.
Assert.Equal(
"You have entered the General channel.",
WeenieErrorMessages.Format(0x051B, "General"));
}
[Fact]
public void Format_YouHaveEnteredChannel_WorksForEachChannelName()
{
Assert.Equal("You have entered the Trade channel.", WeenieErrorMessages.Format(0x051B, "Trade"));
Assert.Equal("You have entered the LFG channel.", WeenieErrorMessages.Format(0x051B, "LFG"));
Assert.Equal("You have entered the Roleplay channel.",WeenieErrorMessages.Format(0x051B, "Roleplay"));
}
[Fact]
public void Format_YouHaveLeftChannel_SubstitutesParam()
{
Assert.Equal(
"You have left the General channel.",
WeenieErrorMessages.Format(0x051C, "General"));
}
// ── known codes — informational, no parameter ────────────────────
[Fact]
public void Format_TurbineChatIsEnabled_NoParamForm()
{
// 0x051D came in WeenieError (no param) form at login.
Assert.Equal(
"Turbine Chat is enabled.",
WeenieErrorMessages.Format(0x051D, param: null));
}
// ── known codes — error-level ────────────────────────────────────
[Fact]
public void Format_CharacterNotAvailable_NoParam()
{
// 0x052B fired by the server when a Tell target lookup fails
// (e.g. the user typed "/t je, hello" → server got "je," → no
// character). Should read like the retail message.
Assert.Equal(
"That person is not available now.",
WeenieErrorMessages.Format(0x052B, param: null));
}
[Fact]
public void Format_TradeComplete()
{
Assert.Equal("Trade Complete!", WeenieErrorMessages.Format(0x0529, null));
}
[Fact]
public void Format_ThatIsNotAValidCommand()
{
// 0x0026 fires on /-prefixed text that ACE's command parser
// can't resolve. Filed after a 2026-04-25 trace where /help
// produced cryptic "WeenieError 0x0026" lines.
Assert.Equal(
"That is not a valid command.",
WeenieErrorMessages.Format(0x0026, null));
}
[Fact]
public void Format_YouAreNotInAllegiance()
{
Assert.Equal(
"You are not in an allegiance!",
WeenieErrorMessages.Format(0x0414, null));
}
[Fact]
public void Format_YouDoNotBelongToAFellowship()
{
Assert.Equal(
"You do not belong to a Fellowship.",
WeenieErrorMessages.Format(0x050F, null));
}
[Theory]
[InlineData(0x0036u, "Action cancelled!")]
[InlineData(0x003Du, "You charged too far!")]
[InlineData(0x004Au, "Ack! You killed yourself!")]
[InlineData(0x0550u, "Out of Range!")]
public void Format_CombatMovementErrors(uint code, string expected)
=> Assert.Equal(expected, WeenieErrorMessages.Format(code, null));
// ── unknown codes — graceful fallback preserves debug info ───────
[Fact]
public void Format_UnknownCode_NoParam_FallsBackToHexForm()
{
Assert.Equal("WeenieError 0xABCD", WeenieErrorMessages.Format(0xABCD, null));
}
[Fact]
public void Format_UnknownCode_WithParam_FallsBackToColonForm()
{
Assert.Equal(
"WeenieError 0xDEAD: Mana Stone",
WeenieErrorMessages.Format(0xDEAD, "Mana Stone"));
}
[Fact]
public void Format_UnknownCode_EmptyParam_StaysAsHexOnly()
{
// Empty string param shouldn't add a stray colon.
Assert.Equal("WeenieError 0xCAFE", WeenieErrorMessages.Format(0xCAFE, ""));
}
// ── parameterised templates with non-trivial params ──────────────
[Fact]
public void Format_HearListAdded_SubstitutesParam()
{
Assert.Equal(
"Caith has been added to the list of people you can hear.",
WeenieErrorMessages.Format(0x0521, "Caith"));
}
[Fact]
public void Format_FailToAffectCannotBeHarmed_SubstitutesParam()
{
Assert.Equal(
"You fail to affect Drudge because they cannot be harmed!",
WeenieErrorMessages.Format(0x004F, "Drudge"));
}
[Fact]
public void Format_HealingTargetAlreadyFull_SubstitutesParam()
{
Assert.Equal(
"+Acdream is already at full health!",
WeenieErrorMessages.Format(0x04FF, "+Acdream"));
}
}