Guard dialog completion by presentation identity
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
# Dialog presentation identity followup
|
||||||
|
|
||||||
|
A custom body retained the service-wide resolver after cancellation, and a delayed native activation rejection canceled whichever presentation was current. Both defects reproduced before the change: two stale custom-context cases and one delayed rejection case failed.
|
||||||
|
|
||||||
|
DialogService now checks the captured completion source. DialogHost binds rendered handlers and activation rejection to their captured DialogState; a stale handler cannot change a replacement prompt draft or result. Existing public APIs, typed cancellation outcomes and the single-active contract are preserved. Disposal still cancels the current presentation.
|
||||||
|
|
||||||
|
Verification: all three regressions pass; the full CentralUI suite passes 1600/1600, zero skips/failures. Logs retain actual red and green runs. This is a local managed lifecycle regression check, not a new native browser matrix or production operation.
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.CentralUI.Tests -> /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll
|
||||||
|
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
|
||||||
|
A total of 1 test files matched the specified pattern.
|
||||||
|
[xUnit.net 00:00:00.19] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared.DialogContextIdentityTests.StaleCustomContext_DoesNotResolveNewDialog(staleCancel: True) [FAIL]
|
||||||
|
[xUnit.net 00:00:00.19] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared.DialogContextIdentityTests.StaleCustomContext_DoesNotResolveNewDialog(staleCancel: False) [FAIL]
|
||||||
|
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared.DialogContextIdentityTests.StaleCustomContext_DoesNotResolveNewDialog(staleCancel: True) [6 ms]
|
||||||
|
Error Message:
|
||||||
|
Assert.Equal() Failure: Strings differ
|
||||||
|
Expected: "Second"
|
||||||
|
Actual: null
|
||||||
|
Stack Trace:
|
||||||
|
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared.DialogContextIdentityTests.StaleCustomContext_DoesNotResolveNewDialog(Boolean staleCancel) in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Shared/DialogContextIdentityTests.cs:line 24
|
||||||
|
--- End of stack trace from previous location ---
|
||||||
|
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared.DialogContextIdentityTests.StaleCustomContext_DoesNotResolveNewDialog(staleCancel: False) [< 1 ms]
|
||||||
|
Error Message:
|
||||||
|
Assert.Equal() Failure: Strings differ
|
||||||
|
Expected: "Second"
|
||||||
|
Actual: null
|
||||||
|
Stack Trace:
|
||||||
|
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared.DialogContextIdentityTests.StaleCustomContext_DoesNotResolveNewDialog(Boolean staleCancel) in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Shared/DialogContextIdentityTests.cs:line 24
|
||||||
|
--- End of stack trace from previous location ---
|
||||||
|
|
||||||
|
Failed! - Failed: 2, Passed: 0, Skipped: 0, Total: 2, Duration: 41 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.CentralUI.Tests -> /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll
|
||||||
|
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
|
||||||
|
A total of 1 test files matched the specified pattern.
|
||||||
|
|
||||||
|
Passed! - Failed: 0, Passed: 3, Skipped: 0, Total: 3, Duration: 166 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
|
||||||
|
A total of 1 test files matched the specified pattern.
|
||||||
|
|
||||||
|
Passed! - Failed: 0, Passed: 1600, Skipped: 0, Total: 1600, Duration: 32 s - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
|
||||||
|
ZB.MOM.WW.ScadaBridge.CentralUI.Tests -> /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll
|
||||||
|
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Debug/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
|
||||||
|
A total of 1 test files matched the specified pattern.
|
||||||
|
[xUnit.net 00:00:01.32] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared.DialogHostPresentationIdentityTests.LateActivationRejection_DoesNotCancelReplacementPrompt [FAIL]
|
||||||
|
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared.DialogHostPresentationIdentityTests.LateActivationRejection_DoesNotCancelReplacementPrompt [1 s]
|
||||||
|
Error Message:
|
||||||
|
Bunit.Extensions.WaitForHelpers.WaitForFailedException : The assertion did not pass within the timeout period.
|
||||||
|
|
||||||
|
If this test does not fail consistently, the reason may be that
|
||||||
|
the wait timeout is too short, and the runtime did not have enough
|
||||||
|
time to complete the necessary number of renders of the component under test.
|
||||||
|
This can happen on highly utilized or slower hardware, for example.
|
||||||
|
|
||||||
|
To determine if this is the cause, compare the check and render count(s) below
|
||||||
|
and see if they match what is expected. If they do not,
|
||||||
|
consider increasing the timeout, either at the individual
|
||||||
|
method call level, e.g. WaitForElement("div", TimeSpan.FromSeconds(15)),
|
||||||
|
or via the static TestContext.DefaultWaitTimeout property.
|
||||||
|
|
||||||
|
Check count: 1.
|
||||||
|
Component render count: 5.
|
||||||
|
Total render count across all components: 0.
|
||||||
|
---- Assert.Equal() Failure: Strings differ
|
||||||
|
Expected: "Second"
|
||||||
|
Actual: null
|
||||||
|
Stack Trace:
|
||||||
|
at Bunit.RenderedComponentWaitForHelperExtensions.WaitForAssertion[TComponent](IRenderedComponent`1 renderedComponent, Action assertion, Nullable`1 timeout) in /_/src/bunit/Extensions/WaitForHelpers/RenderedComponentWaitForHelperExtensions.WaitForState.cs:line 77
|
||||||
|
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared.DialogHostPresentationIdentityTests.LateActivationRejection_DoesNotCancelReplacementPrompt() in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Shared/DialogHostPresentationIdentityTests.cs:line 29
|
||||||
|
--- End of stack trace from previous location ---
|
||||||
|
----- Inner Stack Trace -----
|
||||||
|
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared.DialogHostPresentationIdentityTests.<>c__DisplayClass0_0.<LateActivationRejection_DoesNotCancelReplacementPrompt>b__7() in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Shared/DialogHostPresentationIdentityTests.cs:line 29
|
||||||
|
at Bunit.Extensions.WaitForHelpers.WaitForAssertionHelper`1.<>c__DisplayClass6_0.<.ctor>b__0() in /_/src/bunit/Extensions/WaitForHelpers/WaitForAssertionHelper.cs:line 35
|
||||||
|
at Bunit.Extensions.WaitForHelpers.WaitForHelper`2.OnAfterRender(Object sender, EventArgs args) in /_/src/bunit/Extensions/WaitForHelpers/WaitForHelper.cs:line 173
|
||||||
|
|
||||||
|
Failed! - Failed: 1, Passed: 0, Skipped: 0, Total: 1, Duration: 1 s - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
|
||||||
@@ -18,12 +18,12 @@
|
|||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-labelledby="@TitleId"
|
aria-labelledby="@TitleId"
|
||||||
aria-describedby="@(state.Kind == DialogKind.Confirm ? BodyId : null)"
|
aria-describedby="@(state.Kind == DialogKind.Confirm ? BodyId : null)"
|
||||||
@onkeydown="OnKeyDown">
|
@onkeydown="e => OnKeyDown(state, e)">
|
||||||
<div class="modal-dialog modal-dialog-centered@(state.Size is null ? "" : $" {state.Size}")" role="document">
|
<div class="modal-dialog modal-dialog-centered@(state.Size is null ? "" : $" {state.Size}")" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 id="@TitleId" class="modal-title">@state.Title</h5>
|
<h5 id="@TitleId" class="modal-title">@state.Title</h5>
|
||||||
<button type="button" class="btn-close" aria-label="Close" @onclick="Cancel"></button>
|
<button type="button" class="btn-close" aria-label="Close" @onclick="() => Cancel(state)"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
@if (state.Kind == DialogKind.Confirm)
|
@if (state.Kind == DialogKind.Confirm)
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
class="form-control form-control-sm"
|
class="form-control form-control-sm"
|
||||||
placeholder="@state.Placeholder"
|
placeholder="@state.Placeholder"
|
||||||
value="@_promptValue"
|
value="@_promptValue"
|
||||||
@oninput="OnPromptInput" />
|
@oninput="e => OnPromptInput(state, e)" />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@* Custom dialogs supply their own action buttons inside the body,
|
@* Custom dialogs supply their own action buttons inside the body,
|
||||||
@@ -50,10 +50,10 @@
|
|||||||
{
|
{
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<div class="btn-group btn-group-sm" role="group">
|
<div class="btn-group btn-group-sm" role="group">
|
||||||
<button type="button" class="btn btn-outline-secondary" @onclick="Cancel">Cancel</button>
|
<button type="button" class="btn btn-outline-secondary" @onclick="() => Cancel(state)">Cancel</button>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="btn @ConfirmButtonClass(state)"
|
class="btn @ConfirmButtonClass(state)"
|
||||||
@onclick="Confirm">
|
@onclick="() => Confirm(state)">
|
||||||
@ConfirmLabel(state)
|
@ConfirmLabel(state)
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
public async ValueTask DisposeAsync()
|
public async ValueTask DisposeAsync()
|
||||||
{
|
{
|
||||||
if (Service is DialogService svc) svc.OnChange -= OnServiceChanged;
|
if (Service is DialogService svc) svc.OnChange -= OnServiceChanged;
|
||||||
Cancel(); // A disposed host must not leave its local dialog result pending.
|
if ((Service as DialogService)?.Current is { } current) Cancel(current); // Complete the disposed presentation.
|
||||||
try { await JS.InvokeVoidAsync("sbDialog.deactivate", _overlayId); }
|
try { await JS.InvokeVoidAsync("sbDialog.deactivate", _overlayId); }
|
||||||
catch (JSDisconnectedException) { }
|
catch (JSDisconnectedException) { }
|
||||||
catch (InvalidOperationException) { /* prerender */ }
|
catch (InvalidOperationException) { /* prerender */ }
|
||||||
@@ -114,7 +114,7 @@
|
|||||||
{
|
{
|
||||||
var activated = await JS.InvokeAsync<bool?>("sbDialog.activate", _overlayId,
|
var activated = await JS.InvokeAsync<bool?>("sbDialog.activate", _overlayId,
|
||||||
current.Kind == DialogKind.Prompt ? "#" + PromptId : null);
|
current.Kind == DialogKind.Prompt ? "#" + PromptId : null);
|
||||||
if (activated == false) Cancel(); // Single-active-overlay contract.
|
if (activated == false) Cancel(current); // Single-active-overlay contract.
|
||||||
}
|
}
|
||||||
catch (JSDisconnectedException) { }
|
catch (JSDisconnectedException) { }
|
||||||
catch (InvalidOperationException) { /* prerender */ }
|
catch (InvalidOperationException) { /* prerender */ }
|
||||||
@@ -128,21 +128,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnKeyDown(KeyboardEventArgs e)
|
private void OnKeyDown(DialogState state, KeyboardEventArgs e)
|
||||||
{
|
{
|
||||||
// Native DOM keydown owns synchronous Tab containment; Escape retains
|
// Native DOM keydown owns synchronous Tab containment; Escape retains
|
||||||
// the service's existing typed cancellation path.
|
// the service's existing typed cancellation path.
|
||||||
if (e.Key == "Escape") Cancel();
|
if (e.Key == "Escape") Cancel(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPromptInput(ChangeEventArgs e)
|
private void OnPromptInput(DialogState state, ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (!ReferenceEquals((Service as DialogService)?.Current, state)) return;
|
||||||
_promptValue = e.Value?.ToString() ?? string.Empty;
|
_promptValue = e.Value?.ToString() ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Cancel()
|
private void Cancel(DialogState state)
|
||||||
{
|
{
|
||||||
if (Service is not DialogService svc || svc.Current is null) return;
|
if (Service is not DialogService svc || !ReferenceEquals(svc.Current, state)) return;
|
||||||
var resolveValue = svc.Current.Kind == DialogKind.Confirm
|
var resolveValue = svc.Current.Kind == DialogKind.Confirm
|
||||||
? (object)false
|
? (object)false
|
||||||
: (object?)null;
|
: (object?)null;
|
||||||
@@ -150,9 +151,9 @@
|
|||||||
svc.Resolve(resolveValue);
|
svc.Resolve(resolveValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Confirm()
|
private void Confirm(DialogState state)
|
||||||
{
|
{
|
||||||
if (Service is not DialogService svc || svc.Current is null) return;
|
if (Service is not DialogService svc || !ReferenceEquals(svc.Current, state)) return;
|
||||||
var resolveValue = svc.Current.Kind == DialogKind.Confirm
|
var resolveValue = svc.Current.Kind == DialogKind.Confirm
|
||||||
? (object)true
|
? (object)true
|
||||||
: (object?)_promptValue;
|
: (object?)_promptValue;
|
||||||
|
|||||||
@@ -78,11 +78,12 @@ public class DialogService : IDialogService
|
|||||||
var tcs = new TaskCompletionSource<object?>(TaskCreationOptions.RunContinuationsAsynchronously);
|
var tcs = new TaskCompletionSource<object?>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
_tcs = tcs;
|
_tcs = tcs;
|
||||||
|
|
||||||
// The context routes Close/Cancel back through the same boxed Resolve()
|
// A custom body can finish after its presentation has closed. Only its
|
||||||
// path the host uses for confirm/prompt — Close boxes the typed value,
|
// captured completion source may resolve the active dialog.
|
||||||
// Cancel passes null. Capturing Resolve (not a service reference) keeps
|
var context = new DialogContext<TResult>(result =>
|
||||||
// the body's surface narrow and the resolution path uniform.
|
{
|
||||||
var context = new DialogContext<TResult>(Resolve);
|
if (ReferenceEquals(_tcs, tcs)) Resolve(result);
|
||||||
|
});
|
||||||
|
|
||||||
// Materialise the caller's RenderFragment<DialogContext<TResult>> into a
|
// Materialise the caller's RenderFragment<DialogContext<TResult>> into a
|
||||||
// plain RenderFragment bound to this context, so DialogState stays
|
// plain RenderFragment bound to this context, so DialogState stays
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared;
|
||||||
|
|
||||||
|
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared;
|
||||||
|
|
||||||
|
/// <summary>Custom completions belong to the dialog whose typed context was issued.</summary>
|
||||||
|
public sealed class DialogContextIdentityTests
|
||||||
|
{
|
||||||
|
/// <summary>A canceled custom context cannot confirm or cancel a subsequently opened dialog.</summary>
|
||||||
|
[Theory]
|
||||||
|
[InlineData(false)]
|
||||||
|
[InlineData(true)]
|
||||||
|
public async Task StaleCustomContext_DoesNotResolveNewDialog(bool staleCancel)
|
||||||
|
{
|
||||||
|
var service = new DialogService();
|
||||||
|
DialogContext<bool> first = null!;
|
||||||
|
var pendingFirst = service.ShowAsync<bool>("First", context => { first = context; return _ => { }; });
|
||||||
|
first.Cancel();
|
||||||
|
Assert.False(await pendingFirst);
|
||||||
|
|
||||||
|
DialogContext<bool> second = null!;
|
||||||
|
var pendingSecond = service.ShowAsync<bool>("Second", context => { second = context; return _ => { }; });
|
||||||
|
if (staleCancel) first.Cancel(); else first.Close(true);
|
||||||
|
Assert.False(pendingSecond.IsCompleted);
|
||||||
|
Assert.Equal("Second", service.Current?.Title);
|
||||||
|
second.Close(true);
|
||||||
|
Assert.True(await pendingSecond);
|
||||||
|
Assert.Null(service.Current);
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
using Bunit;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared;
|
||||||
|
|
||||||
|
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared;
|
||||||
|
|
||||||
|
/// <summary>A late native activation result belongs to its original presentation.</summary>
|
||||||
|
public sealed class DialogHostPresentationIdentityTests : BunitContext
|
||||||
|
{
|
||||||
|
/// <summary>Rejecting a closed confirm cannot cancel a prompt that has since opened.</summary>
|
||||||
|
[Fact]
|
||||||
|
public async Task LateActivationRejection_DoesNotCancelReplacementPrompt()
|
||||||
|
{
|
||||||
|
var service = new DialogService();
|
||||||
|
Services.AddSingleton<IDialogService>(service);
|
||||||
|
JSInterop.Mode = JSRuntimeMode.Loose;
|
||||||
|
var firstActivation = JSInterop.Setup<bool?>("sbDialog.activate", call => call.Arguments[1] is null);
|
||||||
|
JSInterop.Setup<bool?>("sbDialog.activate", call => call.Arguments[1] is not null).SetResult(true);
|
||||||
|
var cut = Render<DialogHost>();
|
||||||
|
Task<bool> first = null!;
|
||||||
|
await cut.InvokeAsync(() => { first = service.ConfirmAsync("First", "Synthetic confirm"); });
|
||||||
|
cut.WaitForAssertion(() => Assert.Single(firstActivation.Invocations));
|
||||||
|
await cut.InvokeAsync(() => service.Resolve(false));
|
||||||
|
Assert.False(await first);
|
||||||
|
Task<string?> second = null!;
|
||||||
|
await cut.InvokeAsync(() => { second = service.PromptAsync("Second", "Synthetic prompt", "retained"); });
|
||||||
|
cut.WaitForAssertion(() => Assert.Equal("retained", cut.Find("input").GetAttribute("value")));
|
||||||
|
firstActivation.SetResult(false);
|
||||||
|
cut.WaitForAssertion(() => Assert.Equal("Second", service.Current?.Title));
|
||||||
|
await cut.InvokeAsync(() => cut.Find("button.btn-close").Click());
|
||||||
|
Assert.Null(await second);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user