fix(centralui)+test(centralui): Low-wave integration — T12 Topology race fixture gains T13's IStaleInstanceProbe dependency; T11 sandbox-run continuation skips StateHasChanged after Dispose

Cross-task regression caught by the combined sweep: TopologyLiveUpdatesTimerDisposeRaceTests
(T12) builds a real DeploymentService, whose constructor grew an IStaleInstanceProbe
parameter in T13 (P7-6 up-to-date pre-filter) — 4 DI-resolution failures on the
integration branch that neither task saw in isolation. Registered a substitute, matching
TopologyPageTests.

Bundle review Minor: ApiMethodForm/SharedScriptForm copied TemplateScriptDialog's sandbox
pattern exactly, whose finally re-renders unconditionally; the plan asked the continuation
to be guarded on disposal, so a _disposed flag now suppresses the post-cancel
StateHasChanged (the reference dialog keeps its original shape — out of T11's scope).
This commit is contained in:
Joseph Doherty
2026-08-20 08:42:56 -04:00
parent 3bf1537ea0
commit 57c8973b0d
3 changed files with 10 additions and 2 deletions
@@ -232,6 +232,7 @@
private Dictionary<string, object?> _paramValues = new();
private ScriptAnalysis.SandboxRunResult? _runResult;
private CancellationTokenSource? _runCts;
private bool _disposed;
protected override async Task OnInitializedAsync()
{
@@ -381,6 +382,7 @@
/// <summary>Cancels an in-flight Test Run when the component is torn down.</summary>
public void Dispose()
{
_disposed = true;
_runCts?.Cancel();
_runCts?.Dispose();
_runCts = null;
@@ -422,7 +424,8 @@
finally
{
_running = false;
StateHasChanged();
// The run may have been cancelled BY Dispose — the component is gone, don't re-render it.
if (!_disposed) StateHasChanged();
}
}
@@ -202,6 +202,7 @@
private Dictionary<string, object?> _paramValues = new();
private ScriptAnalysis.SandboxRunResult? _runResult;
private CancellationTokenSource? _runCts;
private bool _disposed;
// CentralUI-024: delegates to the shared helper so the claim type stays
// resolved through JwtTokenService rather than a duplicated magic string.
@@ -245,6 +246,7 @@
/// <summary>Cancels an in-flight Test Run when the component is torn down.</summary>
public void Dispose()
{
_disposed = true;
_runCts?.Cancel();
_runCts?.Dispose();
_runCts = null;
@@ -344,7 +346,8 @@
finally
{
_running = false;
StateHasChanged();
// The run may have been cancelled BY Dispose — the component is gone, don't re-render it.
if (!_disposed) StateHasChanged();
}
}
@@ -56,6 +56,8 @@ public class TopologyLiveUpdatesTimerDisposeRaceTests : BunitContext
Services.AddSingleton(_siteRepo);
Services.AddSingleton(_deployRepo);
Services.AddSingleton(Substitute.For<ZB.MOM.WW.ScadaBridge.DeploymentManager.IFlatteningPipeline>());
// DeploymentService takes IStaleInstanceProbe since the Low-wave P7-6 pre-filter (T13).
Services.AddSingleton(Substitute.For<ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Transport.IStaleInstanceProbe>());
Services.AddSingleton(_audit);
var comms = new CommunicationService(