using AcDream.Core.Chat; using AcDream.UI.Abstractions.Panels.Chat; namespace AcDream.UI.Abstractions.Tests; public sealed class ChatVMTests { [Fact] public void RecentLines_ReturnsEmpty_ForEmptyLog() { var log = new ChatLog(); var vm = new ChatVM(log); Assert.Empty(vm.RecentLines()); } [Fact] public void RecentLines_ReturnsAllEntries_WhenBelowLimit() { var log = new ChatLog(); log.OnLocalSpeech(sender: "Caith", text: "hello", senderGuid: 0x5000_0001u, isRanged: false); log.OnLocalSpeech(sender: "Regal", text: "world", senderGuid: 0x5000_0002u, isRanged: false); var vm = new ChatVM(log, displayLimit: 20); var lines = vm.RecentLines(); Assert.Equal(2, lines.Count); Assert.Equal("Caith: hello", lines[0]); Assert.Equal("Regal: world", lines[1]); } [Fact] public void RecentLines_ReturnsTail_WhenAboveLimit_InOldestFirstOrder() { var log = new ChatLog(); for (int i = 0; i < 30; i++) log.OnLocalSpeech(sender: "A", text: $"msg{i}", senderGuid: 0x5000_0001u, isRanged: false); var vm = new ChatVM(log, displayLimit: 5); var lines = vm.RecentLines(); // Tail = msg25..msg29 (5 entries, oldest first). Assert.Equal(5, lines.Count); Assert.Equal("A: msg25", lines[0]); Assert.Equal("A: msg29", lines[4]); } [Fact] public void FormatEntry_LocalSpeech_SenderColonText() { var entry = new ChatEntry(ChatKind.LocalSpeech, "Caith", "hello", 0x5000_0001u, 0); Assert.Equal("Caith: hello", ChatVM.FormatEntry(entry)); } [Fact] public void FormatEntry_RangedSpeech_IncludesDistanceHint() { var entry = new ChatEntry(ChatKind.RangedSpeech, "Caith", "hello", 0x5000_0001u, 0); Assert.Equal("Caith says distantly: hello", ChatVM.FormatEntry(entry)); } [Fact] public void FormatEntry_Channel_IncludesChannelId() { var entry = new ChatEntry(ChatKind.Channel, "Caith", "g'day", 0x5000_0001u, 7u); Assert.Equal("[ch 7] Caith: g'day", ChatVM.FormatEntry(entry)); } [Fact] public void FormatEntry_Tell_PrefixedWithTellTag() { var entry = new ChatEntry(ChatKind.Tell, "Regal", "psst", 0x5000_0002u, 0); Assert.Equal("[Tell] Regal: psst", ChatVM.FormatEntry(entry)); } [Fact] public void FormatEntry_System_NoSenderShown() { var entry = new ChatEntry(ChatKind.System, Sender: "", "Your spell fizzled!", 0, 0); Assert.Equal("[System] Your spell fizzled!", ChatVM.FormatEntry(entry)); } [Fact] public void FormatEntry_Popup_Prefixed() { var entry = new ChatEntry(ChatKind.Popup, Sender: "", "A door stands before you.", 0, 0); Assert.Equal("[Popup] A door stands before you.", ChatVM.FormatEntry(entry)); } [Fact] public void Constructor_ThrowsOnNullLog() { Assert.Throws(() => new ChatVM(null!)); } [Fact] public void Constructor_ThrowsOnZeroOrNegativeLimit() { var log = new ChatLog(); Assert.Throws(() => new ChatVM(log, displayLimit: 0)); Assert.Throws(() => new ChatVM(log, displayLimit: -1)); } [Fact] public void RecentLines_ReturnsNewLineData_AfterSubsequentAppend() { // Confirm the VM isn't caching — each call re-snapshots the log. var log = new ChatLog(); var vm = new ChatVM(log); Assert.Empty(vm.RecentLines()); log.OnLocalSpeech("Caith", "hello", 0x5000_0001u, false); var after = vm.RecentLines(); Assert.Single(after); Assert.Equal("Caith: hello", after[0]); } }