test(about): assert integrations status through the real render

This commit is contained in:
2026-06-15 14:44:26 +02:00
parent f9ed487ae2
commit 8afcb87624
3 changed files with 106 additions and 0 deletions
+1
View File
@@ -388,6 +388,7 @@ public sealed class Plugin : IAsyncDalamudPlugin
new SelfTests.ConfigMigrationV23Step(this),
new SelfTests.HoverSheenAllocStep(this),
new SelfTests.HonorificHeaderRenderStep(this),
new SelfTests.AboutIntegrationsStatusStep(this),
new SelfTests.PerformanceBaselineStep(this),
new SelfTests.MainWindowFocusOpacityStep(this),
new SelfTests.MainWindowFlagsStep(this),
@@ -0,0 +1,101 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
using HellionChat.Integrations;
namespace HellionChat.SelfTests;
// Verifies the About-tab integrations status. The pure HonorificStatus.Resolve
// covers the three-state mapping (false-green-free); driving the real AboutTab
// render once proves the render path actually calls the resolver (sets
// LastHonorificStatusKey). Set -> Draw -> Assert happen in ONE synchronous
// RunStep so a between-frame Honorific IPC callback can't clobber the seam
// state; the prior service state is restored in CleanUp.
internal sealed class AboutIntegrationsStatusStep : ISelfTestStep
{
private readonly Plugin plugin;
private HonorificService? _svc;
private bool _prevAvailable;
private (uint Major, uint Minor)? _prevVersion;
private HonorificTitleData? _prevTitle;
private bool _snapshotted;
public AboutIntegrationsStatusStep(Plugin plugin)
{
this.plugin = plugin;
}
public string Name => "Hellion Chat - About integrations status";
public SelfTestStepResult RunStep()
{
// AboutTab.Draw renders DrawBrand/coming-soon under _fonts.FontAwesome.Push;
// wait until the atlas is built so the render can't misbehave. Returned
// BEFORE any snapshot/Set, so no seam state leaks (same guard as the header
// step; precedent FoxBannerTextureSmokeStep).
if (!plugin.FontManager.FontsReady)
{
return SelfTestStepResult.Waiting;
}
// Pure mapping (incl. the isAvailable=true + null boundary -> NotInstalled).
if (
HonorificStatus.Resolve(true, (3, 1)) != HonorificStatusKind.Detected
|| HonorificStatus.Resolve(false, (2, 5)) != HonorificStatusKind.Incompatible
|| HonorificStatus.Resolve(false, null) != HonorificStatusKind.NotInstalled
|| HonorificStatus.Resolve(true, null) != HonorificStatusKind.NotInstalled
)
{
ImGui.Text("HonorificStatus.Resolve mapping is wrong");
return SelfTestStepResult.Fail;
}
var about = plugin.SettingsWindow.GetAboutTabForSelfTest();
if (about is null)
{
ImGui.Text("SettingsWindow.AboutTab reference is null");
return SelfTestStepResult.Fail;
}
_svc = plugin.MainWindow.GetHonorificHeaderForSelfTest()?.GetServiceForSelfTest();
if (_svc is null)
{
ImGui.Text("HonorificService reference is null");
return SelfTestStepResult.Fail;
}
_prevAvailable = _svc.IsAvailable;
_prevVersion = _svc.DetectedApiVersion;
_prevTitle = _svc.CurrentTitle;
_snapshotted = true;
try
{
// Drive the real render once and confirm the resolver is wired in.
_svc.TestOnly_SetState(true, (3, 1), null);
about.Draw();
if (about.LastHonorificStatusKey != HonorificStatusKind.Detected.ToString())
{
ImGui.Text(
$"About render did not resolve Detected (got {about.LastHonorificStatusKey})"
);
return SelfTestStepResult.Fail;
}
}
catch (Exception ex)
{
ImGui.Text($"AboutTab.Draw threw: {ex.GetType().Name}: {ex.Message}");
return SelfTestStepResult.Fail;
}
return SelfTestStepResult.Pass;
}
public void CleanUp()
{
if (!_snapshotted || _svc is null)
return;
_svc.TestOnly_SetState(_prevAvailable, _prevVersion, _prevTitle);
_snapshotted = false;
}
}
+4
View File
@@ -112,4 +112,8 @@ internal sealed class SettingsWindow : Window
break;
}
}
// AboutTab is owned here (not MainWindow) and rendered only via the private
// RenderActiveTab; this exposes it for the integrations-status SelfTest.
internal AboutTab GetAboutTabForSelfTest() => _about;
}