test(selftest): pin the top-tab underline invariant
TopTabBar had no observability at all -- no counter, no self-test reaching it. It now exposes LastRenderedUnderlineCount and MainWindow hands the component out the same way it already does for the sidebar. Three cases: one of two tabs active draws exactly one underline, a null active tab draws zero, and an active tab that is not in the list also draws zero. The last one matters because the strip skips popped-out tabs, so the active tab legitimately need not be among the drawn ones.
This commit is contained in:
@@ -455,6 +455,7 @@ public sealed class Plugin : IAsyncDalamudPlugin
|
|||||||
new SelfTests.CurrentTabCouplingStep(this),
|
new SelfTests.CurrentTabCouplingStep(this),
|
||||||
new SelfTests.SidebarUnreadDotStep(this),
|
new SelfTests.SidebarUnreadDotStep(this),
|
||||||
new SelfTests.SidebarActiveSurfaceStep(this),
|
new SelfTests.SidebarActiveSurfaceStep(this),
|
||||||
|
new SelfTests.TopTabUnderlineStep(this),
|
||||||
new SelfTests.UnreadDecisionStep(),
|
new SelfTests.UnreadDecisionStep(),
|
||||||
new SelfTests.CurrentTabGuidedStep(this),
|
new SelfTests.CurrentTabGuidedStep(this),
|
||||||
new SelfTests.CardClipPlanStep(this),
|
new SelfTests.CardClipPlanStep(this),
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Plugin.SelfTest;
|
||||||
|
using HellionChat.Code;
|
||||||
|
|
||||||
|
namespace HellionChat.SelfTests;
|
||||||
|
|
||||||
|
// v1.10.0/D1: the top-tab strip marks the active tab with a fill plus an accent
|
||||||
|
// underline. Drives the real TopTabBar.Draw and reads the render counter.
|
||||||
|
//
|
||||||
|
// "At most one", not "exactly one": the strip skips popped-out tabs, so zero
|
||||||
|
// underlines is a legitimate state.
|
||||||
|
internal sealed class TopTabUnderlineStep : ISelfTestStep
|
||||||
|
{
|
||||||
|
private readonly Plugin _plugin;
|
||||||
|
|
||||||
|
public TopTabUnderlineStep(Plugin plugin) => _plugin = plugin;
|
||||||
|
|
||||||
|
public string Name => "Hellion Chat - Top tab underline";
|
||||||
|
|
||||||
|
public SelfTestStepResult RunStep()
|
||||||
|
{
|
||||||
|
var strip = _plugin.MainWindow.GetTopTabsForSelfTest();
|
||||||
|
if (strip is null)
|
||||||
|
{
|
||||||
|
ImGui.Text("TopTabBar null");
|
||||||
|
SelfTestReport.Append(Name, "FAIL", new[] { "TopTabBar null" });
|
||||||
|
return SelfTestStepResult.Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
var a = NewProbe("Underline Probe A@SelfTest");
|
||||||
|
var b = NewProbe("Underline Probe B@SelfTest");
|
||||||
|
var list = new List<Tab> { a, b };
|
||||||
|
|
||||||
|
// (a) one of two tabs active -> exactly one underline
|
||||||
|
Tab? active = a;
|
||||||
|
strip.Draw(list, ref active);
|
||||||
|
if (strip.LastRenderedUnderlineCount != 1)
|
||||||
|
return Fail(
|
||||||
|
$"active tab drew {strip.LastRenderedUnderlineCount} underlines, expected 1"
|
||||||
|
);
|
||||||
|
|
||||||
|
// (b) no active tab -> zero, not a crash
|
||||||
|
active = null;
|
||||||
|
strip.Draw(list, ref active);
|
||||||
|
if (strip.LastRenderedUnderlineCount != 0)
|
||||||
|
return Fail($"null active drew {strip.LastRenderedUnderlineCount}, expected 0");
|
||||||
|
|
||||||
|
// (c) an active tab that is not in the list -> still zero
|
||||||
|
active = NewProbe("Absent@SelfTest");
|
||||||
|
strip.Draw(list, ref active);
|
||||||
|
if (strip.LastRenderedUnderlineCount != 0)
|
||||||
|
return Fail($"absent active drew {strip.LastRenderedUnderlineCount}, expected 0");
|
||||||
|
|
||||||
|
SelfTestReport.Append(Name, "PASS", new[] { "1 / 0 / 0 across the three cases" });
|
||||||
|
return SelfTestStepResult.Pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Tab NewProbe(string name) =>
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
SelectedChannels = new Dictionary<ChatType, (ChatSource, ChatSource)>
|
||||||
|
{
|
||||||
|
[ChatType.Say] = (ChatSourceExt.All, ChatSourceExt.All),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
private SelfTestStepResult Fail(string message)
|
||||||
|
{
|
||||||
|
ImGui.Text(message);
|
||||||
|
SelfTestReport.Append(Name, "FAIL", new[] { message });
|
||||||
|
return SelfTestStepResult.Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CleanUp() { }
|
||||||
|
}
|
||||||
@@ -204,6 +204,8 @@ internal sealed class MainWindow : Window, IFocusableChatWindow
|
|||||||
|
|
||||||
internal Components.MessageList GetMessageListForSelfTest() => _messages;
|
internal Components.MessageList GetMessageListForSelfTest() => _messages;
|
||||||
|
|
||||||
|
internal Components.TopTabBar GetTopTabsForSelfTest() => _topTabs;
|
||||||
|
|
||||||
public override bool DrawConditions() => !_userHidden;
|
public override bool DrawConditions() => !_userHidden;
|
||||||
|
|
||||||
internal void UserHide() => _userHidden = true;
|
internal void UserHide() => _userHidden = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user