Files
HellionChat/HellionChat/SelfTests/CardClipPlanStep.cs
T
JonKazama-Hellion 16557213cd chore: comments, second pass -- the task codes the first pass missed
The first sweep matched a character class that swallowed the digit, so a bare
B1 slipped through while B1-2 was caught. Searching the whole A-Z space instead
of guessing prefixes turned up 130-odd more: B0 through B6, C2, C3, D1, H2, M6,
P7, P8, T2, W2, plus GP-04, KB-01, OD-1, PM-1, PM-3, SEC-01, TR-4, TR-7, UI-11,
UI-12, XC-8 and API-3.

Kept deliberately: 41 B4 01 is a byte signature, "N0" a format string,
#L119-L128 a source anchor, LS4/LS6 are linkshells, and A=FF B=0C G=41 R=C2
explains a colour-channel order. Those look like codes and are not.

Also translated the eight German comments left in the theme files and
ImGuiUtil. Seven of them described what a palette does to which channel, which
is worth reading -- just not in a second language in an otherwise English
codebase.
2026-08-19 22:03:12 +02:00

112 lines
4.1 KiB
C#

using System.Collections.Generic;
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
using HellionChat.Util;
namespace HellionChat.SelfTests;
// Behavioural check that the card path feeds CardClipPlanner AND that a
// layout change clears the height cache — not a non-null check. Pure plan math
// is pinned headless by CardClipPlanTests; this drives the live accessors.
internal sealed class CardClipPlanStep : ISelfTestStep
{
private readonly Plugin plugin;
public CardClipPlanStep(Plugin plugin) => this.plugin = plugin;
public string Name => "Hellion Chat - Card clip plan + cache invalidation";
public SelfTestStepResult RunStep()
{
var messages = plugin.MainWindow.GetMessageListForSelfTest();
if (messages is null)
{
ImGui.Text("MessageList null");
SelfTestReport.Append(Name, "FAIL", new[] { "MessageList null" });
return SelfTestStepResult.Fail;
}
// 5 rows of 20, viewport 50, scroll 45 -> skip rows 0,1 (lead 40), see 2..4.
IReadOnlyList<float> heights = [20f, 20f, 20f, 20f, 20f];
var plan = messages.PlanCardClipForSelfTest(heights, scrollY: 45f, viewportHeight: 50f);
if (
plan.FirstVisible != 2
|| plan.LastVisible != 4
|| plan.LeadDummyHeight is < 39.9f or > 40.1f
)
{
var msg =
$"Plan wrong: first={plan.FirstVisible} last={plan.LastVisible} lead={plan.LeadDummyHeight}";
ImGui.Text(msg);
SelfTestReport.Append(Name, "FAIL", new[] { msg });
return SelfTestStepResult.Fail;
}
var tab = plugin.MainWindow.ActiveTab;
if (tab is null)
{
ImGui.Text("No active tab");
SelfTestReport.Append(Name, "FAIL", new[] { "No active tab" });
return SelfTestStepResult.Fail;
}
// Flip a height-affecting mode -> fingerprint changes -> cache must drop.
// Config restored in finally (live-singleton discipline).
var savedForm = Plugin.Config.NameFormMode;
int remaining;
try
{
// v1.10.0: the fingerprint gate waits for the value to settle, so
// the step walks a synthetic clock past the window instead of sleeping.
var clock = Environment.TickCount64;
messages.RunHeightCacheInvalidationForSelfTest(tab, 400f, clock);
using (var snap = tab.Messages.GetReadOnly(3))
{
if (snap.Count > 0)
snap[0].Height[tab.Identifier] = 42f;
}
Plugin.Config.NameFormMode =
savedForm == NameFormMode.Full ? NameFormMode.Initials : NameFormMode.Full;
messages.RunHeightCacheInvalidationForSelfTest(tab, 400f, clock);
clock += LayoutFingerprintGate.SettleMs;
remaining = messages.RunHeightCacheInvalidationForSelfTest(tab, 400f, clock);
}
finally
{
Plugin.Config.NameFormMode = savedForm;
var restore = Environment.TickCount64 + LayoutFingerprintGate.SettleMs * 2;
messages.RunHeightCacheInvalidationForSelfTest(tab, 400f, restore);
messages.RunHeightCacheInvalidationForSelfTest(
tab,
400f,
restore + LayoutFingerprintGate.SettleMs
);
}
if (remaining != 0)
{
var msg = $"Cache not cleared after layout change: {remaining} left";
ImGui.Text(msg);
SelfTestReport.Append(Name, "FAIL", new[] { msg });
return SelfTestStepResult.Fail;
}
SelfTestReport.Append(
Name,
"PASS",
new[]
{
$"Plan range [{plan.FirstVisible}..{plan.LastVisible}], lead={plan.LeadDummyHeight}",
"Height cache cleared after layout-fingerprint change",
}
);
ImGui.Text(
$"PASS — plan [{plan.FirstVisible}..{plan.LastVisible}], cache cleared on layout change."
);
return SelfTestStepResult.Pass;
}
public void CleanUp() { }
}