Skip to content

Commit 46b8bc5

Browse files
authored
feat(ppt): websocket messages (#4264)
1 parent b2a8452 commit 46b8bc5

File tree

8 files changed

+192
-57
lines changed

8 files changed

+192
-57
lines changed

docs/helpers/Playwright.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,6 +2217,8 @@ This also resets recorded websocket messages.
22172217
await I.startRecordingWebSocketMessages();
22182218
```
22192219

2220+
Returns **void** automatically synchronized promise through #recorder
2221+
22202222
### stopMockingRoute
22212223

22222224
Stops network mocking created by `mockRoute`.
@@ -2249,6 +2251,8 @@ Stops recording WS messages. Recorded WS messages is not flashed.
22492251
await I.stopRecordingWebSocketMessages();
22502252
```
22512253

2254+
Returns **void** automatically synchronized promise through #recorder
2255+
22522256
### switchTo
22532257

22542258
Switches frame or in case of null locator reverts to parent.

docs/helpers/Puppeteer.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,10 @@ Returns **void** automatically synchronized promise through #recorder
811811
This action supports [React locators](https://codecept.io/react#locators)
812812
813813
814+
### flushWebSocketMessages
815+
816+
Resets all recorded WS messages.
817+
814818
### focus
815819
816820
Calls [focus][8] on the matching element.
@@ -1236,6 +1240,12 @@ const webElements = await I.grabWebElements('#button');
12361240
12371241
Returns **[Promise][13]<any>** WebElement of being used Web helper
12381242
1243+
### grabWebSocketMessages
1244+
1245+
Grab the recording WS messages
1246+
1247+
Returns **[Array][15]<any>**
1248+
12391249
### handleDownloads
12401250
12411251
Sets a directory to where save files. Allows to test file downloads.
@@ -1877,6 +1887,17 @@ I.setPuppeteerRequestHeaders({
18771887
18781888
- `customHeaders` **[object][4]** headers to set
18791889
1890+
### startRecordingWebSocketMessages
1891+
1892+
Starts recording of websocket messages.
1893+
This also resets recorded websocket messages.
1894+
1895+
```js
1896+
await I.startRecordingWebSocketMessages();
1897+
```
1898+
1899+
Returns **void** automatically synchronized promise through #recorder
1900+
18801901
### stopMockingRoute
18811902
18821903
Stops network mocking created by `mockRoute`.
@@ -1889,6 +1910,16 @@ I.stopMockingRoute(/(.png$)|(.jpg$)/);
18891910
18901911
- `url` **([string][6] | [RegExp][18])?** URL, regex or pattern for to match URL
18911912
1913+
### stopRecordingWebSocketMessages
1914+
1915+
Stops recording WS messages. Recorded WS messages is not flashed.
1916+
1917+
```js
1918+
await I.stopRecordingWebSocketMessages();
1919+
```
1920+
1921+
Returns **void** automatically synchronized promise through #recorder
1922+
18921923
### switchTo
18931924
18941925
Switches frame or in case of null locator reverts to parent.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Starts recording of websocket messages.
2+
This also resets recorded websocket messages.
3+
4+
```js
5+
await I.startRecordingWebSocketMessages();
6+
```
7+
8+
@returns {void} automatically synchronized promise through #recorder
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Stops recording WS messages. Recorded WS messages is not flashed.
2+
3+
```js
4+
await I.stopRecordingWebSocketMessages();
5+
```
6+
7+
@returns {void} automatically synchronized promise through #recorder

lib/helper/Playwright.js

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3287,13 +3287,7 @@ class Playwright extends Helper {
32873287
}
32883288

32893289
/**
3290-
* Starts recording of websocket messages.
3291-
* This also resets recorded websocket messages.
3292-
*
3293-
* ```js
3294-
* await I.startRecordingWebSocketMessages();
3295-
* ```
3296-
*
3290+
* {{> startRecordingWebSocketMessages }}
32973291
*/
32983292
async startRecordingWebSocketMessages() {
32993293
this.flushWebSocketMessages();
@@ -3327,11 +3321,7 @@ class Playwright extends Helper {
33273321
}
33283322

33293323
/**
3330-
* Stops recording WS messages. Recorded WS messages is not flashed.
3331-
*
3332-
* ```js
3333-
* await I.stopRecordingWebSocketMessages();
3334-
* ```
3324+
* {{> stopRecordingWebSocketMessages }}
33353325
*/
33363326
async stopRecordingWebSocketMessages() {
33373327
await this.cdpSession.send('Network.disable');

lib/helper/Puppeteer.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,12 @@ class Puppeteer extends Helper {
226226
this.sessionPages = {};
227227
this.activeSessionName = '';
228228

229+
// for websocket messages
230+
this.webSocketMessages = [];
231+
this.recordingWebSocketMessages = false;
232+
this.recordedWebSocketMessagesAtLeastOnce = false;
233+
this.cdpSession = null;
234+
229235
// override defaults with config
230236
this._setConfig(config);
231237
}
@@ -2507,6 +2513,93 @@ class Puppeteer extends Helper {
25072513
}
25082514
});
25092515
}
2516+
2517+
async getNewCDPSession() {
2518+
const client = await this.page.target().createCDPSession();
2519+
return client;
2520+
}
2521+
2522+
/**
2523+
* {{> startRecordingWebSocketMessages }}
2524+
*/
2525+
async startRecordingWebSocketMessages() {
2526+
this.flushWebSocketMessages();
2527+
this.recordingWebSocketMessages = true;
2528+
this.recordedWebSocketMessagesAtLeastOnce = true;
2529+
2530+
this.cdpSession = await this.getNewCDPSession();
2531+
await this.cdpSession.send('Network.enable');
2532+
await this.cdpSession.send('Page.enable');
2533+
2534+
this.cdpSession.on(
2535+
'Network.webSocketFrameReceived',
2536+
(payload) => {
2537+
this._logWebsocketMessages(this._getWebSocketLog('RECEIVED', payload));
2538+
},
2539+
);
2540+
2541+
this.cdpSession.on(
2542+
'Network.webSocketFrameSent',
2543+
(payload) => {
2544+
this._logWebsocketMessages(this._getWebSocketLog('SENT', payload));
2545+
},
2546+
);
2547+
2548+
this.cdpSession.on(
2549+
'Network.webSocketFrameError',
2550+
(payload) => {
2551+
this._logWebsocketMessages(this._getWebSocketLog('ERROR', payload));
2552+
},
2553+
);
2554+
}
2555+
2556+
/**
2557+
* {{> stopRecordingWebSocketMessages }}
2558+
*/
2559+
async stopRecordingWebSocketMessages() {
2560+
await this.cdpSession.send('Network.disable');
2561+
await this.cdpSession.send('Page.disable');
2562+
this.page.removeAllListeners('Network');
2563+
this.recordingWebSocketMessages = false;
2564+
}
2565+
2566+
/**
2567+
* Grab the recording WS messages
2568+
*
2569+
* @return { Array<any> }
2570+
*
2571+
*/
2572+
grabWebSocketMessages() {
2573+
if (!this.recordingWebSocketMessages) {
2574+
if (!this.recordedWebSocketMessagesAtLeastOnce) {
2575+
throw new Error('Failure in test automation. You use "I.grabWebSocketMessages", but "I.startRecordingWebSocketMessages" was never called before.');
2576+
}
2577+
}
2578+
return this.webSocketMessages;
2579+
}
2580+
2581+
/**
2582+
* Resets all recorded WS messages.
2583+
*/
2584+
flushWebSocketMessages() {
2585+
this.webSocketMessages = [];
2586+
}
2587+
2588+
_getWebSocketMessage(payload) {
2589+
if (payload.errorMessage) {
2590+
return payload.errorMessage;
2591+
}
2592+
2593+
return payload.response.payloadData;
2594+
}
2595+
2596+
_getWebSocketLog(prefix, payload) {
2597+
return `${prefix} ID: ${payload.requestId} TIMESTAMP: ${payload.timestamp} (${new Date().toISOString()})\n\n${this._getWebSocketMessage(payload)}\n\n`;
2598+
}
2599+
2600+
_logWebsocketMessages(message) {
2601+
this.webSocketMessages += message;
2602+
}
25102603
}
25112604

25122605
module.exports = Puppeteer;

test/helper/Playwright_test.js

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,51 +1067,6 @@ describe('Playwright', function () {
10671067
});
10681068
});
10691069

1070-
describe('#startRecordingWebSocketMessages, #grabWebSocketMessages, #stopRecordingWebSocketMessages', () => {
1071-
it('should throw error when calling grabWebSocketMessages before startRecordingWebSocketMessages', () => {
1072-
if (process.env.BROWSER === 'firefox') this.skip();
1073-
try {
1074-
I.amOnPage('https://websocketstest.com/');
1075-
I.waitForText('Work for You!');
1076-
I.grabWebSocketMessages();
1077-
} catch (e) {
1078-
expect(e.message).to.equal('Failure in test automation. You use "I.grabWebSocketMessages", but "I.startRecordingWebSocketMessages" was never called before.');
1079-
}
1080-
});
1081-
1082-
it('should flush the WS messages', async () => {
1083-
if (process.env.BROWSER === 'firefox') this.skip();
1084-
await I.startRecordingWebSocketMessages();
1085-
I.amOnPage('https://websocketstest.com/');
1086-
I.waitForText('Work for You!');
1087-
I.flushNetworkTraffics();
1088-
const wsMessages = I.grabWebSocketMessages();
1089-
expect(wsMessages.length).to.equal(0);
1090-
});
1091-
1092-
it('should see recording WS messages', async () => {
1093-
if (process.env.BROWSER === 'firefox') this.skip();
1094-
await I.startRecordingWebSocketMessages();
1095-
await I.amOnPage('https://websocketstest.com/');
1096-
I.waitForText('Work for You!');
1097-
const wsMessages = I.grabWebSocketMessages();
1098-
expect(wsMessages.length).to.greaterThan(0);
1099-
});
1100-
1101-
it('should not see recording WS messages', async () => {
1102-
if (process.env.BROWSER === 'firefox') this.skip();
1103-
await I.startRecordingWebSocketMessages();
1104-
await I.amOnPage('https://websocketstest.com/');
1105-
I.waitForText('Work for You!');
1106-
const wsMessages = I.grabWebSocketMessages();
1107-
await I.stopRecordingWebSocketMessages();
1108-
await I.amOnPage('https://websocketstest.com/');
1109-
I.waitForText('Work for You!');
1110-
const afterWsMessages = I.grabWebSocketMessages();
1111-
expect(wsMessages.length).to.equal(afterWsMessages.length);
1112-
});
1113-
});
1114-
11151070
describe('#makeApiRequest', () => {
11161071
it('should make 3rd party API request', async () => {
11171072
const response = await I.makeApiRequest('get', 'https://reqres.in/api/users?page=2');

test/helper/webapi.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
let assert;
2+
let expect;
23
import('chai').then(chai => {
34
assert = chai.assert;
5+
expect = chai.expect;
46
});
57
const path = require('path');
68

@@ -1609,4 +1611,49 @@ module.exports.tests = function () {
16091611
await I.see('Textarea not focused', '#textareaMessage');
16101612
});
16111613
});
1614+
1615+
describe('#startRecordingWebSocketMessages, #grabWebSocketMessages, #stopRecordingWebSocketMessages', () => {
1616+
beforeEach(function () {
1617+
if (isHelper('TestCafe') || isHelper('WebDriver') || process.env.BROWSER === 'firefox') this.skip();
1618+
});
1619+
1620+
it('should throw error when calling grabWebSocketMessages before startRecordingWebSocketMessages', () => {
1621+
try {
1622+
I.amOnPage('https://websocketstest.com/');
1623+
I.waitForText('Work for You!');
1624+
I.grabWebSocketMessages();
1625+
} catch (e) {
1626+
expect(e.message).to.equal('Failure in test automation. You use "I.grabWebSocketMessages", but "I.startRecordingWebSocketMessages" was never called before.');
1627+
}
1628+
});
1629+
1630+
it('should flush the WS messages', async () => {
1631+
await I.startRecordingWebSocketMessages();
1632+
I.amOnPage('https://websocketstest.com/');
1633+
I.waitForText('Work for You!');
1634+
I.flushWebSocketMessages();
1635+
const wsMessages = I.grabWebSocketMessages();
1636+
expect(wsMessages.length).to.equal(0);
1637+
});
1638+
1639+
it('should see recording WS messages', async () => {
1640+
await I.startRecordingWebSocketMessages();
1641+
await I.amOnPage('https://websocketstest.com/');
1642+
I.waitForText('Work for You!');
1643+
const wsMessages = await I.grabWebSocketMessages();
1644+
expect(wsMessages.length).to.greaterThan(0);
1645+
});
1646+
1647+
it('should not see recording WS messages', async () => {
1648+
await I.startRecordingWebSocketMessages();
1649+
await I.amOnPage('https://websocketstest.com/');
1650+
I.waitForText('Work for You!');
1651+
const wsMessages = I.grabWebSocketMessages();
1652+
await I.stopRecordingWebSocketMessages();
1653+
await I.amOnPage('https://websocketstest.com/');
1654+
I.waitForText('Work for You!');
1655+
const afterWsMessages = I.grabWebSocketMessages();
1656+
expect(wsMessages.length).to.equal(afterWsMessages.length);
1657+
});
1658+
});
16121659
};

0 commit comments

Comments
 (0)