acdream/tests/AcDream.UI.Abstractions.Tests/Panels/Chat/ChatVMCombatTests.cs
Erik 7aae5ba939 chore(chat): CT-D1/D2 — delete the dead ChatPanel, reconcile the stale digest
Campaign CT Group D, closing the campaign.

D1. The ImGui-era ChatPanel has not been constructed anywhere in src/ since
Campaign V deleted AcDream.UI.ImGui. Verified that directly rather than on the
audit's word, then removed it with its three panel-only test files. Those tests
passed, which is exactly the problem: they made the real input surface look
better covered than it is.

ChatVMCombatTests was KEPT — three of its four tests are genuine ChatVM
coverage and only one exercised ChatPanel, so just that method went. Deleting
the file would have quietly dropped real coverage along with the dead kind.
Three doc comments referencing the deleted type were rewritten rather than left
as dangling crefs.

D2. docs/ISSUES.md turned out to be ACCURATE already — #358 and #363 are
recorded CLOSED there, contrary to the audit's summary. What was stale was the
chat DIGEST's "Open" section, which still named four closed issues and claimed
Campaign CH's connected gate was owed. Corrected against ISSUES: genuinely open
are #359, #360, #361 and #366.

The digest also gained a Campaign CT section (the tag mechanism, the MEASURED
tag colour, and what shipped) and three DO-NOT-RETRY rows earned this session:

  - Do not model authored state media with one image per state — the unseen
    indicator's Normal state carries SIX frames and that IS retail's blink.
  - Do not read an element's role from a Binary Ninja field NAME — the names in
    ChatInterface's binder are shifted badly enough to assign a UIElement* into
    a float field.
  - Do not assume our side has a gap because retail has a mechanism. That cost
    this campaign twice in one session: the transcript was claimed unbounded
    when ChatLog has always capped at 500 entries, and C1's auto-scroll was
    planned as a port when UiScrollable already did it.

CT-C4 is deferred and marked so: pure test coverage over behaviour the audit
confirmed already works, changing nothing a user can see.

Solution builds clean; full hermetic gate green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 10:27:43 +02:00

63 lines
2.1 KiB
C#

using AcDream.Core.Chat;
using AcDream.Core.Combat;
using AcDream.UI.Abstractions.Panels.Chat;
namespace AcDream.UI.Abstractions.Tests.Panels.Chat;
/// <summary>
/// Phase I.7: <see cref="ChatVM"/> surfaces combat-kind entries through
/// <see cref="ChatVM.RecentLinesDetailed"/> with their original
/// <see cref="CombatLineKind"/> attached so the panel can pick a
/// <c>TextColored</c> color per line.
/// </summary>
public sealed class ChatVMCombatTests
{
[Fact]
public void FormatEntry_CombatKind_PassesThroughVerbatim()
{
var entry = new ChatEntry(
Kind: ChatKind.Combat,
Sender: "",
Text: "You hit Mosswart for 5 slashing damage (50.0%).",
SenderGuid: 0,
ChannelId: 0)
{ CombatKind = CombatLineKind.Info };
Assert.Equal(
"You hit Mosswart for 5 slashing damage (50.0%).",
ChatVM.FormatEntry(entry));
}
[Fact]
public void RecentLinesDetailed_CombatEntry_RetainsCombatKind()
{
var log = new ChatLog();
var vm = new ChatVM(log);
log.OnCombatLine("Mosswart hit you for 8 fire damage to your chest.",
logTextType: 0x06u, kind: CombatLineKind.Warning);
var lines = vm.RecentLinesDetailed();
var line = Assert.Single(lines);
Assert.Equal(ChatKind.Combat, line.Kind);
Assert.Equal(CombatLineKind.Warning, line.CombatKind);
Assert.Equal("Mosswart hit you for 8 fire damage to your chest.", line.Text);
}
[Fact]
public void RecentLinesDetailed_NonCombatEntry_HasNullCombatKind()
{
var log = new ChatLog();
var vm = new ChatVM(log);
log.OnLocalSpeech("Alice", "hi", senderGuid: 0xAA, isRanged: false, logTextType: 0x02u);
var line = Assert.Single(vm.RecentLinesDetailed());
Assert.Equal(ChatKind.LocalSpeech, line.Kind);
Assert.Null(line.CombatKind);
Assert.Equal("Alice says, \"hi\"", line.Text);
}
private sealed class RecordingChatBus : ICommandBus
{
public void Publish<T>(T command) where T : notnull { /* no-op */ }
}
}