diff --git a/dotnet/versioned_docs/version-stable/api/class-websocketroute.mdx b/dotnet/versioned_docs/version-stable/api/class-websocketroute.mdx index 632be16478..886177b208 100644 --- a/dotnet/versioned_docs/version-stable/api/class-websocketroute.mdx +++ b/dotnet/versioned_docs/version-stable/api/class-websocketroute.mdx @@ -14,7 +14,7 @@ Whenever a [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSoc By default, the routed WebSocket will not connect to the server. This way, you can mock entire communcation over the WebSocket. Here is an example that responds to a `"request"` with a `"response"`. ```csharp -await page.RouteWebSocketAsync("/ws", ws => { +await page.RouteWebSocketAsync("wss://example.com/ws", ws => { ws.OnMessage(message => { if (message == "request") ws.Send("response"); @@ -24,6 +24,23 @@ await page.RouteWebSocketAsync("/ws", ws => { Since we do not call [WebSocketRoute.ConnectToServer](/api/class-websocketroute.mdx#web-socket-route-connect-to-server) inside the WebSocket route handler, Playwright assumes that WebSocket will be mocked, and opens the WebSocket inside the page automatically. +Here is another example that handles JSON messages: + +```csharp +await page.RouteWebSocketAsync("wss://example.com/ws", ws => { + ws.OnMessage(message => { + using var jsonDoc = JsonDocument.Parse(message); + JsonElement root = jsonDoc.RootElement; + if (root.TryGetProperty("request", out JsonElement requestElement) && requestElement.GetString() == "question") + { + var response = new Dictionary { ["response"] = "answer" }; + string jsonResponse = JsonSerializer.Serialize(response); + ws.Send(jsonResponse); + } + }); +}); +``` + **Intercepting** Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block them. Calling [WebSocketRoute.ConnectToServer](/api/class-websocketroute.mdx#web-socket-route-connect-to-server) returns a server-side `WebSocketRoute` instance that you can send messages to, or handle incoming messages. @@ -44,11 +61,11 @@ await page.RouteWebSocketAsync("/ws", ws => { After connecting to the server, all **messages are forwarded** between the page and the server by default. -However, if you call [WebSocketRoute.OnMessageAsync()](/api/class-websocketroute.mdx#web-socket-route-on-message) on the original route, messages from the page to the server **will not be forwarded** anymore, but should instead be handled by the [handler](/api/class-websocketroute.mdx#web-socket-route-on-message-option-handler). +However, if you call [WebSocketRoute.OnMessage()](/api/class-websocketroute.mdx#web-socket-route-on-message) on the original route, messages from the page to the server **will not be forwarded** anymore, but should instead be handled by the [handler](/api/class-websocketroute.mdx#web-socket-route-on-message-option-handler). -Similarly, calling [WebSocketRoute.OnMessageAsync()](/api/class-websocketroute.mdx#web-socket-route-on-message) on the server-side WebSocket will **stop forwarding messages** from the server to the page, and [handler](/api/class-websocketroute.mdx#web-socket-route-on-message-option-handler) should take care of them. +Similarly, calling [WebSocketRoute.OnMessage()](/api/class-websocketroute.mdx#web-socket-route-on-message) on the server-side WebSocket will **stop forwarding messages** from the server to the page, and [handler](/api/class-websocketroute.mdx#web-socket-route-on-message-option-handler) should take care of them. -The following example blocks some messages in both directions. Since it calls [WebSocketRoute.OnMessageAsync()](/api/class-websocketroute.mdx#web-socket-route-on-message) in both directions, there is no automatic forwarding at all. +The following example blocks some messages in both directions. Since it calls [WebSocketRoute.OnMessage()](/api/class-websocketroute.mdx#web-socket-route-on-message) in both directions, there is no automatic forwarding at all. ```csharp await page.RouteWebSocketAsync("/ws", ws => { @@ -102,8 +119,8 @@ await WebSocketRoute.CloseAsync(options); By default, routed WebSocket does not connect to the server, so you can mock entire WebSocket communication. This method connects to the actual WebSocket server, and returns the server-side [WebSocketRoute] instance, giving the ability to send and receive messages from the server. Once connected to the server: -* Messages received from the server will be **automatically forwarded** to the WebSocket in the page, unless [WebSocketRoute.OnMessageAsync()](/api/class-websocketroute.mdx#web-socket-route-on-message) is called on the server-side `WebSocketRoute`. -* Messages sent by the [`WebSocket.send()`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send) call in the page will be **automatically forwarded** to the server, unless [WebSocketRoute.OnMessageAsync()](/api/class-websocketroute.mdx#web-socket-route-on-message) is called on the original `WebSocketRoute`. +* Messages received from the server will be **automatically forwarded** to the WebSocket in the page, unless [WebSocketRoute.OnMessage()](/api/class-websocketroute.mdx#web-socket-route-on-message) is called on the server-side `WebSocketRoute`. +* Messages sent by the [`WebSocket.send()`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send) call in the page will be **automatically forwarded** to the server, unless [WebSocketRoute.OnMessage()](/api/class-websocketroute.mdx#web-socket-route-on-message) is called on the original `WebSocketRoute`. See examples at the top for more details. @@ -133,15 +150,15 @@ WebSocketRoute.OnClose(handler); ``` **Arguments** -- `handler` [Action]<[number]?># +- `handler` Action<int?, string># Function that will handle WebSocket closure. Received an optional [close code](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code) and an optional [close reason](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason). --- -### OnMessageAsync {#web-socket-route-on-message} +### OnMessage {#web-socket-route-on-message} -Added in: v1.48webSocketRoute.OnMessageAsync +Added in: v1.48webSocketRoute.OnMessage This method allows to handle messages that are sent by the WebSocket, either from the page or from the server. @@ -154,7 +171,7 @@ Calling this method again will override the handler with a new one. **Usage** ```csharp -await WebSocketRoute.OnMessageAsync(handler); +WebSocketRoute.OnMessage(handler); ``` **Arguments** @@ -162,9 +179,6 @@ await WebSocketRoute.OnMessageAsync(handler); Function that will handle messages. -**Returns** -- [void]# - --- ### Send {#web-socket-route-send} diff --git a/dotnet/versioned_docs/version-stable/mock.mdx b/dotnet/versioned_docs/version-stable/mock.mdx index ac0112feb0..09e577b1ae 100644 --- a/dotnet/versioned_docs/version-stable/mock.mdx +++ b/dotnet/versioned_docs/version-stable/mock.mdx @@ -153,6 +153,35 @@ pwsh bin/Debug/netX/playwright.ps1 open --save-har=example.har --save-har-glob=" Read more about [advanced networking](./network.mdx). +## Mock WebSockets + +The following code will intercept WebSocket connections and mock entire communcation over the WebSocket, instead of connecting to the server. This example responds to a `"request"` with a `"response"`. + +```csharp +await page.RouteWebSocketAsync("wss://example.com/ws", ws => { + ws.OnMessage(message => { + if (message == "request") + ws.Send("response"); + }); +}); +``` + +Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block them. Here is an example that modifies some of the messages sent by the page to the server, and leaves the rest unmodified. + +```csharp +await page.RouteWebSocketAsync("wss://example.com/ws", ws => { + var server = ws.ConnectToServer(); + ws.OnMessage(message => { + if (message == "request") + server.Send("request2"); + else + server.Send(message); + }); +}); +``` + +For more details, see [WebSocketRoute]. + [Accessibility]: /api/class-accessibility.mdx "Accessibility" [APIRequest]: /api/class-apirequest.mdx "APIRequest" diff --git a/dotnet/versioned_docs/version-stable/network.mdx b/dotnet/versioned_docs/version-stable/network.mdx index 37dbc34cbc..1dc3f2b45f 100644 --- a/dotnet/versioned_docs/version-stable/network.mdx +++ b/dotnet/versioned_docs/version-stable/network.mdx @@ -12,7 +12,7 @@ Playwright provides APIs to **monitor** and **modify** browser network traffic, ## Mock APIs -Check out our [API mocking guide](./mock.mdx) to learn more on how to +Check out our [API mocking guide](./mock.mdx) to learn more on how to - mock API requests and never hit the API - perform the API request and modify the response - use HAR files to mock network requests. @@ -201,7 +201,9 @@ Important notes: ## WebSockets -Playwright supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) inspection out of the box. Every time a WebSocket is created, the [Page.WebSocket](/api/class-page.mdx#page-event-web-socket) event is fired. This event contains the [WebSocket] instance for further web socket frames inspection: +Playwright supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) inspection, mocking and modifying out of the box. See our [API mocking guide](./mock.mdx#mock-websockets) to learn how to mock WebSockets. + +Every time a WebSocket is created, the [Page.WebSocket](/api/class-page.mdx#page-event-web-socket) event is fired. This event contains the [WebSocket] instance for further web socket frames inspection: ```csharp page.WebSocket += (_, ws) => diff --git a/java/versioned_docs/version-stable/api/class-websocketroute.mdx b/java/versioned_docs/version-stable/api/class-websocketroute.mdx index 682e406858..16a504757c 100644 --- a/java/versioned_docs/version-stable/api/class-websocketroute.mdx +++ b/java/versioned_docs/version-stable/api/class-websocketroute.mdx @@ -14,7 +14,7 @@ Whenever a [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSoc By default, the routed WebSocket will not connect to the server. This way, you can mock entire communcation over the WebSocket. Here is an example that responds to a `"request"` with a `"response"`. ```java -page.routeWebSocket("/ws", ws -> { +page.routeWebSocket("wss://example.com/ws", ws -> { ws.onMessage(message -> { if ("request".equals(message)) ws.send("response"); @@ -24,6 +24,21 @@ page.routeWebSocket("/ws", ws -> { Since we do not call [WebSocketRoute.connectToServer()](/api/class-websocketroute.mdx#web-socket-route-connect-to-server) inside the WebSocket route handler, Playwright assumes that WebSocket will be mocked, and opens the WebSocket inside the page automatically. +Here is another example that handles JSON messages: + +```java +page.routeWebSocket("wss://example.com/ws", ws -> { + ws.onMessage(message -> { + JsonObject json = new JsonParser().parse(message).getAsJsonObject(); + if ("question".equals(json.get("request").getAsString())) { + Map result = new HashMap(); + result.put("response", "answer"); + ws.send(gson.toJson(result)); + } + }); +}); +``` + **Intercepting** Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block them. Calling [WebSocketRoute.connectToServer()](/api/class-websocketroute.mdx#web-socket-route-connect-to-server) returns a server-side `WebSocketRoute` instance that you can send messages to, or handle incoming messages. @@ -134,7 +149,7 @@ WebSocketRoute.onClose(handler); ``` **Arguments** -- `handler` [Consumer]<[null] | [number]># +- `handler` [Consumer]<[null] | [int]># Function that will handle WebSocket closure. Received an optional [close code](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code) and an optional [close reason](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason). @@ -163,9 +178,6 @@ WebSocketRoute.onMessage(handler); Function that will handle messages. -**Returns** -- [void]# - --- ### send {#web-socket-route-send} diff --git a/java/versioned_docs/version-stable/mock.mdx b/java/versioned_docs/version-stable/mock.mdx index 49e03926e9..a43140eaf8 100644 --- a/java/versioned_docs/version-stable/mock.mdx +++ b/java/versioned_docs/version-stable/mock.mdx @@ -149,6 +149,35 @@ mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="op Read more about [advanced networking](./network.mdx). +## Mock WebSockets + +The following code will intercept WebSocket connections and mock entire communcation over the WebSocket, instead of connecting to the server. This example responds to a `"request"` with a `"response"`. + +```java +page.routeWebSocket("wss://example.com/ws", ws -> { + ws.onMessage(message -> { + if ("request".equals(message)) + ws.send("response"); + }); +}); +``` + +Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block them. Here is an example that modifies some of the messages sent by the page to the server, and leaves the rest unmodified. + +```java +page.routeWebSocket("wss://example.com/ws", ws -> { + WebSocketRoute server = ws.connectToServer(); + ws.onMessage(message -> { + if ("request".equals(message)) + server.send("request2"); + else + server.send(message); + }); +}); +``` + +For more details, see [WebSocketRoute]. + [APIRequest]: /api/class-apirequest.mdx "APIRequest" [APIRequestContext]: /api/class-apirequestcontext.mdx "APIRequestContext" diff --git a/java/versioned_docs/version-stable/network.mdx b/java/versioned_docs/version-stable/network.mdx index 6e2c2e4f01..70cfac0ec8 100644 --- a/java/versioned_docs/version-stable/network.mdx +++ b/java/versioned_docs/version-stable/network.mdx @@ -12,7 +12,7 @@ Playwright provides APIs to **monitor** and **modify** browser network traffic, ## Mock APIs -Check out our [API mocking guide](./mock.mdx) to learn more on how to +Check out our [API mocking guide](./mock.mdx) to learn more on how to - mock API requests and never hit the API - perform the API request and modify the response - use HAR files to mock network requests. @@ -196,7 +196,9 @@ Important notes: ## WebSockets -Playwright supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) inspection out of the box. Every time a WebSocket is created, the [Page.onWebSocket(handler)](/api/class-page.mdx#page-event-web-socket) event is fired. This event contains the [WebSocket] instance for further web socket frames inspection: +Playwright supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) inspection, mocking and modifying out of the box. See our [API mocking guide](./mock.mdx#mock-websockets) to learn how to mock WebSockets. + +Every time a WebSocket is created, the [Page.onWebSocket(handler)](/api/class-page.mdx#page-event-web-socket) event is fired. This event contains the [WebSocket] instance for further web socket frames inspection: ```java page.onWebSocket(ws -> { diff --git a/nodejs/versioned_docs/version-stable/api/class-websocketroute.mdx b/nodejs/versioned_docs/version-stable/api/class-websocketroute.mdx index a44d30ac7a..8868e95bf8 100644 --- a/nodejs/versioned_docs/version-stable/api/class-websocketroute.mdx +++ b/nodejs/versioned_docs/version-stable/api/class-websocketroute.mdx @@ -14,7 +14,7 @@ Whenever a [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSoc By default, the routed WebSocket will not connect to the server. This way, you can mock entire communcation over the WebSocket. Here is an example that responds to a `"request"` with a `"response"`. ```js -await page.routeWebSocket('/ws', ws => { +await page.routeWebSocket('wss://example.com/ws', ws => { ws.onMessage(message => { if (message === 'request') ws.send('response'); @@ -24,6 +24,18 @@ await page.routeWebSocket('/ws', ws => { Since we do not call [webSocketRoute.connectToServer()](/api/class-websocketroute.mdx#web-socket-route-connect-to-server) inside the WebSocket route handler, Playwright assumes that WebSocket will be mocked, and opens the WebSocket inside the page automatically. +Here is another example that handles JSON messages: + +```js +await page.routeWebSocket('wss://example.com/ws', ws => { + ws.onMessage(message => { + const json = JSON.parse(message); + if (json.request === 'question') + ws.send(JSON.stringify({ response: 'answer' })); + }); +}); +``` + **Intercepting** Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block them. Calling [webSocketRoute.connectToServer()](/api/class-websocketroute.mdx#web-socket-route-connect-to-server) returns a server-side `WebSocketRoute` instance that you can send messages to, or handle incoming messages. @@ -155,7 +167,7 @@ Calling this method again will override the handler with a new one. **Usage** ```js -await webSocketRoute.onMessage(handler); +webSocketRoute.onMessage(handler); ``` **Arguments** @@ -163,9 +175,6 @@ await webSocketRoute.onMessage(handler); Function that will handle messages. -**Returns** -- [Promise]<[void]># - --- ### send {#web-socket-route-send} diff --git a/nodejs/versioned_docs/version-stable/ci.mdx b/nodejs/versioned_docs/version-stable/ci.mdx index 895cd16650..58fac41fc7 100644 --- a/nodejs/versioned_docs/version-stable/ci.mdx +++ b/nodejs/versioned_docs/version-stable/ci.mdx @@ -101,7 +101,7 @@ jobs: name: 'Playwright Tests' runs-on: ubuntu-latest container: - image: mcr.microsoft.com/playwright:v1.48.0-jammy + image: mcr.microsoft.com/playwright:v1.48.1-jammy options: --user 1001 steps: - uses: actions/checkout@v4 @@ -340,7 +340,7 @@ trigger: pool: vmImage: ubuntu-latest -container: mcr.microsoft.com/playwright:v1.48.0-noble +container: mcr.microsoft.com/playwright:v1.48.1-noble steps: - task: NodeTool@0 @@ -364,7 +364,7 @@ Running Playwright on CircleCI is very similar to running on GitHub Actions. In executors: pw-jammy-development: docker: - - image: mcr.microsoft.com/playwright:v1.48.0-noble + - image: mcr.microsoft.com/playwright:v1.48.1-noble ``` Note: When using the docker agent definition, you are specifying the resource class of where playwright runs to the 'medium' tier [here](https://circleci.com/docs/configuration-reference?#docker-execution-environment). The default behavior of Playwright is to set the number of workers to the detected core count (2 in the case of the medium tier). Overriding the number of workers to greater than this number will cause unnecessary timeouts and failures. @@ -387,7 +387,7 @@ Jenkins supports Docker agents for pipelines. Use the [Playwright Docker image]( ```groovy pipeline { - agent { docker { image 'mcr.microsoft.com/playwright:v1.48.0-noble' } } + agent { docker { image 'mcr.microsoft.com/playwright:v1.48.1-noble' } } stages { stage('e2e-tests') { steps { @@ -404,7 +404,7 @@ pipeline { Bitbucket Pipelines can use public [Docker images as build environments](https://confluence.atlassian.com/bitbucket/use-docker-images-as-build-environments-792298897.html). To run Playwright tests on Bitbucket, use our public Docker image ([see Dockerfile](./docker.mdx)). ```yml -image: mcr.microsoft.com/playwright:v1.48.0-noble +image: mcr.microsoft.com/playwright:v1.48.1-noble ``` ### GitLab CI @@ -417,7 +417,7 @@ stages: tests: stage: test - image: mcr.microsoft.com/playwright:v1.48.0-noble + image: mcr.microsoft.com/playwright:v1.48.1-noble script: ... ``` @@ -432,7 +432,7 @@ stages: tests: stage: test - image: mcr.microsoft.com/playwright:v1.48.0-noble + image: mcr.microsoft.com/playwright:v1.48.1-noble parallel: 7 script: - npm ci @@ -447,7 +447,7 @@ stages: tests: stage: test - image: mcr.microsoft.com/playwright:v1.48.0-noble + image: mcr.microsoft.com/playwright:v1.48.1-noble parallel: matrix: - PROJECT: ['chromium', 'webkit'] @@ -463,7 +463,7 @@ To run Playwright tests on Google Cloud Build, use our public Docker image ([see ```yml steps: -- name: mcr.microsoft.com/playwright:v1.48.0-noble +- name: mcr.microsoft.com/playwright:v1.48.1-noble script: ... env: @@ -481,7 +481,7 @@ type: docker steps: - name: test - image: mcr.microsoft.com/playwright:v1.48.0-jammy + image: mcr.microsoft.com/playwright:v1.48.1-jammy commands: - npx playwright test ``` diff --git a/nodejs/versioned_docs/version-stable/docker.mdx b/nodejs/versioned_docs/version-stable/docker.mdx index b35809ff38..f8ed28e650 100644 --- a/nodejs/versioned_docs/version-stable/docker.mdx +++ b/nodejs/versioned_docs/version-stable/docker.mdx @@ -22,7 +22,7 @@ This Docker image is intended to be used for testing and development purposes on ### Pull the image ```bash -docker pull mcr.microsoft.com/playwright:v1.48.0-noble +docker pull mcr.microsoft.com/playwright:v1.48.1-noble ``` ### Run the image @@ -34,7 +34,7 @@ By default, the Docker image will use the `root` user to run the browsers. This On trusted websites, you can avoid creating a separate user and use root for it since you trust the code which will run on the browsers. ```bash -docker run -it --rm --ipc=host mcr.microsoft.com/playwright:v1.48.0-noble /bin/bash +docker run -it --rm --ipc=host mcr.microsoft.com/playwright:v1.48.1-noble /bin/bash ``` #### Crawling and scraping @@ -42,7 +42,7 @@ docker run -it --rm --ipc=host mcr.microsoft.com/playwright:v1.48.0-noble /bin/b On untrusted websites, it's recommended to use a separate user for launching the browsers in combination with the seccomp profile. Inside the container or if you are using the Docker image as a base image you have to use `adduser` for it. ```bash -docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright:v1.48.0-noble /bin/bash +docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright:v1.48.1-noble /bin/bash ``` [`seccomp_profile.json`](https://github.com/microsoft/playwright/blob/main/utils/docker/seccomp_profile.json) is needed to run Chromium with sandbox. This is a [default Docker seccomp profile](https://github.com/docker/engine/blob/d0d99b04cf6e00ed3fc27e81fc3d94e7eda70af3/profiles/seccomp/default.json) with extra user namespace cloning permissions: @@ -75,10 +75,10 @@ See our [Continuous Integration guides](./ci.mdx) for sample configs. See [all available image tags]. We currently publish images with the following tags: -- `:v1.48.0` - Playwright v1.48.0 release docker image based on Ubuntu 24.04 LTS (Noble Numbat). -- `:v1.48.0-noble` - Playwright v1.48.0 release docker image based on Ubuntu 24.04 LTS (Noble Numbat). -- `:v1.48.0-jammy` - Playwright v1.48.0 release docker image based on Ubuntu 22.04 LTS (Jammy Jellyfish). -- `:v1.48.0-focal` - Playwright v1.48.0 release docker image based on Ubuntu 20.04 LTS (Focal Fossa). +- `:v1.48.1` - Playwright v1.48.1 release docker image based on Ubuntu 24.04 LTS (Noble Numbat). +- `:v1.48.1-noble` - Playwright v1.48.1 release docker image based on Ubuntu 24.04 LTS (Noble Numbat). +- `:v1.48.1-jammy` - Playwright v1.48.1 release docker image based on Ubuntu 22.04 LTS (Jammy Jellyfish). +- `:v1.48.1-focal` - Playwright v1.48.1 release docker image based on Ubuntu 20.04 LTS (Focal Fossa). :::note @@ -103,7 +103,7 @@ To run Playwright inside Docker, you need to have Node.js, [Playwright browsers] ```Dockerfile FROM node:20-bookworm -RUN npx -y playwright@1.48.0 install --with-deps +RUN npx -y playwright@1.48.1 install --with-deps ``` diff --git a/nodejs/versioned_docs/version-stable/mock.mdx b/nodejs/versioned_docs/version-stable/mock.mdx index 1f8e02c7e3..8cc9e4562c 100644 --- a/nodejs/versioned_docs/version-stable/mock.mdx +++ b/nodejs/versioned_docs/version-stable/mock.mdx @@ -151,6 +151,35 @@ npx playwright open --save-har=example.har --save-har-glob="**/api/**" https://e Read more about [advanced networking](./network.mdx). +## Mock WebSockets + +The following code will intercept WebSocket connections and mock entire communcation over the WebSocket, instead of connecting to the server. This example responds to a `"request"` with a `"response"`. + +```js +await page.routeWebSocket('wss://example.com/ws', ws => { + ws.onMessage(message => { + if (message === 'request') + ws.send('response'); + }); +}); +``` + +Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block them. Here is an example that modifies some of the messages sent by the page to the server, and leaves the rest unmodified. + +```js +await page.routeWebSocket('wss://example.com/ws', ws => { + const server = ws.connectToServer(); + ws.onMessage(message => { + if (message === 'request') + server.send('request2'); + else + server.send(message); + }); +}); +``` + +For more details, see [WebSocketRoute]. + [Accessibility]: /api/class-accessibility.mdx "Accessibility" [Android]: /api/class-android.mdx "Android" diff --git a/nodejs/versioned_docs/version-stable/network.mdx b/nodejs/versioned_docs/version-stable/network.mdx index d542fa5e58..7d605bda84 100644 --- a/nodejs/versioned_docs/version-stable/network.mdx +++ b/nodejs/versioned_docs/version-stable/network.mdx @@ -12,7 +12,7 @@ Playwright provides APIs to **monitor** and **modify** browser network traffic, ## Mock APIs -Check out our [API mocking guide](./mock.mdx) to learn more on how to +Check out our [API mocking guide](./mock.mdx) to learn more on how to - mock API requests and never hit the API - perform the API request and modify the response - use HAR files to mock network requests. @@ -315,7 +315,9 @@ Important notes: ## WebSockets -Playwright supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) inspection out of the box. Every time a WebSocket is created, the [page.on('websocket')](/api/class-page.mdx#page-event-web-socket) event is fired. This event contains the [WebSocket] instance for further web socket frames inspection: +Playwright supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) inspection, mocking and modifying out of the box. See our [API mocking guide](./mock.mdx#mock-websockets) to learn how to mock WebSockets. + +Every time a WebSocket is created, the [page.on('websocket')](/api/class-page.mdx#page-event-web-socket) event is fired. This event contains the [WebSocket] instance for further web socket frames inspection: ```js page.on('websocket', ws => { diff --git a/python/versioned_docs/version-stable/api/class-websocketroute.mdx b/python/versioned_docs/version-stable/api/class-websocketroute.mdx index 06a705f971..44c9bf23f9 100644 --- a/python/versioned_docs/version-stable/api/class-websocketroute.mdx +++ b/python/versioned_docs/version-stable/api/class-websocketroute.mdx @@ -28,7 +28,7 @@ def message_handler(ws: WebSocketRoute, message: Union[str, bytes]): if message == "request": ws.send("response") -page.route_web_socket("/ws", lambda ws: ws.on_message( +page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( lambda message: message_handler(ws, message) )) ``` @@ -41,7 +41,7 @@ def message_handler(ws: WebSocketRoute, message: Union[str, bytes]): if message == "request": ws.send("response") -await page.route_web_socket("/ws", lambda ws: ws.on_message( +await page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( lambda message: message_handler(ws, message) )) ``` @@ -51,6 +51,46 @@ await page.route_web_socket("/ws", lambda ws: ws.on_message( Since we do not call [web_socket_route.connect_to_server](/api/class-websocketroute.mdx#web-socket-route-connect-to-server) inside the WebSocket route handler, Playwright assumes that WebSocket will be mocked, and opens the WebSocket inside the page automatically. +Here is another example that handles JSON messages: + + + + +```py +def message_handler(ws: WebSocketRoute, message: Union[str, bytes]): + json_message = json.loads(message) + if json_message["request"] == "question": + ws.send(json.dumps({ "response": "answer" })) + +page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( + lambda message: message_handler(ws, message) +)) +``` + + + + +```py +def message_handler(ws: WebSocketRoute, message: Union[str, bytes]): + json_message = json.loads(message) + if json_message["request"] == "question": + ws.send(json.dumps({ "response": "answer" })) + +await page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( + lambda message: message_handler(ws, message) +)) +``` + + + + **Intercepting** Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block them. Calling [web_socket_route.connect_to_server](/api/class-websocketroute.mdx#web-socket-route-connect-to-server) returns a server-side `WebSocketRoute` instance that you can send messages to, or handle incoming messages. @@ -205,7 +245,7 @@ web_socket_route.on_close(handler) ``` **Arguments** -- `handler` [Callable]\[[number] | [undefined]\]:[Promise]\[[Any]\] | [Any]# +- `handler` [Callable]\[[int] | [undefined]\]:[Promise]\[[Any]\] | [Any]# Function that will handle WebSocket closure. Received an optional [close code](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code) and an optional [close reason](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason). @@ -234,9 +274,6 @@ web_socket_route.on_message(handler) Function that will handle messages. -**Returns** -- [NoneType]# - --- ### send {#web-socket-route-send} diff --git a/python/versioned_docs/version-stable/mock.mdx b/python/versioned_docs/version-stable/mock.mdx index b83d7c3442..9f8364a29c 100644 --- a/python/versioned_docs/version-stable/mock.mdx +++ b/python/versioned_docs/version-stable/mock.mdx @@ -270,6 +270,94 @@ playwright open --save-har=example.har --save-har-glob="**/api/**" https://examp Read more about [advanced networking](./network.mdx). +## Mock WebSockets + +The following code will intercept WebSocket connections and mock entire communcation over the WebSocket, instead of connecting to the server. This example responds to a `"request"` with a `"response"`. + + + + +```py +def message_handler(ws: WebSocketRoute, message: Union[str, bytes]): + if message == "request": + ws.send("response") + +page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( + lambda message: message_handler(ws, message) +)) +``` + + + + +```py +def message_handler(ws: WebSocketRoute, message: Union[str, bytes]): + if message == "request": + ws.send("response") + +await page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( + lambda message: message_handler(ws, message) +)) +``` + + + + +Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block them. Here is an example that modifies some of the messages sent by the page to the server, and leaves the rest unmodified. + + + + +```py +def message_handler(server: WebSocketRoute, message: Union[str, bytes]): + if message == "request": + server.send("request2") + else: + server.send(message) + +def handler(ws: WebSocketRoute): + server = ws.connect_to_server() + ws.on_message(lambda message: message_handler(server, message)) + +page.route_web_socket("wss://example.com/ws", handler) +``` + + + + +```py +def message_handler(server: WebSocketRoute, message: Union[str, bytes]): + if message == "request": + server.send("request2") + else: + server.send(message) + +def handler(ws: WebSocketRoute): + server = ws.connect_to_server() + ws.on_message(lambda message: message_handler(server, message)) + +await page.route_web_socket("wss://example.com/ws", handler) +``` + + + + +For more details, see [WebSocketRoute]. + [Accessibility]: /api/class-accessibility.mdx "Accessibility" [APIRequest]: /api/class-apirequest.mdx "APIRequest" diff --git a/python/versioned_docs/version-stable/network.mdx b/python/versioned_docs/version-stable/network.mdx index 79a604b28a..2861c63de9 100644 --- a/python/versioned_docs/version-stable/network.mdx +++ b/python/versioned_docs/version-stable/network.mdx @@ -12,7 +12,7 @@ Playwright provides APIs to **monitor** and **modify** browser network traffic, ## Mock APIs -Check out our [API mocking guide](./mock.mdx) to learn more on how to +Check out our [API mocking guide](./mock.mdx) to learn more on how to - mock API requests and never hit the API - perform the API request and modify the response - use HAR files to mock network requests. @@ -479,7 +479,9 @@ Important notes: ## WebSockets -Playwright supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) inspection out of the box. Every time a WebSocket is created, the [page.on("websocket")](/api/class-page.mdx#page-event-web-socket) event is fired. This event contains the [WebSocket] instance for further web socket frames inspection: +Playwright supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) inspection, mocking and modifying out of the box. See our [API mocking guide](./mock.mdx#mock-websockets) to learn how to mock WebSockets. + +Every time a WebSocket is created, the [page.on("websocket")](/api/class-page.mdx#page-event-web-socket) event is fired. This event contains the [WebSocket] instance for further web socket frames inspection: ```python def on_web_socket(ws):