Skip to content

Commit

Permalink
feat(ppt): websocket messages (#4264)
Browse files Browse the repository at this point in the history
  • Loading branch information
kobenguyent authored Mar 21, 2024
1 parent b2a8452 commit 46b8bc5
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 57 deletions.
4 changes: 4 additions & 0 deletions docs/helpers/Playwright.md
Original file line number Diff line number Diff line change
Expand Up @@ -2217,6 +2217,8 @@ This also resets recorded websocket messages.
await I.startRecordingWebSocketMessages();
```

Returns **void** automatically synchronized promise through #recorder

### stopMockingRoute

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

Returns **void** automatically synchronized promise through #recorder

### switchTo

Switches frame or in case of null locator reverts to parent.
Expand Down
31 changes: 31 additions & 0 deletions docs/helpers/Puppeteer.md
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,10 @@ Returns **void** automatically synchronized promise through #recorder
This action supports [React locators](https://codecept.io/react#locators)
### flushWebSocketMessages
Resets all recorded WS messages.
### focus
Calls [focus][8] on the matching element.
Expand Down Expand Up @@ -1236,6 +1240,12 @@ const webElements = await I.grabWebElements('#button');
Returns **[Promise][13]<any>** WebElement of being used Web helper
### grabWebSocketMessages
Grab the recording WS messages
Returns **[Array][15]<any>**
### handleDownloads
Sets a directory to where save files. Allows to test file downloads.
Expand Down Expand Up @@ -1877,6 +1887,17 @@ I.setPuppeteerRequestHeaders({
- `customHeaders` **[object][4]** headers to set
### startRecordingWebSocketMessages
Starts recording of websocket messages.
This also resets recorded websocket messages.
```js
await I.startRecordingWebSocketMessages();
```
Returns **void** automatically synchronized promise through #recorder
### stopMockingRoute
Stops network mocking created by `mockRoute`.
Expand All @@ -1889,6 +1910,16 @@ I.stopMockingRoute(/(.png$)|(.jpg$)/);
- `url` **([string][6] | [RegExp][18])?** URL, regex or pattern for to match URL
### stopRecordingWebSocketMessages
Stops recording WS messages. Recorded WS messages is not flashed.
```js
await I.stopRecordingWebSocketMessages();
```
Returns **void** automatically synchronized promise through #recorder
### switchTo
Switches frame or in case of null locator reverts to parent.
Expand Down
8 changes: 8 additions & 0 deletions docs/webapi/startRecordingWebSocketMessages.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Starts recording of websocket messages.
This also resets recorded websocket messages.

```js
await I.startRecordingWebSocketMessages();
```

@returns {void} automatically synchronized promise through #recorder
7 changes: 7 additions & 0 deletions docs/webapi/stopRecordingWebSocketMessages.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Stops recording WS messages. Recorded WS messages is not flashed.

```js
await I.stopRecordingWebSocketMessages();
```

@returns {void} automatically synchronized promise through #recorder
14 changes: 2 additions & 12 deletions lib/helper/Playwright.js
Original file line number Diff line number Diff line change
Expand Up @@ -3287,13 +3287,7 @@ class Playwright extends Helper {
}

/**
* Starts recording of websocket messages.
* This also resets recorded websocket messages.
*
* ```js
* await I.startRecordingWebSocketMessages();
* ```
*
* {{> startRecordingWebSocketMessages }}
*/
async startRecordingWebSocketMessages() {
this.flushWebSocketMessages();
Expand Down Expand Up @@ -3327,11 +3321,7 @@ class Playwright extends Helper {
}

/**
* Stops recording WS messages. Recorded WS messages is not flashed.
*
* ```js
* await I.stopRecordingWebSocketMessages();
* ```
* {{> stopRecordingWebSocketMessages }}
*/
async stopRecordingWebSocketMessages() {
await this.cdpSession.send('Network.disable');
Expand Down
93 changes: 93 additions & 0 deletions lib/helper/Puppeteer.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ class Puppeteer extends Helper {
this.sessionPages = {};
this.activeSessionName = '';

// for websocket messages
this.webSocketMessages = [];
this.recordingWebSocketMessages = false;
this.recordedWebSocketMessagesAtLeastOnce = false;
this.cdpSession = null;

// override defaults with config
this._setConfig(config);
}
Expand Down Expand Up @@ -2507,6 +2513,93 @@ class Puppeteer extends Helper {
}
});
}

async getNewCDPSession() {
const client = await this.page.target().createCDPSession();
return client;
}

/**
* {{> startRecordingWebSocketMessages }}
*/
async startRecordingWebSocketMessages() {
this.flushWebSocketMessages();
this.recordingWebSocketMessages = true;
this.recordedWebSocketMessagesAtLeastOnce = true;

this.cdpSession = await this.getNewCDPSession();
await this.cdpSession.send('Network.enable');
await this.cdpSession.send('Page.enable');

this.cdpSession.on(
'Network.webSocketFrameReceived',
(payload) => {
this._logWebsocketMessages(this._getWebSocketLog('RECEIVED', payload));
},
);

this.cdpSession.on(
'Network.webSocketFrameSent',
(payload) => {
this._logWebsocketMessages(this._getWebSocketLog('SENT', payload));
},
);

this.cdpSession.on(
'Network.webSocketFrameError',
(payload) => {
this._logWebsocketMessages(this._getWebSocketLog('ERROR', payload));
},
);
}

/**
* {{> stopRecordingWebSocketMessages }}
*/
async stopRecordingWebSocketMessages() {
await this.cdpSession.send('Network.disable');
await this.cdpSession.send('Page.disable');
this.page.removeAllListeners('Network');
this.recordingWebSocketMessages = false;
}

/**
* Grab the recording WS messages
*
* @return { Array<any> }
*
*/
grabWebSocketMessages() {
if (!this.recordingWebSocketMessages) {
if (!this.recordedWebSocketMessagesAtLeastOnce) {
throw new Error('Failure in test automation. You use "I.grabWebSocketMessages", but "I.startRecordingWebSocketMessages" was never called before.');
}
}
return this.webSocketMessages;
}

/**
* Resets all recorded WS messages.
*/
flushWebSocketMessages() {
this.webSocketMessages = [];
}

_getWebSocketMessage(payload) {
if (payload.errorMessage) {
return payload.errorMessage;
}

return payload.response.payloadData;
}

_getWebSocketLog(prefix, payload) {
return `${prefix} ID: ${payload.requestId} TIMESTAMP: ${payload.timestamp} (${new Date().toISOString()})\n\n${this._getWebSocketMessage(payload)}\n\n`;
}

_logWebsocketMessages(message) {
this.webSocketMessages += message;
}
}

module.exports = Puppeteer;
Expand Down
45 changes: 0 additions & 45 deletions test/helper/Playwright_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1067,51 +1067,6 @@ describe('Playwright', function () {
});
});

describe('#startRecordingWebSocketMessages, #grabWebSocketMessages, #stopRecordingWebSocketMessages', () => {
it('should throw error when calling grabWebSocketMessages before startRecordingWebSocketMessages', () => {
if (process.env.BROWSER === 'firefox') this.skip();
try {
I.amOnPage('https://websocketstest.com/');
I.waitForText('Work for You!');
I.grabWebSocketMessages();
} catch (e) {
expect(e.message).to.equal('Failure in test automation. You use "I.grabWebSocketMessages", but "I.startRecordingWebSocketMessages" was never called before.');
}
});

it('should flush the WS messages', async () => {
if (process.env.BROWSER === 'firefox') this.skip();
await I.startRecordingWebSocketMessages();
I.amOnPage('https://websocketstest.com/');
I.waitForText('Work for You!');
I.flushNetworkTraffics();
const wsMessages = I.grabWebSocketMessages();
expect(wsMessages.length).to.equal(0);
});

it('should see recording WS messages', async () => {
if (process.env.BROWSER === 'firefox') this.skip();
await I.startRecordingWebSocketMessages();
await I.amOnPage('https://websocketstest.com/');
I.waitForText('Work for You!');
const wsMessages = I.grabWebSocketMessages();
expect(wsMessages.length).to.greaterThan(0);
});

it('should not see recording WS messages', async () => {
if (process.env.BROWSER === 'firefox') this.skip();
await I.startRecordingWebSocketMessages();
await I.amOnPage('https://websocketstest.com/');
I.waitForText('Work for You!');
const wsMessages = I.grabWebSocketMessages();
await I.stopRecordingWebSocketMessages();
await I.amOnPage('https://websocketstest.com/');
I.waitForText('Work for You!');
const afterWsMessages = I.grabWebSocketMessages();
expect(wsMessages.length).to.equal(afterWsMessages.length);
});
});

describe('#makeApiRequest', () => {
it('should make 3rd party API request', async () => {
const response = await I.makeApiRequest('get', 'https://reqres.in/api/users?page=2');
Expand Down
47 changes: 47 additions & 0 deletions test/helper/webapi.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
let assert;
let expect;
import('chai').then(chai => {
assert = chai.assert;
expect = chai.expect;
});
const path = require('path');

Expand Down Expand Up @@ -1609,4 +1611,49 @@ module.exports.tests = function () {
await I.see('Textarea not focused', '#textareaMessage');
});
});

describe('#startRecordingWebSocketMessages, #grabWebSocketMessages, #stopRecordingWebSocketMessages', () => {
beforeEach(function () {
if (isHelper('TestCafe') || isHelper('WebDriver') || process.env.BROWSER === 'firefox') this.skip();
});

it('should throw error when calling grabWebSocketMessages before startRecordingWebSocketMessages', () => {
try {
I.amOnPage('https://websocketstest.com/');
I.waitForText('Work for You!');
I.grabWebSocketMessages();
} catch (e) {
expect(e.message).to.equal('Failure in test automation. You use "I.grabWebSocketMessages", but "I.startRecordingWebSocketMessages" was never called before.');
}
});

it('should flush the WS messages', async () => {
await I.startRecordingWebSocketMessages();
I.amOnPage('https://websocketstest.com/');
I.waitForText('Work for You!');
I.flushWebSocketMessages();
const wsMessages = I.grabWebSocketMessages();
expect(wsMessages.length).to.equal(0);
});

it('should see recording WS messages', async () => {
await I.startRecordingWebSocketMessages();
await I.amOnPage('https://websocketstest.com/');
I.waitForText('Work for You!');
const wsMessages = await I.grabWebSocketMessages();
expect(wsMessages.length).to.greaterThan(0);
});

it('should not see recording WS messages', async () => {
await I.startRecordingWebSocketMessages();
await I.amOnPage('https://websocketstest.com/');
I.waitForText('Work for You!');
const wsMessages = I.grabWebSocketMessages();
await I.stopRecordingWebSocketMessages();
await I.amOnPage('https://websocketstest.com/');
I.waitForText('Work for You!');
const afterWsMessages = I.grabWebSocketMessages();
expect(wsMessages.length).to.equal(afterWsMessages.length);
});
});
};

0 comments on commit 46b8bc5

Please sign in to comment.