Files
HellionChat/HellionChat/SelfTests/HonorificHeaderRenderStep.cs
T
JonKazama-Hellion c4562dd6a0 style(selftests): wrap HonorificTitleData ctor to satisfy csharpier
Inherited csharpier drift from the 1.8.7 merge (72099c8); format-only, no behaviour change.
2026-06-15 16:18:05 +02:00

121 lines
4.3 KiB
C#

using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
using HellionChat.Integrations;
namespace HellionChat.SelfTests;
// HonorificHeader has to render without crashing whether the Honorific
// plugin is reachable or not. This probe drives the component through
// one Draw call with the live HonorificService state. The fallback
// path (no IPC, no title) renders just the crown — the present-title
// path renders crown + bracketed title — both must survive without an
// exception.
internal sealed class HonorificHeaderRenderStep : ISelfTestStep
{
private readonly Plugin plugin;
public HonorificHeaderRenderStep(Plugin plugin)
{
this.plugin = plugin;
}
public string Name => "Hellion Chat - HonorificHeader render";
private HonorificService? _svc;
private bool _prevAvailable;
private (uint Major, uint Minor)? _prevVersion;
private HonorificTitleData? _prevTitle;
private bool _prevToggle;
private bool _snapshotted;
public SelfTestStepResult RunStep()
{
// HonorificHeader.Draw early-returns on !FontsReady (HonorificHeader.cs:40-44)
// and never reaches the gated title branch, which would make assert (a) a
// false FAIL during a font-atlas rebuild. Return Waiting BEFORE any
// snapshot/mutation so the runner re-polls cleanly and no seam state leaks
// (precedent: FoxBannerTextureSmokeStep). This is a pre-Set precondition
// gate, not a mid-test Waiting — the Set->Draw->Assert window stays synchronous.
if (!plugin.FontManager.FontsReady)
{
return SelfTestStepResult.Waiting;
}
var header = plugin.MainWindow.GetHonorificHeaderForSelfTest();
if (header is null)
{
ImGui.Text("MainWindow.HonorificHeader reference is null");
return SelfTestStepResult.Fail;
}
_svc = header.GetServiceForSelfTest();
_prevAvailable = _svc.IsAvailable;
_prevVersion = _svc.DetectedApiVersion;
_prevTitle = _svc.CurrentTitle;
_prevToggle = Plugin.Config.ShowHonorificTitleInHeader;
_snapshotted = true;
var valid = new HonorificTitleData("Champion", false, false, null, null, null, null, null);
var original = new HonorificTitleData(
"Champion",
false,
true,
null,
null,
null,
null,
null
);
// Draw at a deliberately wide 420px so the title never hits the truncation
// clamp — LastTitleRendered then reflects the GATE outcome, not the width.
try
{
// (a) available + valid title + toggle on -> title renders
Plugin.Config.ShowHonorificTitleInHeader = true;
_svc.TestOnly_SetState(true, (3, 1), valid);
header.Draw(420f);
if (!header.LastTitleRendered)
{
ImGui.Text("Gate failed: valid title did not render");
return SelfTestStepResult.Fail;
}
// (b) toggle off -> title suppressed (crown stays, untestable headless)
Plugin.Config.ShowHonorificTitleInHeader = false;
header.Draw(420f);
if (header.LastTitleRendered)
{
ImGui.Text("Gate failed: title rendered with toggle off");
return SelfTestStepResult.Fail;
}
// (c) IsOriginal title -> suppressed even with toggle on
Plugin.Config.ShowHonorificTitleInHeader = true;
_svc.TestOnly_SetState(true, (3, 1), original);
header.Draw(420f);
if (header.LastTitleRendered)
{
ImGui.Text("Gate failed: original title rendered");
return SelfTestStepResult.Fail;
}
}
catch (Exception ex)
{
ImGui.Text($"HonorificHeader.Draw threw: {ex.GetType().Name}: {ex.Message}");
return SelfTestStepResult.Fail;
}
return SelfTestStepResult.Pass;
}
public void CleanUp()
{
if (!_snapshotted || _svc is null)
return;
Plugin.Config.ShowHonorificTitleInHeader = _prevToggle;
_svc.TestOnly_SetState(_prevAvailable, _prevVersion, _prevTitle);
_snapshotted = false;
}
}