diff --git a/tests/ScadaLink.CentralUI.Tests/Auth/AuthEndpointsCsrfTests.cs b/tests/ScadaLink.CentralUI.Tests/Auth/AuthEndpointsCsrfTests.cs index 1ddafa7..ac49d3a 100644 --- a/tests/ScadaLink.CentralUI.Tests/Auth/AuthEndpointsCsrfTests.cs +++ b/tests/ScadaLink.CentralUI.Tests/Auth/AuthEndpointsCsrfTests.cs @@ -22,7 +22,11 @@ public class AuthEndpointsCsrfTests var builder = WebApplication.CreateBuilder(); builder.Services.AddRouting(); builder.Services.AddAntiforgery(); - var app = builder.Build(); + // Dispose the host: an undisposed WebApplication leaks its config + // PhysicalFileProvider (appsettings reload-watch FileSystemWatcher — a + // process-wide macOS run-loop thread) and a ConsoleLoggerProcessor + // thread, which keep the test host process alive after the run. + using var app = builder.Build(); app.MapAuthEndpoints(); return ((IEndpointRouteBuilder)app).DataSources diff --git a/tests/ScadaLink.CentralUI.Tests/Auth/AuthPingEndpointTests.cs b/tests/ScadaLink.CentralUI.Tests/Auth/AuthPingEndpointTests.cs index 6f7ea54..67cebda 100644 --- a/tests/ScadaLink.CentralUI.Tests/Auth/AuthPingEndpointTests.cs +++ b/tests/ScadaLink.CentralUI.Tests/Auth/AuthPingEndpointTests.cs @@ -23,7 +23,11 @@ public class AuthPingEndpointTests var builder = WebApplication.CreateBuilder(); builder.Services.AddRouting(); builder.Services.AddAntiforgery(); - var app = builder.Build(); + // Dispose the host: an undisposed WebApplication leaks its config + // PhysicalFileProvider (appsettings reload-watch FileSystemWatcher — a + // process-wide macOS run-loop thread) and a ConsoleLoggerProcessor + // thread, which keep the test host process alive after the run. + using var app = builder.Build(); app.MapAuthEndpoints(); return ((IEndpointRouteBuilder)app).DataSources diff --git a/tests/ScadaLink.CentralUI.Tests/Deployment/DebugViewDisposalTests.cs b/tests/ScadaLink.CentralUI.Tests/Deployment/DebugViewDisposalTests.cs index a76767f..4103184 100644 --- a/tests/ScadaLink.CentralUI.Tests/Deployment/DebugViewDisposalTests.cs +++ b/tests/ScadaLink.CentralUI.Tests/Deployment/DebugViewDisposalTests.cs @@ -50,8 +50,11 @@ public class DebugViewDisposalTests : BunitContext Services.AddSingleton(comms); var grpcFactory = new SiteStreamGrpcClientFactory(NullLoggerFactory.Instance); + // An empty throwaway provider — these tests never call StartStreamAsync, + // so the provider is unused. (Services.BuildServiceProvider() would leak + // an undisposed provider.) var debugStream = new DebugStreamService( - comms, Services.BuildServiceProvider(), grpcFactory, + comms, new ServiceCollection().BuildServiceProvider(), grpcFactory, NullLogger.Instance); Services.AddSingleton(debugStream); diff --git a/tests/ScadaLink.CentralUI.Tests/Deployment/DebugViewStreamRaceTests.cs b/tests/ScadaLink.CentralUI.Tests/Deployment/DebugViewStreamRaceTests.cs index f7a8937..a09af20 100644 --- a/tests/ScadaLink.CentralUI.Tests/Deployment/DebugViewStreamRaceTests.cs +++ b/tests/ScadaLink.CentralUI.Tests/Deployment/DebugViewStreamRaceTests.cs @@ -46,8 +46,11 @@ public class DebugViewStreamRaceTests : BunitContext Services.AddSingleton(comms); var grpcFactory = new SiteStreamGrpcClientFactory(NullLoggerFactory.Instance); + // An empty throwaway provider — these tests drive HandleStreamEvent + // directly and never call StartStreamAsync, so the provider is unused. + // (Services.BuildServiceProvider() would leak an undisposed provider.) var debugStream = new DebugStreamService( - comms, Services.BuildServiceProvider(), grpcFactory, + comms, new ServiceCollection().BuildServiceProvider(), grpcFactory, NullLogger.Instance); Services.AddSingleton(debugStream); diff --git a/tests/ScadaLink.CentralUI.Tests/Shared/DiffDialogTests.cs b/tests/ScadaLink.CentralUI.Tests/Shared/DiffDialogTests.cs index 5c742a7..0427133 100644 --- a/tests/ScadaLink.CentralUI.Tests/Shared/DiffDialogTests.cs +++ b/tests/ScadaLink.CentralUI.Tests/Shared/DiffDialogTests.cs @@ -14,16 +14,16 @@ namespace ScadaLink.CentralUI.Tests.Shared; public class DiffDialogTests : BunitContext { /// - /// DiffDialog applies/removes a body scroll-lock class via JS interop on - /// open/close. CentralUI-023 narrowed those catch blocks so they no longer - /// swallow every exception — including bUnit's strict-mode unplanned-call - /// exception. Tests that exercise open/close must therefore register the - /// body-class calls so they do not surface as harness exceptions. + /// DiffDialog applies/removes a body scroll-lock class and focuses the modal + /// via JS interop on open/close. Loose mode auto-completes those void calls + /// so a path that awaits them (e.g. DisposeAsync → + /// TryUnlockBodyAsync) resumes instead of hanging on a never-completed + /// planned invocation, and no strict-mode unplanned-invocation exception + /// surfaces through the narrowed CentralUI-023 catch blocks. /// private void SetupBodyLockInterop() { - JSInterop.SetupVoid("document.body.classList.add", "modal-open"); - JSInterop.SetupVoid("document.body.classList.remove", "modal-open"); + JSInterop.Mode = JSRuntimeMode.Loose; } [Fact]