Skip to content

Commit 78c43bc

Browse files
committed
cherry-pick(#33097): docs: improve docs for WebSocketRoute
1 parent 6dc9ec7 commit 78c43bc

File tree

4 files changed

+204
-8
lines changed

4 files changed

+204
-8
lines changed

docs/src/api/class-websocketroute.md

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Whenever a [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSoc
88
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"`.
99

1010
```js
11-
await page.routeWebSocket('/ws', ws => {
11+
await page.routeWebSocket('wss://example.com/ws', ws => {
1212
ws.onMessage(message => {
1313
if (message === 'request')
1414
ws.send('response');
@@ -17,7 +17,7 @@ await page.routeWebSocket('/ws', ws => {
1717
```
1818

1919
```java
20-
page.routeWebSocket("/ws", ws -> {
20+
page.routeWebSocket("wss://example.com/ws", ws -> {
2121
ws.onMessage(message -> {
2222
if ("request".equals(message))
2323
ws.send("response");
@@ -30,7 +30,7 @@ def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
3030
if message == "request":
3131
ws.send("response")
3232

33-
await page.route_web_socket("/ws", lambda ws: ws.on_message(
33+
await page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message(
3434
lambda message: message_handler(ws, message)
3535
))
3636
```
@@ -40,13 +40,13 @@ def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
4040
if message == "request":
4141
ws.send("response")
4242

43-
page.route_web_socket("/ws", lambda ws: ws.on_message(
43+
page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message(
4444
lambda message: message_handler(ws, message)
4545
))
4646
```
4747

4848
```csharp
49-
await page.RouteWebSocketAsync("/ws", ws => {
49+
await page.RouteWebSocketAsync("wss://example.com/ws", ws => {
5050
ws.OnMessage(message => {
5151
if (message == "request")
5252
ws.Send("response");
@@ -56,6 +56,69 @@ await page.RouteWebSocketAsync("/ws", ws => {
5656

5757
Since we do not call [`method: WebSocketRoute.connectToServer`] inside the WebSocket route handler, Playwright assumes that WebSocket will be mocked, and opens the WebSocket inside the page automatically.
5858

59+
Here is another example that handles JSON messages:
60+
61+
```js
62+
await page.routeWebSocket('wss://example.com/ws', ws => {
63+
ws.onMessage(message => {
64+
const json = JSON.parse(message);
65+
if (json.request === 'question')
66+
ws.send(JSON.stringify({ response: 'answer' }));
67+
});
68+
});
69+
```
70+
71+
```java
72+
page.routeWebSocket("wss://example.com/ws", ws -> {
73+
ws.onMessage(message -> {
74+
JsonObject json = new JsonParser().parse(message).getAsJsonObject();
75+
if ("question".equals(json.get("request").getAsString())) {
76+
Map<String, String> result = new HashMap();
77+
result.put("response", "answer");
78+
ws.send(gson.toJson(result));
79+
}
80+
});
81+
});
82+
```
83+
84+
```python async
85+
def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
86+
json_message = json.loads(message)
87+
if json_message["request"] == "question":
88+
ws.send(json.dumps({ "response": "answer" }))
89+
90+
await page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message(
91+
lambda message: message_handler(ws, message)
92+
))
93+
```
94+
95+
```python sync
96+
def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
97+
json_message = json.loads(message)
98+
if json_message["request"] == "question":
99+
ws.send(json.dumps({ "response": "answer" }))
100+
101+
page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message(
102+
lambda message: message_handler(ws, message)
103+
))
104+
```
105+
106+
```csharp
107+
await page.RouteWebSocketAsync("wss://example.com/ws", ws => {
108+
ws.OnMessage(message => {
109+
using var jsonDoc = JsonDocument.Parse(message);
110+
JsonElement root = jsonDoc.RootElement;
111+
if (root.TryGetProperty("request", out JsonElement requestElement) && requestElement.GetString() == "question")
112+
{
113+
var response = new Dictionary<string, string> { ["response"] = "answer" };
114+
string jsonResponse = JsonSerializer.Serialize(response);
115+
ws.Send(jsonResponse);
116+
}
117+
});
118+
});
119+
```
120+
121+
59122
**Intercepting**
60123

61124
Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block them. Calling [`method: WebSocketRoute.connectToServer`] returns a server-side `WebSocketRoute` instance that you can send messages to, or handle incoming messages.

docs/src/mock.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,3 +434,122 @@ pwsh bin/Debug/netX/playwright.ps1 open --save-har=example.har --save-har-glob="
434434
```
435435

436436
Read more about [advanced networking](./network.md).
437+
438+
## Mock WebSockets
439+
440+
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"`.
441+
442+
```js
443+
await page.routeWebSocket('wss://example.com/ws', ws => {
444+
ws.onMessage(message => {
445+
if (message === 'request')
446+
ws.send('response');
447+
});
448+
});
449+
```
450+
451+
```java
452+
page.routeWebSocket("wss://example.com/ws", ws -> {
453+
ws.onMessage(message -> {
454+
if ("request".equals(message))
455+
ws.send("response");
456+
});
457+
});
458+
```
459+
460+
```python async
461+
def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
462+
if message == "request":
463+
ws.send("response")
464+
465+
await page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message(
466+
lambda message: message_handler(ws, message)
467+
))
468+
```
469+
470+
```python sync
471+
def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
472+
if message == "request":
473+
ws.send("response")
474+
475+
page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message(
476+
lambda message: message_handler(ws, message)
477+
))
478+
```
479+
480+
```csharp
481+
await page.RouteWebSocketAsync("wss://example.com/ws", ws => {
482+
ws.OnMessage(message => {
483+
if (message == "request")
484+
ws.Send("response");
485+
});
486+
});
487+
```
488+
489+
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.
490+
491+
```js
492+
await page.routeWebSocket('wss://example.com/ws', ws => {
493+
const server = ws.connectToServer();
494+
ws.onMessage(message => {
495+
if (message === 'request')
496+
server.send('request2');
497+
else
498+
server.send(message);
499+
});
500+
});
501+
```
502+
503+
```java
504+
page.routeWebSocket("wss://example.com/ws", ws -> {
505+
WebSocketRoute server = ws.connectToServer();
506+
ws.onMessage(message -> {
507+
if ("request".equals(message))
508+
server.send("request2");
509+
else
510+
server.send(message);
511+
});
512+
});
513+
```
514+
515+
```python async
516+
def message_handler(server: WebSocketRoute, message: Union[str, bytes]):
517+
if message == "request":
518+
server.send("request2")
519+
else:
520+
server.send(message)
521+
522+
def handler(ws: WebSocketRoute):
523+
server = ws.connect_to_server()
524+
ws.on_message(lambda message: message_handler(server, message))
525+
526+
await page.route_web_socket("wss://example.com/ws", handler)
527+
```
528+
529+
```python sync
530+
def message_handler(server: WebSocketRoute, message: Union[str, bytes]):
531+
if message == "request":
532+
server.send("request2")
533+
else:
534+
server.send(message)
535+
536+
def handler(ws: WebSocketRoute):
537+
server = ws.connect_to_server()
538+
ws.on_message(lambda message: message_handler(server, message))
539+
540+
page.route_web_socket("wss://example.com/ws", handler)
541+
```
542+
543+
```csharp
544+
await page.RouteWebSocketAsync("wss://example.com/ws", ws => {
545+
var server = ws.ConnectToServer();
546+
ws.OnMessage(message => {
547+
if (message == "request")
548+
server.Send("request2");
549+
else
550+
server.Send(message);
551+
});
552+
});
553+
```
554+
555+
For more details, see [WebSocketRoute].

docs/src/network.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Playwright provides APIs to **monitor** and **modify** browser network traffic,
1010

1111
## Mock APIs
1212

13-
Check out our [API mocking guide](./mock.md) to learn more on how to
13+
Check out our [API mocking guide](./mock.md) to learn more on how to
1414
- mock API requests and never hit the API
1515
- perform the API request and modify the response
1616
- use HAR files to mock network requests.
@@ -723,7 +723,9 @@ Important notes:
723723

724724
## WebSockets
725725

726-
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 [`event: Page.webSocket`] event is fired. This event contains the [WebSocket] instance for further web socket frames inspection:
726+
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.md#mock-websockets) to learn how to mock WebSockets.
727+
728+
Every time a WebSocket is created, the [`event: Page.webSocket`] event is fired. This event contains the [WebSocket] instance for further web socket frames inspection:
727729

728730
```js
729731
page.on('websocket', ws => {

packages/playwright-core/types/types.d.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15355,7 +15355,7 @@ export interface CDPSession {
1535515355
* the WebSocket. Here is an example that responds to a `"request"` with a `"response"`.
1535615356
*
1535715357
* ```js
15358-
* await page.routeWebSocket('/ws', ws => {
15358+
* await page.routeWebSocket('wss://example.com/ws', ws => {
1535915359
* ws.onMessage(message => {
1536015360
* if (message === 'request')
1536115361
* ws.send('response');
@@ -15368,6 +15368,18 @@ export interface CDPSession {
1536815368
* inside the WebSocket route handler, Playwright assumes that WebSocket will be mocked, and opens the WebSocket
1536915369
* inside the page automatically.
1537015370
*
15371+
* Here is another example that handles JSON messages:
15372+
*
15373+
* ```js
15374+
* await page.routeWebSocket('wss://example.com/ws', ws => {
15375+
* ws.onMessage(message => {
15376+
* const json = JSON.parse(message);
15377+
* if (json.request === 'question')
15378+
* ws.send(JSON.stringify({ response: 'answer' }));
15379+
* });
15380+
* });
15381+
* ```
15382+
*
1537115383
* **Intercepting**
1537215384
*
1537315385
* Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block

0 commit comments

Comments
 (0)