test(selftest): pin the sidebar active-surface invariant
Drives the real Sidebar.Draw and reads the render counter, so a regression in the draw path fails instead of a parallel calculation passing. Three cases: one of two tabs active draws exactly one surface, a null active tab draws zero, and icon-only mode still marks the active row. Zero is a legitimate state, not a failure -- PickMainActiveTab returns null when every tab is popped out, so the invariant is "at most one", not "exactly one".
This commit is contained in:
@@ -454,6 +454,7 @@ public sealed class Plugin : IAsyncDalamudPlugin
|
||||
new SelfTests.TellResetOnActivateStep(),
|
||||
new SelfTests.CurrentTabCouplingStep(this),
|
||||
new SelfTests.SidebarUnreadDotStep(this),
|
||||
new SelfTests.SidebarActiveSurfaceStep(this),
|
||||
new SelfTests.UnreadDecisionStep(),
|
||||
new SelfTests.CurrentTabGuidedStep(this),
|
||||
new SelfTests.CardClipPlanStep(this),
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Plugin.SelfTest;
|
||||
using HellionChat.Code;
|
||||
|
||||
namespace HellionChat.SelfTests;
|
||||
|
||||
// v1.10.0/C3: the active row gets a surface and an accent bar, so exactly the
|
||||
// row the user is on must be marked -- and only that one. Drives the real
|
||||
// Sidebar.Draw and reads the render-observability counter, so a regression in
|
||||
// the draw path fails rather than a parallel calculation passing.
|
||||
//
|
||||
// "At most one", not "exactly one": PickMainActiveTab returns null when every
|
||||
// tab is popped out, which is a legitimate state with zero marked rows.
|
||||
internal sealed class SidebarActiveSurfaceStep : ISelfTestStep
|
||||
{
|
||||
private readonly Plugin _plugin;
|
||||
|
||||
public SidebarActiveSurfaceStep(Plugin plugin) => _plugin = plugin;
|
||||
|
||||
public string Name => "Hellion Chat - Sidebar active surface";
|
||||
|
||||
public SelfTestStepResult RunStep()
|
||||
{
|
||||
var sidebar = _plugin.MainWindow.GetSidebarForSelfTest();
|
||||
if (sidebar is null)
|
||||
{
|
||||
ImGui.Text("Sidebar null");
|
||||
SelfTestReport.Append(Name, "FAIL", new[] { "Sidebar null" });
|
||||
return SelfTestStepResult.Fail;
|
||||
}
|
||||
|
||||
var a = NewProbe("Surface Probe A@SelfTest");
|
||||
var b = NewProbe("Surface Probe B@SelfTest");
|
||||
var list = new List<Tab> { a, b };
|
||||
var width = (float)Plugin.Config.SidebarAutoSwitchThresholdPx + 100f;
|
||||
var savedWidth = Plugin.Config.SidebarWidth;
|
||||
|
||||
try
|
||||
{
|
||||
Plugin.Config.SidebarWidth = 220;
|
||||
|
||||
// (a) one of two tabs is active -> exactly one surface
|
||||
Tab? active = a;
|
||||
sidebar.Draw(width, list, ref active);
|
||||
if (sidebar.LastRenderedActiveSurfaceCount != 1)
|
||||
return Fail(
|
||||
$"active tab drew {sidebar.LastRenderedActiveSurfaceCount}, expected 1"
|
||||
);
|
||||
|
||||
// (b) no active tab (every tab popped out) -> zero, not a crash
|
||||
active = null;
|
||||
sidebar.Draw(width, list, ref active);
|
||||
if (sidebar.LastRenderedActiveSurfaceCount != 0)
|
||||
return Fail(
|
||||
$"null active drew {sidebar.LastRenderedActiveSurfaceCount}, expected 0"
|
||||
);
|
||||
|
||||
// (c) icon-only mode still marks the active row
|
||||
active = b;
|
||||
sidebar.Draw((float)Plugin.Config.SidebarAutoSwitchThresholdPx - 1f, list, ref active);
|
||||
if (sidebar.LastRenderedActiveSurfaceCount != 1)
|
||||
return Fail($"icon-only drew {sidebar.LastRenderedActiveSurfaceCount}, expected 1");
|
||||
|
||||
SelfTestReport.Append(Name, "PASS", new[] { "1 / 0 / 1 across the three cases" });
|
||||
return SelfTestStepResult.Pass;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Plugin.Config.SidebarWidth = savedWidth;
|
||||
}
|
||||
}
|
||||
|
||||
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() { }
|
||||
}
|
||||
Reference in New Issue
Block a user