diff --git a/src/Playwright.Tests/PageRouteWebSocketTests.cs b/src/Playwright.Tests/PageRouteWebSocketTests.cs index 0dd3b9946..7f0bce4ba 100644 --- a/src/Playwright.Tests/PageRouteWebSocketTests.cs +++ b/src/Playwright.Tests/PageRouteWebSocketTests.cs @@ -287,6 +287,51 @@ await AssertAreEqualWithRetriesAsync(() => Page.EvaluateAsync("() => w ]); } + [PlaywrightTest("route-web-socket.spec.ts", "should emit close upon frame navigation")] + public async Task ShouldEmitCloseUponFrameNavigation() + { + var tcs = new TaskCompletionSource(); + await Page.RouteWebSocketAsync(new Regex(".*"), ws => + { + ws.ConnectToServer(); + tcs.SetResult(ws); + }); + + await SetupWS(Page, Server.Port, "blob"); + + var route = await tcs.Task; + route.Send("hello"); + + await AssertAreEqualWithRetriesAsync(() => Page.EvaluateAsync("() => window.log"), new[] + { + "open", + $"message: data=hello origin=ws://localhost:{Server.Port} lastEventId=", + }); + + var closedTcs = new TaskCompletionSource(); + route.OnClose((code, reason) => closedTcs.TrySetResult()); + await Page.GotoAsync(Server.EmptyPage); + await closedTcs.Task; + } + + [PlaywrightTest("route-web-socket.spec.ts", "should not throw after page closure")] + public async Task ShouldNotThrowAfterPageClosure() + { + var tcs = new TaskCompletionSource(); + await Page.RouteWebSocketAsync(new Regex(".*"), ws => + { + ws.ConnectToServer(); + tcs.SetResult(ws); + }); + + await SetupWS(Page, Server.Port, "blob"); + + var route = await tcs.Task; + var closeTask = Page.CloseAsync(); + route.Send("hello"); + await closeTask; + } + [PlaywrightTest("page-route-web-socket.spec.ts", "should work with baseURL")] public async Task ShouldWorkWithBaseURL() { diff --git a/src/Playwright/Core/WebSocketRoute.cs b/src/Playwright/Core/WebSocketRoute.cs index 6896b299d..8532f5264 100644 --- a/src/Playwright/Core/WebSocketRoute.cs +++ b/src/Playwright/Core/WebSocketRoute.cs @@ -90,35 +90,43 @@ internal override void OnMessage(string method, JsonElement serverParams) } break; case "closePage": - if (_onPageClose != null) { - _onPageClose(serverParams.GetProperty("code").GetInt32(), serverParams.GetProperty("reason").GetString()); - } - else - { - SendMessageToServerAsync("closeServer", new Dictionary + int? code = serverParams.TryGetProperty("code", out var codeElement) && codeElement.ValueKind == JsonValueKind.Number ? codeElement.GetInt32() : null; + string? reason = serverParams.TryGetProperty("reason", out var reasonElement) && reasonElement.ValueKind == JsonValueKind.String ? reasonElement.GetString() : null; + if (_onPageClose != null) { - ["code"] = serverParams.GetProperty("code").GetInt32(), - ["reason"] = serverParams.GetProperty("reason").GetString(), - ["wasClean"] = serverParams.GetProperty("wasClean").GetBoolean(), - }).IgnoreException(); + _onPageClose(code, reason); + } + else + { + SendMessageToServerAsync("closeServer", new Dictionary + { + ["code"] = code, + ["reason"] = reason, + ["wasClean"] = serverParams.GetProperty("wasClean").GetBoolean(), + }).IgnoreException(); + } + break; } - break; case "closeServer": - if (_onServerClose != null) { - _onServerClose(serverParams.GetProperty("code").GetInt32(), serverParams.GetProperty("reason").GetString()); - } - else - { - SendMessageToServerAsync("closePage", new Dictionary + int? code = serverParams.TryGetProperty("code", out var codeElement) && codeElement.ValueKind == JsonValueKind.Number ? codeElement.GetInt32() : null; + string? reason = serverParams.TryGetProperty("reason", out var reasonElement) && reasonElement.ValueKind == JsonValueKind.String ? reasonElement.GetString() : null; + if (_onServerClose != null) { - ["code"] = serverParams.GetProperty("code").GetInt32(), - ["reason"] = serverParams.GetProperty("reason").GetString(), - ["wasClean"] = serverParams.GetProperty("wasClean").GetBoolean(), - }).IgnoreException(); + _onServerClose(code, reason); + } + else + { + SendMessageToServerAsync("closePage", new Dictionary + { + ["code"] = code, + ["reason"] = reason, + ["wasClean"] = serverParams.GetProperty("wasClean").GetBoolean(), + }).IgnoreException(); + } + break; } - break; } }