Skip to content

feat: mock route for ppt #4262

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

Merged
merged 1 commit into from
Mar 18, 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: 2 additions & 2 deletions docs/helpers/Playwright.md
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,7 @@ This method allows intercepting and mocking requests & responses. [Learn more ab
#### Parameters

- `url` **([string][9] | [RegExp][11])?** URL, regex or pattern for to match URL
- `handler` **[function][21]?** a function to process reques
- `handler` **[function][21]?** a function to process request

### mockTraffic

Expand Down Expand Up @@ -2230,7 +2230,7 @@ If no handler is passed, all mock requests for the rote are disabled.
#### Parameters

- `url` **([string][9] | [RegExp][11])?** URL, regex or pattern for to match URL
- `handler` **[function][21]?** a function to process reques
- `handler` **[function][21]?** a function to process request

### stopRecordingTraffic

Expand Down
91 changes: 61 additions & 30 deletions docs/helpers/Puppeteer.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,26 @@ Type: [object][4]

- `url` **[string][6]** base url of website to be tested
- `basicAuth` **[object][4]?** (optional) the basic authentication to pass to base url. Example: {username: 'username', password: 'password'}
- `show` **[boolean][20]?** show Google Chrome window for debug.
- `restart` **[boolean][20]?** restart browser between tests.
- `disableScreenshots` **[boolean][20]?** don't save screenshot on failure.
- `fullPageScreenshots` **[boolean][20]?** make full page screenshots on failure.
- `uniqueScreenshotNames` **[boolean][20]?** option to prevent screenshot override if you have scenarios with the same name in different suites.
- `trace` **[boolean][20]?** record [tracing information][24] with screenshots.
- `keepTraceForPassedTests` **[boolean][20]?** save trace for passed tests.
- `keepBrowserState` **[boolean][20]?** keep browser state between tests when `restart` is set to false.
- `keepCookies` **[boolean][20]?** keep cookies between tests when `restart` is set to false.
- `show` **[boolean][22]?** show Google Chrome window for debug.
- `restart` **[boolean][22]?** restart browser between tests.
- `disableScreenshots` **[boolean][22]?** don't save screenshot on failure.
- `fullPageScreenshots` **[boolean][22]?** make full page screenshots on failure.
- `uniqueScreenshotNames` **[boolean][22]?** option to prevent screenshot override if you have scenarios with the same name in different suites.
- `trace` **[boolean][22]?** record [tracing information][26] with screenshots.
- `keepTraceForPassedTests` **[boolean][22]?** save trace for passed tests.
- `keepBrowserState` **[boolean][22]?** keep browser state between tests when `restart` is set to false.
- `keepCookies` **[boolean][22]?** keep cookies between tests when `restart` is set to false.
- `waitForAction` **[number][10]?** how long to wait after click, doubleClick or PressKey actions in ms. Default: 100.
- `waitForNavigation` **[string][6]?** when to consider navigation succeeded. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API][23]. Array values are accepted as well.
- `waitForNavigation` **[string][6]?** when to consider navigation succeeded. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API][25]. Array values are accepted as well.
- `pressKeyDelay` **[number][10]?** delay between key presses in ms. Used when calling Puppeteers page.type(...) in fillField/appendField
- `getPageTimeout` **[number][10]?** config option to set maximum navigation time in milliseconds. If the timeout is set to 0, then timeout will be disabled.
- `waitForTimeout` **[number][10]?** default wait* timeout in ms.
- `windowSize` **[string][6]?** default window size. Set a dimension in format WIDTHxHEIGHT like `640x480`.
- `userAgent` **[string][6]?** user-agent string.
- `manualStart` **[boolean][20]?** do not start browser before a test, start it manually inside a helper with `this.helpers["Puppeteer"]._startBrowser()`.
- `manualStart` **[boolean][22]?** do not start browser before a test, start it manually inside a helper with `this.helpers["Puppeteer"]._startBrowser()`.
- `browser` **[string][6]?** can be changed to `firefox` when using [puppeteer-firefox][2].
- `chrome` **[object][4]?** pass additional [Puppeteer run options][25].
- `highlightElement` **[boolean][20]?** highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
- `chrome` **[object][4]?** pass additional [Puppeteer run options][27].
- `highlightElement` **[boolean][22]?** highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).



Expand Down Expand Up @@ -1255,6 +1255,21 @@ I.seeFile('avatar.jpg');

- `downloadPath` **[string][6]** change this parameter to set another directory for saving

### mockRoute

Mocks network request using [`Request Interception`][17]

```js
I.mockRoute(/(.png$)|(.jpg$)/, route => route.abort());
```

This method allows intercepting and mocking requests & responses. [Learn more about it][17]

#### Parameters

- `url` **([string][6] | [RegExp][18])?** URL, regex or pattern for to match URL
- `handler` **[function][12]?** a function to process request

### moveCursorTo

Moves cursor to element matched by locator.
Expand Down Expand Up @@ -1287,11 +1302,11 @@ I.openNewTab();

### pressKey

_Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([GoogleChrome/puppeteer#1313][17]).
_Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([GoogleChrome/puppeteer#1313][19]).

Presses a key in the browser (on a focused element).

_Hint:_ For populating text field or textarea, it is recommended to use [`fillField`][18].
_Hint:_ For populating text field or textarea, it is recommended to use [`fillField`][20].

```js
I.pressKey('Backspace');
Expand Down Expand Up @@ -1358,7 +1373,7 @@ Returns **void** automatically synchronized promise through #recorder

Presses a key in the browser and leaves it in a down state.

To make combinations with modifier key and user operation (e.g. `'Control'` + [`click`][19]).
To make combinations with modifier key and user operation (e.g. `'Control'` + [`click`][21]).

```js
I.pressKeyDown('Control');
Expand All @@ -1376,7 +1391,7 @@ Returns **void** automatically synchronized promise through #recorder

Releases a key in the browser which was previously set to a down state.

To make combinations with modifier key and user operation (e.g. `'Control'` + [`click`][19]).
To make combinations with modifier key and user operation (e.g. `'Control'` + [`click`][21]).

```js
I.pressKeyDown('Control');
Expand Down Expand Up @@ -1470,7 +1485,7 @@ I.saveScreenshot('debug.png', true) //resizes to available scrollHeight and scro
#### Parameters

- `fileName` **[string][6]** file name to save.
- `fullPage` **[boolean][20]** (optional, `false` by default) flag to enable fullscreen screenshot mode.
- `fullPage` **[boolean][22]** (optional, `false` by default) flag to enable fullscreen screenshot mode.

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

Expand Down Expand Up @@ -1862,6 +1877,18 @@ I.setPuppeteerRequestHeaders({

- `customHeaders` **[object][4]** headers to set

### stopMockingRoute

Stops network mocking created by `mockRoute`.

```js
I.stopMockingRoute(/(.png$)|(.jpg$)/);
```

#### Parameters

- `url` **([string][6] | [RegExp][18])?** URL, regex or pattern for to match URL

### switchTo

Switches frame or in case of null locator reverts to parent.
Expand Down Expand Up @@ -1907,7 +1934,7 @@ I.switchToPreviousTab(2);

Types out the given text into an active field.
To slow down typing use a second parameter, to set interval between key presses.
_Note:_ Should be used when [`fillField`][18] is not an option.
_Note:_ Should be used when [`fillField`][20] is not an option.

```js
// passing in a string
Expand Down Expand Up @@ -1958,7 +1985,7 @@ Use Puppeteer API inside a test.
First argument is a description of an action.
Second argument is async function that gets this helper as parameter.

{ [`page`][21], [`browser`][22] } from Puppeteer API are available.
{ [`page`][23], [`browser`][24] } from Puppeteer API are available.

```js
I.usePuppeteerTo('emulate offline mode', async ({ page }) {
Expand Down Expand Up @@ -2110,7 +2137,7 @@ Returns **void** automatically synchronized promise through #recorder

Waits for navigation to finish. By default, takes configured `waitForNavigation` option.

See [Puppeteer's reference][23]
See [Puppeteer's reference][25]

#### Parameters

Expand Down Expand Up @@ -2313,20 +2340,24 @@ Returns **void** automatically synchronized promise through #recorder

[16]: https://codecept.io/helpers/FileSystem

[17]: https://github.com/GoogleChrome/puppeteer/issues/1313
[17]: https://pptr.dev/next/guides/request-interception

[18]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp

[19]: https://github.com/GoogleChrome/puppeteer/issues/1313

[18]: #fillfield
[20]: #fillfield

[19]: #click
[21]: #click

[20]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[22]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean

[21]: https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-page
[23]: https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-page

[22]: https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-browser
[24]: https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-browser

[23]: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagewaitfornavigationoptions
[25]: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagewaitfornavigationoptions

[24]: https://pptr.dev/api/puppeteer.tracing
[26]: https://pptr.dev/api/puppeteer.tracing

[25]: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions
[27]: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions
54 changes: 15 additions & 39 deletions docs/puppeteer.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,52 +216,28 @@ await eachElement(

> ℹ Learn more about [eachElement plugin](/plugins/#eachelement)

## Mocking Requests
## Mocking Network Requests <Badge text="Since 3.5.16" type="warning"/>

Web application sends various requests to local services (Rest API, GraphQL) or to 3rd party services (CDNS, Google Analytics, etc).
When you run tests with Puppeteer you can control those requests by mocking them. For instance, you can speed up your tests by blocking trackers, Google Analytics, and other services you don't control.

Also you can replace real request with a one explicitly defined. This is useful when you want to isolate application testing from a backend. For instance, if you don't want to save data to database, and you know the request which performs save, you can mock the request, so application will treat this as valid response, but no data will be actually saved.

To mock requests enable additional helper [MockRequest](/helpers/MockRequest) (which is based on Polly.js).
Network requests & responses can be mocked and modified. Use `mockRoute` which strictly follows [Puppeteer's `setRequestInterception` API](https://pptr.dev/next/api/puppeteer.page.setrequestinterception).

```js
helpers: {
Puppeteer: {
// regular Puppeteer config here
},
MockRequest: {}
}
```

And install additional packages:

```
npm i @pollyjs/core @pollyjs/adapter-puppeteer --save-dev
```

After an installation function `mockRequest` will be added to `I` object. You can use it to explicitly define which requests to block and which response they should return instead:

```js
// block all Google Analytics calls
I.mockRequest('/google-analytics/*path', 200);
// return an empty successful response
I.mockRequest('GET', '/api/users', 200);
// block post requests to /api/users and return predefined object
I.mockRequest('POST', '/api/users', { user: 'davert' });
// return error request with body
I.mockRequest('GET', '/api/users/1', 404, { error: 'User not found' });
```

> See [`mockRequest` API](/helpers/MockRequest#mockrequest)
I.mockRoute('https://reqres.in/api/comments/1', request => {
request.respond({
status: 200,
headers: { 'Access-Control-Allow-Origin': '*' },
contentType: 'application/json',
body: '{"name": "this was mocked" }',
});
})

To see `mockRequest` method in intellisense auto completion don't forget to run `codeceptjs def` command:
I.mockRoute('**/*.{png,jpg,jpeg}', route => route.abort());

```
npx codeceptjs def
// To disable mocking for a route call `stopMockingRoute`
// for previously mocked URL
I.stopMockingRoute('**/*.{png,jpg,jpeg}'
```

Mocking rules will be kept while a test is running. To stop mocking use `I.stopMocking()` command
To master request intercepting [use `HTTPRequest` object](https://pptr.dev/next/api/puppeteer.httprequest) object passed into mock request handler.


## Accessing Puppeteer API
Expand Down
4 changes: 2 additions & 2 deletions lib/helper/Playwright.js
Original file line number Diff line number Diff line change
Expand Up @@ -2957,7 +2957,7 @@ class Playwright extends Helper {
* This method allows intercepting and mocking requests & responses. [Learn more about it](https://playwright.dev/docs/network#handle-requests)
*
* @param {string|RegExp} [url] URL, regex or pattern for to match URL
* @param {function} [handler] a function to process reques
* @param {function} [handler] a function to process request
*/
async mockRoute(url, handler) {
return this.browserContext.route(...arguments);
Expand All @@ -2973,7 +2973,7 @@ class Playwright extends Helper {
* If no handler is passed, all mock requests for the rote are disabled.
*
* @param {string|RegExp} [url] URL, regex or pattern for to match URL
* @param {function} [handler] a function to process reques
* @param {function} [handler] a function to process request
*/
async stopMockingRoute(url, handler) {
return this.browserContext.unroute(...arguments);
Expand Down
48 changes: 48 additions & 0 deletions lib/helper/Puppeteer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2459,6 +2459,54 @@ class Puppeteer extends Helper {
if (prop) return rect[prop];
return rect;
}

/**
* Mocks network request using [`Request Interception`](https://pptr.dev/next/guides/request-interception)
*
* ```js
* I.mockRoute(/(\.png$)|(\.jpg$)/, route => route.abort());
* ```
* This method allows intercepting and mocking requests & responses. [Learn more about it](https://pptr.dev/next/guides/request-interception)
*
* @param {string|RegExp} [url] URL, regex or pattern for to match URL
* @param {function} [handler] a function to process request
*/
async mockRoute(url, handler) {
await this.page.setRequestInterception(true);

this.page.on('request', interceptedRequest => {
if (interceptedRequest.url().match(url)) {
// @ts-ignore
handler(interceptedRequest);
} else {
interceptedRequest.continue();
}
});
}

/**
* Stops network mocking created by `mockRoute`.
*
* ```js
* I.stopMockingRoute(/(\.png$)|(\.jpg$)/);
* ```
*
* @param {string|RegExp} [url] URL, regex or pattern for to match URL
*/
async stopMockingRoute(url) {
await this.page.setRequestInterception(true);

this.page.off('request');

// Resume normal request handling for the given URL
this.page.on('request', interceptedRequest => {
if (interceptedRequest.url().includes(url)) {
interceptedRequest.continue();
} else {
interceptedRequest.continue();
}
});
}
}

module.exports = Puppeteer;
Expand Down
20 changes: 20 additions & 0 deletions test/helper/Puppeteer_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,26 @@ describe('Puppeteer', function () {
assert.equal('TestEd Beta 2.0', title);
});
});

describe('#mockRoute, #stopMockingRoute', () => {
it('should mock a route', async () => {
await I.amOnPage('/form/fetch_call');
await I.mockRoute('https://reqres.in/api/comments/1', request => {
request.respond({
status: 200,
headers: { 'Access-Control-Allow-Origin': '*' },
contentType: 'application/json',
body: '{"name": "this was mocked" }',
});
});
await I.click('GET COMMENTS');
await I.see('this was mocked');
await I.stopMockingRoute('https://reqres.in/api/comments/1');
await I.click('GET COMMENTS');
await I.see('data');
await I.dontSee('this was mocked');
});
});
});

let remoteBrowser;
Expand Down