From f43436218ac932f5a9613fb9fd7b24447a06ea43 Mon Sep 17 00:00:00 2001 From: Jaap-Jan de Wit | DodoTech Date: Fri, 16 Oct 2026 13:17:01 +0200 Subject: [PATCH] Tests: wait for a dropped session's forwards to stop, not just for the tab to go dead WhenTheSessionEnds_ItsForwardsSayTheyWentWithIt failed once under a full run. Ended clears IsLive and then tells each forward its session is over, in one call. The app's dispatcher never splits that, but the harness's post runs it on the fake shell's thread, so the test's poll on !IsLive could return between the two and find the forwards still listening. The test now also waits until every forward says "Stopped with the session.", the last thing SessionEnded sets. A 300 ms sleep injected between the two steps fails the old test and passes the new one; the full App.Tests suite passed three runs in a row. --- tests/DodoSSH.Client.App.Tests/ShellFlowTests.Forwards.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/DodoSSH.Client.App.Tests/ShellFlowTests.Forwards.cs b/tests/DodoSSH.Client.App.Tests/ShellFlowTests.Forwards.cs index 2caa3ef..af580a6 100644 --- a/tests/DodoSSH.Client.App.Tests/ShellFlowTests.Forwards.cs +++ b/tests/DodoSSH.Client.App.Tests/ShellFlowTests.Forwards.cs @@ -114,6 +114,13 @@ public sealed partial class ShellFlowTests await EventuallyAsync(() => !tab.IsLive, "the dropped shell should have ended the session"); + // Waited for in its own right rather than taken as read from IsLive. Ended clears IsLive and then + // ends the forwards in the same dispatcher turn, which the app's UI thread never splits — but this + // harness's post runs the ending on the fake shell's thread, so a poll from here can land between. + await EventuallyAsync( + () => tab.Forwards.All(row => row.Detail == "Stopped with the session."), + "the session's end should have reached its forwards"); + tab.Forwards.ShouldAllBe(row => row.State == PortForwardState.Stopped); tab.Forwards.ShouldAllBe(row => row.Detail == "Stopped with the session."); tab.Forwards.ShouldAllBe(row => !row.CanToggle);