Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ppt): websocket messages #4264

Merged
merged 3 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
});
});
};
Loading