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.
112 lines
4.1 KiB
C#
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() { }
|
|
}
|