From 515fdcc6fa741cef28dea66585dff51e3d3e26d0 Mon Sep 17 00:00:00 2001 From: Devin Rousso Date: Fri, 5 Jun 2026 15:30:42 -0600 Subject: [PATCH 1/2] feat(routeWebSocket): add missing `unrouteWebSocket` to match `routeWebSocket` this mirrors the existing `unroute` with it's corresponding `route` --- docs/src/api/class-browsercontext.md | 49 ++++++++++ docs/src/api/class-page.md | 49 ++++++++++ packages/playwright-client/types/types.d.ts | 58 ++++++++++++ .../src/client/browserContext.ts | 10 ++ packages/playwright-core/src/client/page.ts | 10 ++ packages/playwright-core/types/types.d.ts | 58 ++++++++++++ tests/library/route-web-socket.spec.ts | 94 +++++++++++++++++++ 7 files changed, 328 insertions(+) diff --git a/docs/src/api/class-browsercontext.md b/docs/src/api/class-browsercontext.md index 518b2f6059bcf..94165d55b92dd 100644 --- a/docs/src/api/class-browsercontext.md +++ b/docs/src/api/class-browsercontext.md @@ -1618,6 +1618,15 @@ Removes all routes created with [`method: BrowserContext.route`] and [`method: B ### option: BrowserContext.unrouteAll.behavior = %%-unroute-all-options-behavior-%% * since: v1.41 +## async method: BrowserContext.unrouteAllWebSockets +* since: v1.61 + +Removes all routes created with [`method: BrowserContext.routeWebSocket`]. + +:::note +Only affects `WebSocket` created after this call. Any [WebSocketRoute] already passed to a handler will keep working until the underlying `WebSocket` is closed. +::: + ## async method: BrowserContext.unroute * since: v1.8 @@ -1654,6 +1663,46 @@ Optional handler function used to register a routing with [`method: BrowserConte Optional handler function used to register a routing with [`method: BrowserContext.route`]. +## async method: BrowserContext.unrouteWebSocket +* since: v1.61 + +Removes a route created with [`method: BrowserContext.routeWebSocket`]. When [`param: handler`] is not specified, +removes all routes for the [`param: url`]. + +:::note +Only affects `WebSocket` created after this call. Any [WebSocketRoute] already passed to a handler will keep working until the underlying `WebSocket` is closed. +::: + +### param: BrowserContext.unrouteWebSocket.url +* since: v1.61 +* langs: js +- `url` <[string]|[RegExp]|[URLPattern]|[function]\([URL]\):[boolean]> + +A glob pattern, regex pattern, URL pattern, or predicate receiving [URL] used to register a routing with +[`method: BrowserContext.routeWebSocket`]. + +### param: BrowserContext.unrouteWebSocket.url +* since: v1.61 +* langs: python, csharp, java +- `url` <[string]|[RegExp]|[function]\([URL]\):[boolean]> + +A glob pattern, regex pattern, or predicate receiving [URL] used to register a routing with +[`method: BrowserContext.routeWebSocket`]. + +### param: BrowserContext.unrouteWebSocket.handler +* since: v1.61 +* langs: js, python +- `handler` ?<[function]\([WebSocketRoute]\): [Promise|any]> + +Optional handler function used to register a routing with [`method: BrowserContext.routeWebSocket`]. + +### param: BrowserContext.unrouteWebSocket.handler +* since: v1.61 +* langs: csharp, java +- `handler` ?<[function]\([WebSocketRoute]\)> + +Optional handler function used to register a routing with [`method: BrowserContext.routeWebSocket`]. + ## async method: BrowserContext.waitForCondition * since: v1.32 * langs: java diff --git a/docs/src/api/class-page.md b/docs/src/api/class-page.md index 098d83af7275f..6152fd68211b4 100644 --- a/docs/src/api/class-page.md +++ b/docs/src/api/class-page.md @@ -4446,6 +4446,15 @@ Removes all routes created with [`method: Page.route`] and [`method: Page.routeF ### option: Page.unrouteAll.behavior = %%-unroute-all-options-behavior-%% * since: v1.41 +## async method: Page.unrouteAllWebSockets +* since: v1.61 + +Removes all routes created with [`method: Page.routeWebSocket`]. + +:::note +Only affects `WebSocket` created after this call. Any [WebSocketRoute] already passed to a handler will keep working until the underlying `WebSocket` is closed. +::: + ## async method: Page.unroute * since: v1.8 @@ -4480,6 +4489,46 @@ Optional handler function to route the request. Optional handler function to route the request. +## async method: Page.unrouteWebSocket +* since: v1.61 + +Removes a route created with [`method: Page.routeWebSocket`]. When [`param: handler`] is not specified, removes all +routes for the [`param: url`]. + +:::note +Only affects `WebSocket` created after this call. Any [WebSocketRoute] already passed to a handler will keep working until the underlying `WebSocket` is closed. +::: + +### param: Page.unrouteWebSocket.url +* since: v1.61 +* langs: js +- `url` <[string]|[RegExp]|[URLPattern]|[function]\([URL]\):[boolean]> + +A glob pattern, regex pattern, URL pattern, or predicate receiving [URL] used to register a routing with +[`method: Page.routeWebSocket`]. + +### param: Page.unrouteWebSocket.url +* since: v1.61 +* langs: python, csharp, java +- `url` <[string]|[RegExp]|[function]\([URL]\):[boolean]> + +A glob pattern, regex pattern, or predicate receiving [URL] used to register a routing with +[`method: Page.routeWebSocket`]. + +### param: Page.unrouteWebSocket.handler +* since: v1.61 +* langs: js, python +- `handler` ?<[function]\([WebSocketRoute]\): [Promise|any]> + +Optional handler function used to register a routing with [`method: Page.routeWebSocket`]. + +### param: Page.unrouteWebSocket.handler +* since: v1.61 +* langs: csharp, java +- `handler` ?<[function]\([WebSocketRoute]\)> + +Optional handler function used to register a routing with [`method: Page.routeWebSocket`]. + ## method: Page.url * since: v1.8 - returns: <[string]> diff --git a/packages/playwright-client/types/types.d.ts b/packages/playwright-client/types/types.d.ts index d9902ca08932a..ff12f0d574143 100644 --- a/packages/playwright-client/types/types.d.ts +++ b/packages/playwright-client/types/types.d.ts @@ -4764,6 +4764,34 @@ export interface Page { behavior?: "wait"|"ignoreErrors"|"default"; }): Promise; + /** + * Removes all routes created with + * [page.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-page#page-route-web-socket). + * + * **NOTE** Only affects `WebSocket` created after this call. Any + * [WebSocketRoute](https://playwright.dev/docs/api/class-websocketroute) already passed to a handler will keep + * working until the underlying `WebSocket` is closed. + * + */ + unrouteAllWebSockets(): Promise; + + /** + * Removes a route created with + * [page.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-page#page-route-web-socket). When + * [`handler`](https://playwright.dev/docs/api/class-page#page-unroute-web-socket-option-handler) is not specified, + * removes all routes for the [`url`](https://playwright.dev/docs/api/class-page#page-unroute-web-socket-option-url). + * + * **NOTE** Only affects `WebSocket` created after this call. Any + * [WebSocketRoute](https://playwright.dev/docs/api/class-websocketroute) already passed to a handler will keep + * working until the underlying `WebSocket` is closed. + * + * @param url A glob pattern, regex pattern, URL pattern, or predicate receiving [URL] used to register a routing with + * [page.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-page#page-route-web-socket). + * @param handler Optional handler function used to register a routing with + * [page.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-page#page-route-web-socket). + */ + unrouteWebSocket(url: string|RegExp|URLPattern|((url: URL) => boolean), handler?: ((websocketroute: WebSocketRoute) => Promise|any)): Promise; + url(): string; /** @@ -9784,6 +9812,36 @@ export interface BrowserContext { behavior?: "wait"|"ignoreErrors"|"default"; }): Promise; + /** + * Removes all routes created with + * [browserContext.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-browsercontext#browser-context-route-web-socket). + * + * **NOTE** Only affects `WebSocket` created after this call. Any + * [WebSocketRoute](https://playwright.dev/docs/api/class-websocketroute) already passed to a handler will keep + * working until the underlying `WebSocket` is closed. + * + */ + unrouteAllWebSockets(): Promise; + + /** + * Removes a route created with + * [browserContext.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-browsercontext#browser-context-route-web-socket). + * When + * [`handler`](https://playwright.dev/docs/api/class-browsercontext#browser-context-unroute-web-socket-option-handler) + * is not specified, removes all routes for the + * [`url`](https://playwright.dev/docs/api/class-browsercontext#browser-context-unroute-web-socket-option-url). + * + * **NOTE** Only affects `WebSocket` created after this call. Any + * [WebSocketRoute](https://playwright.dev/docs/api/class-websocketroute) already passed to a handler will keep + * working until the underlying `WebSocket` is closed. + * + * @param url A glob pattern, regex pattern, URL pattern, or predicate receiving [URL] used to register a routing with + * [browserContext.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-browsercontext#browser-context-route-web-socket). + * @param handler Optional handler function used to register a routing with + * [browserContext.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-browsercontext#browser-context-route-web-socket). + */ + unrouteWebSocket(url: string|RegExp|URLPattern|((url: URL) => boolean), handler?: ((websocketroute: WebSocketRoute) => Promise|any)): Promise; + /** * This event is not emitted. */ diff --git a/packages/playwright-core/src/client/browserContext.ts b/packages/playwright-core/src/client/browserContext.ts index ff4b4241de878..8c2f21eff779b 100644 --- a/packages/playwright-core/src/client/browserContext.ts +++ b/packages/playwright-core/src/client/browserContext.ts @@ -408,6 +408,11 @@ export class BrowserContext extends ChannelOwner this._disposeHarRouters(); } + async unrouteAllWebSockets(): Promise { + this._webSocketRoutes = []; + await this._updateWebSocketInterceptionPatterns({ title: 'Unroute WebSockets' }); + } + async unroute(url: URLMatch, handler?: network.RouteHandlerCallback): Promise { const removed = []; const remaining = []; @@ -420,6 +425,11 @@ export class BrowserContext extends ChannelOwner await this._unrouteInternal(removed, remaining, 'default'); } + async unrouteWebSocket(url: URLMatch, handler?: network.WebSocketRouteHandlerCallback): Promise { + this._webSocketRoutes = this._webSocketRoutes.filter(route => !urlMatchesEqual(route.url, url) || (handler && route.handler !== handler)); + await this._updateWebSocketInterceptionPatterns({ title: 'Unroute WebSockets' }); + } + private async _unrouteInternal(removed: network.RouteHandler[], remaining: network.RouteHandler[], behavior?: 'wait'|'ignoreErrors'|'default'): Promise { this._routes = remaining; if (behavior && behavior !== 'default') { diff --git a/packages/playwright-core/src/client/page.ts b/packages/playwright-core/src/client/page.ts index b45b623083a7f..3eb89ed44a095 100644 --- a/packages/playwright-core/src/client/page.ts +++ b/packages/playwright-core/src/client/page.ts @@ -568,6 +568,11 @@ export class Page extends ChannelOwner implements api.Page this._disposeHarRouters(); } + async unrouteAllWebSockets(): Promise { + this._webSocketRoutes = []; + await this._updateWebSocketInterceptionPatterns({ title: 'Unroute WebSockets' }); + } + async unroute(url: URLMatch, handler?: RouteHandlerCallback): Promise { const removed = []; const remaining = []; @@ -580,6 +585,11 @@ export class Page extends ChannelOwner implements api.Page await this._unrouteInternal(removed, remaining, 'default'); } + async unrouteWebSocket(url: URLMatch, handler?: WebSocketRouteHandlerCallback): Promise { + this._webSocketRoutes = this._webSocketRoutes.filter(route => !urlMatchesEqual(route.url, url) || (handler && route.handler !== handler)); + await this._updateWebSocketInterceptionPatterns({ title: 'Unroute WebSockets' }); + } + private async _unrouteInternal(removed: RouteHandler[], remaining: RouteHandler[], behavior?: 'wait'|'ignoreErrors'|'default'): Promise { this._routes = remaining; if (behavior && behavior !== 'default') { diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index d9902ca08932a..ff12f0d574143 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -4764,6 +4764,34 @@ export interface Page { behavior?: "wait"|"ignoreErrors"|"default"; }): Promise; + /** + * Removes all routes created with + * [page.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-page#page-route-web-socket). + * + * **NOTE** Only affects `WebSocket` created after this call. Any + * [WebSocketRoute](https://playwright.dev/docs/api/class-websocketroute) already passed to a handler will keep + * working until the underlying `WebSocket` is closed. + * + */ + unrouteAllWebSockets(): Promise; + + /** + * Removes a route created with + * [page.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-page#page-route-web-socket). When + * [`handler`](https://playwright.dev/docs/api/class-page#page-unroute-web-socket-option-handler) is not specified, + * removes all routes for the [`url`](https://playwright.dev/docs/api/class-page#page-unroute-web-socket-option-url). + * + * **NOTE** Only affects `WebSocket` created after this call. Any + * [WebSocketRoute](https://playwright.dev/docs/api/class-websocketroute) already passed to a handler will keep + * working until the underlying `WebSocket` is closed. + * + * @param url A glob pattern, regex pattern, URL pattern, or predicate receiving [URL] used to register a routing with + * [page.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-page#page-route-web-socket). + * @param handler Optional handler function used to register a routing with + * [page.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-page#page-route-web-socket). + */ + unrouteWebSocket(url: string|RegExp|URLPattern|((url: URL) => boolean), handler?: ((websocketroute: WebSocketRoute) => Promise|any)): Promise; + url(): string; /** @@ -9784,6 +9812,36 @@ export interface BrowserContext { behavior?: "wait"|"ignoreErrors"|"default"; }): Promise; + /** + * Removes all routes created with + * [browserContext.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-browsercontext#browser-context-route-web-socket). + * + * **NOTE** Only affects `WebSocket` created after this call. Any + * [WebSocketRoute](https://playwright.dev/docs/api/class-websocketroute) already passed to a handler will keep + * working until the underlying `WebSocket` is closed. + * + */ + unrouteAllWebSockets(): Promise; + + /** + * Removes a route created with + * [browserContext.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-browsercontext#browser-context-route-web-socket). + * When + * [`handler`](https://playwright.dev/docs/api/class-browsercontext#browser-context-unroute-web-socket-option-handler) + * is not specified, removes all routes for the + * [`url`](https://playwright.dev/docs/api/class-browsercontext#browser-context-unroute-web-socket-option-url). + * + * **NOTE** Only affects `WebSocket` created after this call. Any + * [WebSocketRoute](https://playwright.dev/docs/api/class-websocketroute) already passed to a handler will keep + * working until the underlying `WebSocket` is closed. + * + * @param url A glob pattern, regex pattern, URL pattern, or predicate receiving [URL] used to register a routing with + * [browserContext.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-browsercontext#browser-context-route-web-socket). + * @param handler Optional handler function used to register a routing with + * [browserContext.routeWebSocket(url, handler)](https://playwright.dev/docs/api/class-browsercontext#browser-context-route-web-socket). + */ + unrouteWebSocket(url: string|RegExp|URLPattern|((url: URL) => boolean), handler?: ((websocketroute: WebSocketRoute) => Promise|any)): Promise; + /** * This event is not emitted. */ diff --git a/tests/library/route-web-socket.spec.ts b/tests/library/route-web-socket.spec.ts index d968889490b4a..960da58445bf4 100644 --- a/tests/library/route-web-socket.spec.ts +++ b/tests/library/route-web-socket.spec.ts @@ -679,3 +679,97 @@ test('should expose protocols on server-side route', async ({ page, server }) => expect(pageRoute.protocols()).toEqual(['chat.v2', 'chat.v1']); expect(serverRoute.protocols()).toEqual(['chat.v2', 'chat.v1']); }); + +test('unrouteWebSocket should filter routes by url, handler, and scope', async ({ page, server }) => { + const ws1 = (ws: WebSocketRoute) => ws.onMessage(() => ws.send('ws1')); + const ws2 = (ws: WebSocketRoute) => ws.onMessage(() => ws.send('ws2')); + await page.routeWebSocket(/.*\/ws$/, ws1); + await page.routeWebSocket(/.*\/ws$/, ws2); + await page.context().routeWebSocket(/.*/, ws => ws.onMessage(() => ws.send('context'))); + + // ws2 was registered last (unshifted), so the page-level ws2 wins. + await setupWS(page, server, 'blob'); + await page.evaluate(async () => { + await window.wsOpened; + window.ws.send('req'); + }); + await expect.poll(() => page.evaluate(() => window.log)).toEqual([ + 'open', + `message: data=ws2 origin=ws://${server.HOST} lastEventId=`, + ]); + + // No-op when nothing matches. + await page.unrouteWebSocket(/.*\/never$/); + await setupWS(page, server, 'blob'); + await page.evaluate(async () => { + await window.wsOpened; + window.ws.send('req'); + }); + await expect.poll(() => page.evaluate(() => window.log)).toEqual([ + 'open', + `message: data=ws2 origin=ws://${server.HOST} lastEventId=`, + ]); + + // Removing only ws2 lets ws1 win for new WebSockets. + await page.unrouteWebSocket(/.*\/ws$/, ws2); + await setupWS(page, server, 'blob'); + await page.evaluate(async () => { + await window.wsOpened; + window.ws.send('req'); + }); + await expect.poll(() => page.evaluate(() => window.log)).toEqual([ + 'open', + `message: data=ws1 origin=ws://${server.HOST} lastEventId=`, + ]); + + // Removing without a handler arg clears all page handlers for that url; + // the context-level fallback takes over. + await page.unrouteWebSocket(/.*\/ws$/); + await setupWS(page, server, 'blob'); + await page.evaluate(async () => { + await window.wsOpened; + window.ws.send('req'); + }); + await expect.poll(() => page.evaluate(() => window.log)).toEqual([ + 'open', + `message: data=context origin=ws://${server.HOST} lastEventId=`, + ]); + + // Re-register a page handler and remove all context routes — page still wins. + await page.routeWebSocket(/.*\/ws$/, ws1); + await page.context().unrouteAllWebSockets(); + await setupWS(page, server, 'blob'); + await page.evaluate(async () => { + await window.wsOpened; + window.ws.send('req'); + }); + await expect.poll(() => page.evaluate(() => window.log)).toEqual([ + 'open', + `message: data=ws1 origin=ws://${server.HOST} lastEventId=`, + ]); + + // After unrouteAllWebSockets, the already-active WebSocket keeps its route. + await page.unrouteAllWebSockets(); + await page.evaluate(() => window.ws.send('req')); + await expect.poll(() => page.evaluate(() => window.log)).toEqual([ + 'open', + `message: data=ws1 origin=ws://${server.HOST} lastEventId=`, + `message: data=ws1 origin=ws://${server.HOST} lastEventId=`, + ]); + + // New WebSockets fall through to the real server. If unroute had not taken + // effect, the page-side mock would reply with 'ws1' and the real server + // would never observe the connection. + const wsPromise = server.waitForWebSocket(); + await setupWS(page, server, 'blob'); + const realWs = await wsPromise; + realWs.on('message', message => realWs.send(`real:${message}`)); + await page.evaluate(async () => { + await window.wsOpened; + window.ws.send('req'); + }); + await expect.poll(() => page.evaluate(() => window.log)).toEqual([ + 'open', + `message: data=real:req origin=ws://${server.HOST} lastEventId=`, + ]); +}); From fc2828a75e98f9d150f22b53b2d6e5fa22d47c2d Mon Sep 17 00:00:00 2001 From: Devin Rousso Date: Fri, 5 Jun 2026 16:28:48 -0600 Subject: [PATCH 2/2] feat(routeWebSocket): return a `Disposable` to match `route` --- docs/src/api/class-browsercontext.md | 5 ++++- docs/src/api/class-page.md | 5 ++++- packages/playwright-client/types/types.d.ts | 12 ++++++------ .../playwright-core/src/client/browserContext.ts | 3 ++- packages/playwright-core/src/client/page.ts | 3 ++- packages/playwright-core/types/types.d.ts | 12 ++++++------ 6 files changed, 24 insertions(+), 16 deletions(-) diff --git a/docs/src/api/class-browsercontext.md b/docs/src/api/class-browsercontext.md index 94165d55b92dd..6be49edc7bb97 100644 --- a/docs/src/api/class-browsercontext.md +++ b/docs/src/api/class-browsercontext.md @@ -1310,10 +1310,13 @@ Optional setting to control resource content management. If `attach` is specifie ## async method: BrowserContext.routeWebSocket * since: v1.48 +- returns: <[Disposable]> This method allows to modify websocket connections that are made by any page in the browser context. -Note that only `WebSocket`s created after this method was called will be routed. It is recommended to call this method before creating any pages. +:::note +Only affects `WebSocket` created after this method was called will be routed. It is recommended to call this method before creating any pages. +::: **Usage** diff --git a/docs/src/api/class-page.md b/docs/src/api/class-page.md index 6152fd68211b4..c857d7505d69b 100644 --- a/docs/src/api/class-page.md +++ b/docs/src/api/class-page.md @@ -3811,10 +3811,13 @@ Optional setting to control resource content management. If `attach` is specifie ## async method: Page.routeWebSocket * since: v1.48 +- returns: <[Disposable]> This method allows to modify websocket connections that are made by the page. -Note that only `WebSocket`s created after this method was called will be routed. It is recommended to call this method before navigating the page. +:::note +Only affects `WebSocket` created after this method was called will be routed. It is recommended to call this method before navigating the page. +::: **Usage** diff --git a/packages/playwright-client/types/types.d.ts b/packages/playwright-client/types/types.d.ts index ff12f0d574143..e31d14962fb5e 100644 --- a/packages/playwright-client/types/types.d.ts +++ b/packages/playwright-client/types/types.d.ts @@ -4129,8 +4129,8 @@ export interface Page { /** * This method allows to modify websocket connections that are made by the page. * - * Note that only `WebSocket`s created after this method was called will be routed. It is recommended to call this - * method before navigating the page. + * **NOTE** Only affects `WebSocket` created after this method was called will be routed. It is recommended to call + * this method before navigating the page. * * **Usage** * @@ -4150,7 +4150,7 @@ export interface Page { * [`baseURL`](https://playwright.dev/docs/api/class-browser#browser-new-context-option-base-url) context option. * @param handler Handler function to route the WebSocket. */ - routeWebSocket(url: string|RegExp|URLPattern|((url: URL) => boolean), handler: ((websocketroute: WebSocketRoute) => Promise|any)): Promise; + routeWebSocket(url: string|RegExp|URLPattern|((url: URL) => boolean), handler: ((websocketroute: WebSocketRoute) => Promise|any)): Promise; /** * Returns the buffer with the captured screenshot. @@ -9533,8 +9533,8 @@ export interface BrowserContext { /** * This method allows to modify websocket connections that are made by any page in the browser context. * - * Note that only `WebSocket`s created after this method was called will be routed. It is recommended to call this - * method before creating any pages. + * **NOTE** Only affects `WebSocket` created after this method was called will be routed. It is recommended to call + * this method before creating any pages. * * **Usage** * @@ -9556,7 +9556,7 @@ export interface BrowserContext { * [`baseURL`](https://playwright.dev/docs/api/class-browser#browser-new-context-option-base-url) context option. * @param handler Handler function to route the WebSocket. */ - routeWebSocket(url: string|RegExp|((url: URL) => boolean), handler: ((websocketroute: WebSocketRoute) => Promise|any)): Promise; + routeWebSocket(url: string|RegExp|((url: URL) => boolean), handler: ((websocketroute: WebSocketRoute) => Promise|any)): Promise; /** * **NOTE** Service workers are only supported on Chromium-based browsers. diff --git a/packages/playwright-core/src/client/browserContext.ts b/packages/playwright-core/src/client/browserContext.ts index 8c2f21eff779b..9393968d27c2e 100644 --- a/packages/playwright-core/src/client/browserContext.ts +++ b/packages/playwright-core/src/client/browserContext.ts @@ -380,9 +380,10 @@ export class BrowserContext extends ChannelOwner return new DisposableStub(() => this.unroute(url, handler)); } - async routeWebSocket(url: URLMatch, handler: network.WebSocketRouteHandlerCallback): Promise { + async routeWebSocket(url: URLMatch, handler: network.WebSocketRouteHandlerCallback): Promise { this._webSocketRoutes.unshift(new network.WebSocketRouteHandler(this._options.baseURL, url, handler)); await this._updateWebSocketInterceptionPatterns({ title: 'Route WebSockets' }); + return new DisposableStub(() => this.unrouteWebSocket(url, handler)); } async routeFromHAR(har: string, options: { url?: string | RegExp, notFound?: 'abort' | 'fallback', update?: boolean, updateContent?: 'attach' | 'embed', updateMode?: 'minimal' | 'full' } = {}): Promise { diff --git a/packages/playwright-core/src/client/page.ts b/packages/playwright-core/src/client/page.ts index 3eb89ed44a095..99d2eb6a1afae 100644 --- a/packages/playwright-core/src/client/page.ts +++ b/packages/playwright-core/src/client/page.ts @@ -553,9 +553,10 @@ export class Page extends ChannelOwner implements api.Page await harRouter.addPageRoute(this); } - async routeWebSocket(url: URLMatch, handler: WebSocketRouteHandlerCallback): Promise { + async routeWebSocket(url: URLMatch, handler: WebSocketRouteHandlerCallback): Promise { this._webSocketRoutes.unshift(new WebSocketRouteHandler(this._browserContext._options.baseURL, url, handler)); await this._updateWebSocketInterceptionPatterns({ title: 'Route WebSockets' }); + return new DisposableStub(() => this.unrouteWebSocket(url, handler)); } private _disposeHarRouters() { diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index ff12f0d574143..e31d14962fb5e 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -4129,8 +4129,8 @@ export interface Page { /** * This method allows to modify websocket connections that are made by the page. * - * Note that only `WebSocket`s created after this method was called will be routed. It is recommended to call this - * method before navigating the page. + * **NOTE** Only affects `WebSocket` created after this method was called will be routed. It is recommended to call + * this method before navigating the page. * * **Usage** * @@ -4150,7 +4150,7 @@ export interface Page { * [`baseURL`](https://playwright.dev/docs/api/class-browser#browser-new-context-option-base-url) context option. * @param handler Handler function to route the WebSocket. */ - routeWebSocket(url: string|RegExp|URLPattern|((url: URL) => boolean), handler: ((websocketroute: WebSocketRoute) => Promise|any)): Promise; + routeWebSocket(url: string|RegExp|URLPattern|((url: URL) => boolean), handler: ((websocketroute: WebSocketRoute) => Promise|any)): Promise; /** * Returns the buffer with the captured screenshot. @@ -9533,8 +9533,8 @@ export interface BrowserContext { /** * This method allows to modify websocket connections that are made by any page in the browser context. * - * Note that only `WebSocket`s created after this method was called will be routed. It is recommended to call this - * method before creating any pages. + * **NOTE** Only affects `WebSocket` created after this method was called will be routed. It is recommended to call + * this method before creating any pages. * * **Usage** * @@ -9556,7 +9556,7 @@ export interface BrowserContext { * [`baseURL`](https://playwright.dev/docs/api/class-browser#browser-new-context-option-base-url) context option. * @param handler Handler function to route the WebSocket. */ - routeWebSocket(url: string|RegExp|((url: URL) => boolean), handler: ((websocketroute: WebSocketRoute) => Promise|any)): Promise; + routeWebSocket(url: string|RegExp|((url: URL) => boolean), handler: ((websocketroute: WebSocketRoute) => Promise|any)): Promise; /** * **NOTE** Service workers are only supported on Chromium-based browsers.