107 lines
4.1 KiB
C#
107 lines
4.1 KiB
C#
using Dalamud.Bindings.ImGui;
|
|
using Dalamud.Game.Text;
|
|
using Dalamud.Game.Text.SeStringHandling;
|
|
using Dalamud.Plugin.SelfTest;
|
|
using HellionChat.Code;
|
|
using HellionChat.Util;
|
|
|
|
namespace HellionChat.SelfTests;
|
|
|
|
// B3-3: notification-sound selection. Drives the pure SelectNotificationSound
|
|
// (the exact pick logic ProcessMessage runs per message) through its SelfTest
|
|
// wrapper with local synthetic tabs — Plugin.Config.Tabs is never touched, so
|
|
// no real tab gains messages or unread state. The audible preview button is
|
|
// smoke-only and deliberately not exercised here.
|
|
internal sealed class NotificationSoundSelectStep : ISelfTestStep
|
|
{
|
|
public string Name => "Hellion Chat - Notification sound selection";
|
|
|
|
public SelfTestStepResult RunStep()
|
|
{
|
|
// Probe: a plain Say line, built the FakeMessage way (InputPreview /
|
|
// AutoTellTabsService pattern). Source 0 short-circuits the source
|
|
// filter in Message.Matches, so only the ChatType key decides a match.
|
|
var ss = new SeStringBuilder().AddText("probe").Build();
|
|
var chunks = ChunkUtil.ToChunks(ss, ChunkSource.Content, ChatType.Say).ToList();
|
|
var probe = Message.FakeMessage(chunks, new ChatCode(XivChatType.Say, 0, 0));
|
|
|
|
// The current tab wants a sound too — it must lose ONLY because it is
|
|
// current, so a broken is-active exclusion yields 1 instead of 7 here.
|
|
var currentTab = MakeSayTab(enableSound: true, soundId: 1);
|
|
var inactiveWanting = MakeSayTab(enableSound: true, soundId: 7);
|
|
|
|
// (a) the inactive tab that wants a sound wins.
|
|
var picked = MessageManager.TestSelectNotificationSoundForSelfTest(
|
|
[currentTab, inactiveWanting],
|
|
currentTab,
|
|
probe,
|
|
playSounds: true
|
|
);
|
|
if (picked != 7)
|
|
{
|
|
ImGui.Text($"Expected sound 7 from inactive tab, got {picked?.ToString() ?? "null"}");
|
|
return SelfTestStepResult.Fail;
|
|
}
|
|
|
|
// (b) first match wins: a later qualifying tab must not override.
|
|
var second = MakeSayTab(enableSound: true, soundId: 9);
|
|
picked = MessageManager.TestSelectNotificationSoundForSelfTest(
|
|
[currentTab, inactiveWanting, second],
|
|
currentTab,
|
|
probe,
|
|
playSounds: true
|
|
);
|
|
if (picked != 7)
|
|
{
|
|
ImGui.Text($"First-match guard broken: expected 7, got {picked?.ToString() ?? "null"}");
|
|
return SelfTestStepResult.Fail;
|
|
}
|
|
|
|
// (c) the global sound master mutes everything.
|
|
picked = MessageManager.TestSelectNotificationSoundForSelfTest(
|
|
[currentTab, inactiveWanting],
|
|
currentTab,
|
|
probe,
|
|
playSounds: false
|
|
);
|
|
if (picked is not null)
|
|
{
|
|
ImGui.Text($"PlaySounds=false must return null, got {picked}");
|
|
return SelfTestStepResult.Fail;
|
|
}
|
|
|
|
// (d) negative: a tab without the Say channel never matches the probe.
|
|
var nonMatching = new Tab { EnableNotificationSound = true, NotificationSoundId = 7 };
|
|
picked = MessageManager.TestSelectNotificationSoundForSelfTest(
|
|
[currentTab, nonMatching],
|
|
currentTab,
|
|
probe,
|
|
playSounds: true
|
|
);
|
|
if (picked is not null)
|
|
{
|
|
ImGui.Text($"Non-matching tab must not pick a sound, got {picked}");
|
|
return SelfTestStepResult.Fail;
|
|
}
|
|
|
|
return SelfTestStepResult.Pass;
|
|
}
|
|
|
|
// Local synthetic tab matching Say, the way TabsUtil presets build their
|
|
// channel maps. Non-temp and without TellTarget, so Tab.Matches stays on
|
|
// the pure channel path instead of routing through MatchesSender.
|
|
private static Tab MakeSayTab(bool enableSound, uint soundId) =>
|
|
new()
|
|
{
|
|
Name = "selftest-sound",
|
|
SelectedChannels = new Dictionary<ChatType, (ChatSource, ChatSource)>
|
|
{
|
|
[ChatType.Say] = (ChatSourceExt.All, ChatSourceExt.All),
|
|
},
|
|
EnableNotificationSound = enableSound,
|
|
NotificationSoundId = soundId,
|
|
};
|
|
|
|
public void CleanUp() { }
|
|
}
|