From 8afcb87624b3e7052fae3a91658356147aa05f32 Mon Sep 17 00:00:00 2001 From: Jon Kazama Date: Mon, 15 Jun 2026 14:44:26 +0200 Subject: [PATCH] test(about): assert integrations status through the real render --- HellionChat/Plugin.cs | 1 + .../SelfTests/AboutIntegrationsStatusStep.cs | 101 ++++++++++++++++++ HellionChat/Ui/Windows/SettingsWindow.cs | 4 + 3 files changed, 106 insertions(+) create mode 100644 HellionChat/SelfTests/AboutIntegrationsStatusStep.cs diff --git a/HellionChat/Plugin.cs b/HellionChat/Plugin.cs index f00ab25..96d278d 100755 --- a/HellionChat/Plugin.cs +++ b/HellionChat/Plugin.cs @@ -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), diff --git a/HellionChat/SelfTests/AboutIntegrationsStatusStep.cs b/HellionChat/SelfTests/AboutIntegrationsStatusStep.cs new file mode 100644 index 0000000..c7e9014 --- /dev/null +++ b/HellionChat/SelfTests/AboutIntegrationsStatusStep.cs @@ -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; + } +} diff --git a/HellionChat/Ui/Windows/SettingsWindow.cs b/HellionChat/Ui/Windows/SettingsWindow.cs index 82ec235..b7b8537 100644 --- a/HellionChat/Ui/Windows/SettingsWindow.cs +++ b/HellionChat/Ui/Windows/SettingsWindow.cs @@ -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; }