fix(central-ui): resolve CentralUI-020..025 — auth-ping idle logout, DebugView race, push-handler disposal guard, JS-interop catch narrowing, claim-constant helper, SessionExpiry tests
This commit is contained in:
@@ -109,4 +109,48 @@ public class DeploymentsPushUpdateTests : BunitContext
|
||||
_deployRepo.DidNotReceive()
|
||||
.GetAllDeploymentRecordsAsync(Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Regression test for CentralUI-022. The notifier is a process singleton:
|
||||
/// it can read its subscriber list and begin invoking
|
||||
/// <c>OnDeploymentStatusChanged</c> on the DeploymentManager thread an
|
||||
/// instant before the component is disposed. The handler must no-op against
|
||||
/// a disposed component rather than letting <c>InvokeAsync</c> throw an
|
||||
/// unobserved <see cref="ObjectDisposedException"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Deployments_HasDisposalGuardField()
|
||||
{
|
||||
var field = typeof(DeploymentsPage).GetField(
|
||||
"_disposed", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
|
||||
Assert.NotNull(field);
|
||||
Assert.Equal(typeof(bool), field!.FieldType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Deployments_StatusChangeAfterDispose_DoesNotThrowOrReload()
|
||||
{
|
||||
RegisterServices();
|
||||
var cut = Render<DeploymentsPage>();
|
||||
var component = cut.Instance;
|
||||
|
||||
component.Dispose();
|
||||
_deployRepo.ClearReceivedCalls();
|
||||
|
||||
// Simulate the race: the notifier captured the handler before the
|
||||
// Dispose() unsubscribe and invokes it directly against the now-disposed
|
||||
// component. Pre-fix this dispatched InvokeAsync against a dead circuit
|
||||
// and threw ObjectDisposedException on a fire-and-forget task.
|
||||
var handler = typeof(DeploymentsPage).GetMethod(
|
||||
"OnDeploymentStatusChanged", BindingFlags.Instance | BindingFlags.NonPublic)!;
|
||||
|
||||
var ex = Record.Exception(() => handler.Invoke(component,
|
||||
new object[] { new DeploymentStatusChange("dep-9", 1, DeploymentStatus.Success) }));
|
||||
|
||||
Assert.Null(ex);
|
||||
// The guard short-circuits before any reload is attempted.
|
||||
_deployRepo.DidNotReceive()
|
||||
.GetAllDeploymentRecordsAsync(Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user