codeceptjs 3.0.6 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +92 -8
- package/README.md +9 -1
- package/bin/codecept.js +28 -17
- package/docs/build/Appium.js +69 -0
- package/docs/build/GraphQL.js +9 -10
- package/docs/build/Playwright.js +271 -63
- package/docs/build/Protractor.js +2 -0
- package/docs/build/Puppeteer.js +56 -18
- package/docs/build/REST.js +16 -3
- package/docs/build/WebDriver.js +82 -16
- package/docs/changelog.md +93 -9
- package/docs/configuration.md +15 -2
- package/docs/email.md +8 -8
- package/docs/examples.md +3 -3
- package/docs/helpers/Appium.md +66 -68
- package/docs/helpers/MockRequest.md +3 -3
- package/docs/helpers/Playwright.md +269 -203
- package/docs/helpers/Puppeteer.md +17 -1
- package/docs/helpers/REST.md +23 -9
- package/docs/helpers/WebDriver.md +3 -2
- package/docs/locators.md +27 -0
- package/docs/mobile.md +2 -1
- package/docs/nightmare.md +0 -5
- package/docs/parallel.md +14 -7
- package/docs/playwright.md +178 -11
- package/docs/plugins.md +61 -69
- package/docs/react.md +1 -1
- package/docs/reports.md +5 -4
- package/lib/actor.js +1 -2
- package/lib/codecept.js +13 -2
- package/lib/command/definitions.js +8 -1
- package/lib/command/interactive.js +4 -2
- package/lib/command/run-multiple/collection.js +4 -0
- package/lib/container.js +3 -3
- package/lib/helper/Appium.js +41 -0
- package/lib/helper/GraphQL.js +9 -10
- package/lib/helper/Playwright.js +218 -70
- package/lib/helper/Protractor.js +2 -0
- package/lib/helper/Puppeteer.js +56 -18
- package/lib/helper/REST.js +12 -0
- package/lib/helper/WebDriver.js +82 -16
- package/lib/helper/errors/ConnectionRefused.js +1 -1
- package/lib/helper/extras/Popup.js +1 -1
- package/lib/helper/extras/React.js +44 -32
- package/lib/interfaces/gherkin.js +1 -0
- package/lib/listener/exit.js +2 -4
- package/lib/listener/helpers.js +3 -4
- package/lib/locator.js +7 -0
- package/lib/mochaFactory.js +11 -6
- package/lib/output.js +5 -2
- package/lib/plugin/allure.js +7 -18
- package/lib/plugin/commentStep.js +1 -1
- package/lib/plugin/{puppeteerCoverage.js → coverage.js} +10 -22
- package/lib/plugin/customLocator.js +2 -2
- package/lib/plugin/screenshotOnFail.js +5 -0
- package/lib/plugin/subtitles.js +88 -0
- package/lib/plugin/tryTo.js +1 -1
- package/lib/step.js +4 -2
- package/lib/ui.js +6 -2
- package/package.json +5 -4
- package/typings/index.d.ts +44 -21
- package/typings/types.d.ts +137 -16
|
@@ -101,6 +101,8 @@ This helper should be configured in codecept.json or codecept.conf.js
|
|
|
101
101
|
}
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
+
> Note: When connecting to remote browser `show` and specific `chrome` options (e.g. `headless` or `devtools`) are ignored.
|
|
105
|
+
|
|
104
106
|
#### Example #5: Target URL with provided basic authentication
|
|
105
107
|
|
|
106
108
|
```js
|
|
@@ -115,7 +117,21 @@ This helper should be configured in codecept.json or codecept.conf.js
|
|
|
115
117
|
}
|
|
116
118
|
```
|
|
117
119
|
|
|
118
|
-
|
|
120
|
+
#### Troubleshooting
|
|
121
|
+
|
|
122
|
+
Error Message: `No usable sandbox!`
|
|
123
|
+
|
|
124
|
+
When running Puppeteer on CI try to disable sandbox if you see that message
|
|
125
|
+
|
|
126
|
+
helpers: {
|
|
127
|
+
Puppeteer: {
|
|
128
|
+
url: 'http://localhost',
|
|
129
|
+
show: false,
|
|
130
|
+
chrome: {
|
|
131
|
+
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
}
|
|
119
135
|
|
|
120
136
|
## Access From Helpers
|
|
121
137
|
|
package/docs/helpers/REST.md
CHANGED
|
@@ -61,6 +61,8 @@ Executes axios request
|
|
|
61
61
|
|
|
62
62
|
- `request` **any**
|
|
63
63
|
|
|
64
|
+
Returns **[Promise][2]<any>** response
|
|
65
|
+
|
|
64
66
|
### _url
|
|
65
67
|
|
|
66
68
|
Generates url based on format sent (takes endpoint + url if latter lacks 'http')
|
|
@@ -80,7 +82,9 @@ I.sendDeleteRequest('/api/users/1');
|
|
|
80
82
|
#### Parameters
|
|
81
83
|
|
|
82
84
|
- `url` **any**
|
|
83
|
-
- `headers` **[object][
|
|
85
|
+
- `headers` **[object][3]** the headers object to be sent. By default it is sent as an empty object
|
|
86
|
+
|
|
87
|
+
Returns **[Promise][2]<any>** response
|
|
84
88
|
|
|
85
89
|
### sendGetRequest
|
|
86
90
|
|
|
@@ -93,7 +97,9 @@ I.sendGetRequest('/api/users.json');
|
|
|
93
97
|
#### Parameters
|
|
94
98
|
|
|
95
99
|
- `url` **any**
|
|
96
|
-
- `headers` **[object][
|
|
100
|
+
- `headers` **[object][3]** the headers object to be sent. By default it is sent as an empty object
|
|
101
|
+
|
|
102
|
+
Returns **[Promise][2]<any>** response
|
|
97
103
|
|
|
98
104
|
### sendPatchRequest
|
|
99
105
|
|
|
@@ -108,9 +114,11 @@ I.sendPatchRequest('/api/users.json', secret({ "email": "user@user.com" }));
|
|
|
108
114
|
|
|
109
115
|
#### Parameters
|
|
110
116
|
|
|
111
|
-
- `url` **[string][
|
|
117
|
+
- `url` **[string][4]**
|
|
112
118
|
- `payload` **any** the payload to be sent. By default it is sent as an empty object
|
|
113
|
-
- `headers` **[object][
|
|
119
|
+
- `headers` **[object][3]** the headers object to be sent. By default it is sent as an empty object
|
|
120
|
+
|
|
121
|
+
Returns **[Promise][2]<any>** response
|
|
114
122
|
|
|
115
123
|
### sendPostRequest
|
|
116
124
|
|
|
@@ -127,7 +135,9 @@ I.sendPostRequest('/api/users.json', secret({ "email": "user@user.com" }));
|
|
|
127
135
|
|
|
128
136
|
- `url` **any**
|
|
129
137
|
- `payload` **any** the payload to be sent. By default it is sent as an empty object
|
|
130
|
-
- `headers` **[object][
|
|
138
|
+
- `headers` **[object][3]** the headers object to be sent. By default it is sent as an empty object
|
|
139
|
+
|
|
140
|
+
Returns **[Promise][2]<any>** response
|
|
131
141
|
|
|
132
142
|
### sendPutRequest
|
|
133
143
|
|
|
@@ -142,9 +152,11 @@ I.sendPutRequest('/api/users.json', secret({ "email": "user@user.com" }));
|
|
|
142
152
|
|
|
143
153
|
#### Parameters
|
|
144
154
|
|
|
145
|
-
- `url` **[string][
|
|
155
|
+
- `url` **[string][4]**
|
|
146
156
|
- `payload` **any** the payload to be sent. By default it is sent as an empty object
|
|
147
|
-
- `headers` **[object][
|
|
157
|
+
- `headers` **[object][3]** the headers object to be sent. By default it is sent as an empty object
|
|
158
|
+
|
|
159
|
+
Returns **[Promise][2]<any>** response
|
|
148
160
|
|
|
149
161
|
### setRequestTimeout
|
|
150
162
|
|
|
@@ -160,6 +172,8 @@ I.setRequestTimeout(10000); // In milliseconds
|
|
|
160
172
|
|
|
161
173
|
[1]: https://github.com/axios/axios
|
|
162
174
|
|
|
163
|
-
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/
|
|
175
|
+
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
|
176
|
+
|
|
177
|
+
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
|
|
164
178
|
|
|
165
|
-
[
|
|
179
|
+
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
|
|
@@ -873,6 +873,7 @@ I.fillField({css: 'form#login input[name=username]'}, 'John');
|
|
|
873
873
|
|
|
874
874
|
This action supports [React locators](https://codecept.io/react#locators)
|
|
875
875
|
|
|
876
|
+
{{ custom }}
|
|
876
877
|
|
|
877
878
|
### forceClick
|
|
878
879
|
|
|
@@ -962,7 +963,7 @@ let hint = await I.grabAttributeFrom('#tooltip', 'title');
|
|
|
962
963
|
- `locator` **([string][19] | [object][18])** element located by CSS|XPath|strict locator.
|
|
963
964
|
- `attr` **[string][19]** attribute name.
|
|
964
965
|
|
|
965
|
-
Returns **[Promise][25]<[string][19]>** attribute
|
|
966
|
+
Returns **[Promise][25]<[string][19]>** attribute value
|
|
966
967
|
|
|
967
968
|
### grabAttributeFromAll
|
|
968
969
|
|
|
@@ -978,7 +979,7 @@ let hints = await I.grabAttributeFromAll('.tooltip', 'title');
|
|
|
978
979
|
- `locator` **([string][19] | [object][18])** element located by CSS|XPath|strict locator.
|
|
979
980
|
- `attr` **[string][19]** attribute name.
|
|
980
981
|
|
|
981
|
-
Returns **[Promise][25]<[Array][27]<[string][19]>>** attribute
|
|
982
|
+
Returns **[Promise][25]<[Array][27]<[string][19]>>** attribute value
|
|
982
983
|
|
|
983
984
|
### grabBrowserLogs
|
|
984
985
|
|
package/docs/locators.md
CHANGED
|
@@ -297,8 +297,35 @@ codeceptjs.locator.addFilter((providedLocator, locatorObj) => {
|
|
|
297
297
|
```
|
|
298
298
|
New locator strategy is ready to use:
|
|
299
299
|
|
|
300
|
+
|
|
300
301
|
```js
|
|
301
302
|
I.click('=Login');
|
|
302
303
|
```
|
|
303
304
|
|
|
305
|
+
#### Custom Strategy Locators
|
|
306
|
+
|
|
307
|
+
CodeceptJS provides the option to specify custom locators that uses Custom Locator Strategies defined in the WebDriver configuration. It uses the WebDriverIO's [custom$](https://webdriver.io/docs/api/browser/custom$.html) locators internally to locate the elements on page.
|
|
308
|
+
To use the defined Custom Locator Strategy add your custom strategy to your configuration.
|
|
309
|
+
|
|
310
|
+
```js
|
|
311
|
+
// in codecept.conf.js
|
|
312
|
+
|
|
313
|
+
const myStrat = (selector) => {
|
|
314
|
+
return document.querySelectorAll(selector)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// under WebDriver Helpers Configuration
|
|
318
|
+
WebDriver: {
|
|
319
|
+
...
|
|
320
|
+
customLocatorStrategies: {
|
|
321
|
+
custom: myStrat
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
```js
|
|
327
|
+
I.click({custom: 'my-shadow-element-unique-css'})
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
|
|
304
331
|
> For more details on locator object see [Locator](https://github.com/codeceptjs/CodeceptJS/blob/master/lib/locator.js) class implementation.
|
package/docs/mobile.md
CHANGED
|
@@ -114,7 +114,7 @@ If you wish to use BrowserStack's [Automated Mobile App Testing](https://www.bro
|
|
|
114
114
|
|
|
115
115
|
```js
|
|
116
116
|
helpers: {
|
|
117
|
-
Appium:
|
|
117
|
+
Appium: {
|
|
118
118
|
app: "bs://<hashed app-id>",
|
|
119
119
|
host: "hub-cloud.browserstack.com",
|
|
120
120
|
port: 4444,
|
|
@@ -122,6 +122,7 @@ helpers: {
|
|
|
122
122
|
user: "BROWSERSTACK_USER",
|
|
123
123
|
key: "BROWSERSTACK_KEY",
|
|
124
124
|
device: "iPhone 7"
|
|
125
|
+
}
|
|
125
126
|
}
|
|
126
127
|
```
|
|
127
128
|
Here is the full list of [capabilities](https://www.browserstack.com/app-automate/capabilities).
|
package/docs/nightmare.md
CHANGED
|
@@ -221,8 +221,3 @@ I.seeAttributeContains('#main img', 'src', '/cat.jpg');
|
|
|
221
221
|
This sample assertion used `_locate` helper method which searched for elements
|
|
222
222
|
by CSS/XPath or a strict locator. Then `browser.evaluate` method was called to
|
|
223
223
|
use locate found elements on a page and return attribute from the first of them.
|
|
224
|
-
|
|
225
|
-
## Additional Links
|
|
226
|
-
|
|
227
|
-
* [Nightmare Tutorial](http://codenroll.it/acceptance-testing-with-codecept-js/) by jploskonka.
|
|
228
|
-
|
package/docs/parallel.md
CHANGED
|
@@ -26,7 +26,7 @@ This command is similar to `run`, however, steps output can't be shown in worker
|
|
|
26
26
|
|
|
27
27
|
Each worker spins an instance of CodeceptJS, executes a group of tests, and sends back report to the main process.
|
|
28
28
|
|
|
29
|
-
By default the tests are assigned one by one to the
|
|
29
|
+
By default the tests are assigned one by one to the available workers this may lead to multiple execution of `BeforeSuite()`. Use the option `--suites` to assigne the suites one by one to the workers.
|
|
30
30
|
|
|
31
31
|
```sh
|
|
32
32
|
npx codeceptjs run-workers --suites 2
|
|
@@ -196,22 +196,23 @@ workers.on(event.all.result, (status, completedTests, workerStats) => {
|
|
|
196
196
|
|
|
197
197
|
## Sharing Data Between Workers
|
|
198
198
|
|
|
199
|
-
NodeJS Workers can communicate between each other via messaging system. It may happen that you want to pass some data from one of workers to other. For instance, you may want to share user credentials accross all tests. Data will be appended to a container.
|
|
199
|
+
NodeJS Workers can communicate between each other via messaging system. It may happen that you want to pass some data from one of the workers to other. For instance, you may want to share user credentials accross all tests. Data will be appended to a container.
|
|
200
200
|
|
|
201
|
-
However, you can't access uninitialized data from a container, so to start, you need to
|
|
201
|
+
However, you can't access uninitialized data from a container, so to start, you need to initialize data first. Inside `bootstrap` function of the config we execute the `share` to initialize value:
|
|
202
202
|
|
|
203
203
|
|
|
204
204
|
```js
|
|
205
205
|
// inside codecept.conf.js
|
|
206
206
|
exports.config = {
|
|
207
207
|
bootstrap() {
|
|
208
|
-
// append empty userData to container
|
|
209
|
-
share({ userData: false }
|
|
208
|
+
// append empty userData to container
|
|
209
|
+
share({ userData: false });
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
```
|
|
213
|
+
|
|
213
214
|
Now each worker has `userData` inside a container. However, it is empty.
|
|
214
|
-
When you obtain real data in one of tests you can this data accross tests. Use `inject` function to access data inside a container:
|
|
215
|
+
When you obtain real data in one of the tests you can now `share` this data accross tests. Use `inject` function to access data inside a container:
|
|
215
216
|
|
|
216
217
|
```js
|
|
217
218
|
// get current value of userData
|
|
@@ -220,6 +221,12 @@ let { userData } = inject();
|
|
|
220
221
|
if (!userData) {
|
|
221
222
|
userData = { name: 'user', password: '123456' };
|
|
222
223
|
// now new userData will be shared accross all workers
|
|
223
|
-
share(userData);
|
|
224
|
+
share({userData : userData});
|
|
224
225
|
}
|
|
225
226
|
```
|
|
227
|
+
|
|
228
|
+
If you want to share data only within same worker, and not across all workers, you need to add option `local: true` every time you run `share`
|
|
229
|
+
|
|
230
|
+
```js
|
|
231
|
+
share({ userData: false }, {local: true });
|
|
232
|
+
```
|
package/docs/playwright.md
CHANGED
|
@@ -3,11 +3,11 @@ permalink: /playwright
|
|
|
3
3
|
title: Testing with Playwright
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Testing with Playwright
|
|
6
|
+
# Testing with Playwright
|
|
7
7
|
|
|
8
8
|
Playwright is a Node library to automate the [Chromium](https://www.chromium.org/Home), [WebKit](https://webkit.org/) and [Firefox](https://www.mozilla.org/en-US/firefox/new/) browsers as well as [Electron](https://www.electronjs.org/) apps with a single API. It enables **cross-browser** web automation that is **ever-green**, **capable**, **reliable** and **fast**.
|
|
9
9
|
|
|
10
|
-
Playwright was built similarly to [Puppeteer](https://github.com/puppeteer/puppeteer), using its API and so is very different in usage. However, Playwright has cross browser support with better design for test
|
|
10
|
+
Playwright was built similarly to [Puppeteer](https://github.com/puppeteer/puppeteer), using its API and so is very different in usage. However, Playwright has cross browser support with better design for test automation.
|
|
11
11
|
|
|
12
12
|
Take a look at a sample test:
|
|
13
13
|
|
|
@@ -270,7 +270,7 @@ Playwright can emulate browsers of mobile devices. Instead of paying for expensi
|
|
|
270
270
|
|
|
271
271
|
Device emulation can be enabled in CodeceptJS globally in a config or per session.
|
|
272
272
|
|
|
273
|
-
Playwright contains a [list of predefined devices](https://github.com/
|
|
273
|
+
Playwright contains a [list of predefined devices](https://github.com/microsoft/playwright/blob/master/src/server/deviceDescriptors.js) to emulate, for instance this is how you can enable iPhone 6 emulation for all tests:
|
|
274
274
|
|
|
275
275
|
```js
|
|
276
276
|
const { devices } = require('playwright');
|
|
@@ -282,7 +282,7 @@ helpers: {
|
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
```
|
|
285
|
-
To adjust browser settings you can pass [custom options](https://github.com/microsoft/playwright/blob/master/docs/api.md
|
|
285
|
+
To adjust browser settings you can pass [custom options](https://github.com/microsoft/playwright/blob/master/docs/src/api/class-browsercontext.md)
|
|
286
286
|
|
|
287
287
|
```js
|
|
288
288
|
helpers: {
|
|
@@ -322,30 +322,197 @@ Playwright can be added to GitHub Actions using [official action](https://github
|
|
|
322
322
|
|
|
323
323
|
## Accessing Playwright API
|
|
324
324
|
|
|
325
|
-
To get [Playwright API](https://
|
|
325
|
+
To get [Playwright API](https://playwright.dev/docs/api/class-playwright) inside a test use `I.usePlaywrightTo` method with a callback.
|
|
326
|
+
|
|
327
|
+
`usePlaywrightTo` passes in an instance of Playwright helper from which you can obtain access to main Playwright classes:
|
|
328
|
+
|
|
329
|
+
* [`browser`](https://playwright.dev/docs/api/class-browser)
|
|
330
|
+
* [`browserContext`](https://playwright.dev/docs/api/class-browsercontext)
|
|
331
|
+
* [`page`](https://playwright.dev/docs/api/class-page)
|
|
332
|
+
|
|
326
333
|
To keep test readable provide a description of a callback inside the first parameter.
|
|
327
334
|
|
|
328
335
|
```js
|
|
329
|
-
I.usePlaywrightTo('emulate offline mode', async ({ browser,
|
|
336
|
+
I.usePlaywrightTo('emulate offline mode', async ({ browser, browserContext, page }) => {
|
|
330
337
|
// use browser, page, context objects inside this function
|
|
331
|
-
await
|
|
338
|
+
await browserContext.setOffline(true);
|
|
332
339
|
});
|
|
333
340
|
```
|
|
334
341
|
|
|
335
342
|
Playwright commands are asynchronous so a callback function must be async.
|
|
336
343
|
|
|
337
|
-
A Playwright helper is passed as argument for callback, so you can combine
|
|
344
|
+
A Playwright helper is passed as argument for callback, so you can combine Playwright API with CodeceptJS API:
|
|
338
345
|
|
|
339
346
|
```js
|
|
340
347
|
I.usePlaywrightTo('emulate offline mode', async (Playwright) => {
|
|
341
348
|
// access internal objects browser, page, context of helper
|
|
342
|
-
await Playwright.
|
|
349
|
+
await Playwright.browserContext.setOffline(true);
|
|
343
350
|
// call a method of helper, await is required here
|
|
344
351
|
await Playwright.click('Reload');
|
|
345
352
|
});
|
|
346
353
|
|
|
347
354
|
```
|
|
348
355
|
|
|
356
|
+
## Mocking Network Requests <Badge text="Since 3.1" type="warning"/>
|
|
357
|
+
|
|
358
|
+
Network requests & responses can be mocked and modified. Use `mockRequest` which strictly follows [Playwright's `route` API](https://playwright.dev/docs/api/class-browsercontext#browser-context-route).
|
|
359
|
+
|
|
360
|
+
```js
|
|
361
|
+
I.mockRoute('/api/**', route => {
|
|
362
|
+
if (route.request().postData().includes('my-string'))
|
|
363
|
+
route.fulfill({ body: 'mocked-data' });
|
|
364
|
+
else
|
|
365
|
+
route.continue();
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
I.mockRoute('**/*.{png,jpg,jpeg}', route => route.abort());
|
|
369
|
+
|
|
370
|
+
// To disable mocking for a route call `stopMockingRoute`
|
|
371
|
+
// for previously mocked URL
|
|
372
|
+
I.stopMockingRoute('**/*.{png,jpg,jpeg}'
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
To master request intercepting [use `route` object](https://playwright.dev/docs/api/class-route) object passed into mock request handler.
|
|
376
|
+
|
|
377
|
+
## Video <Badge text="Since 3.1" type="warning"/>
|
|
378
|
+
|
|
379
|
+
Playwright may record videos for failed tests. This can be enabled in a config with `video: true` option:
|
|
380
|
+
|
|
381
|
+
```js
|
|
382
|
+
exports.config = {
|
|
383
|
+
helpers: {
|
|
384
|
+
Playwright: {
|
|
385
|
+
// ...
|
|
386
|
+
video: true
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
When a test fails and video was enabled a video file is shown under the `artifacts` section in the error message:
|
|
392
|
+
|
|
393
|
+
```
|
|
394
|
+
-- FAILURES:
|
|
395
|
+
|
|
396
|
+
1) GitHub
|
|
397
|
+
open:
|
|
398
|
+
|
|
399
|
+
Scenario Steps:
|
|
400
|
+
- I.amOnPage("https://gothub11.com/search") at Test.<anonymous> (./github_test.js:16:5)
|
|
401
|
+
|
|
402
|
+
Artifacts:
|
|
403
|
+
- screenshot: /home/davert/projects/codeceptjs/examples/output/open.failed.png
|
|
404
|
+
- video: /home/davert/projects/codeceptjs/examples/output/videos/5ecf6aaa78865bce14d271b55de964fd.webm
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Open video and use it to debug a failed test case. Video helps when running tests on CI. Configure your CI system to enable artifacts storage for `output/video` and review videos of failed test case to understand failures.
|
|
408
|
+
|
|
409
|
+
## Trace <Badge text="Since 3.1" type="warning"/>
|
|
410
|
+
|
|
411
|
+
If video is not enough to descover why a test failed a [trace](https://playwright.dev/docs/trace-viewer/) can be recorded.
|
|
412
|
+
|
|
413
|
+

|
|
414
|
+
|
|
415
|
+
Inside a trace you get screenshots, DOM snapshots, console logs, network requests and playwright commands logged and showed on a timeline. This may help for a deep debug of a failed test cases. Trace file is saved into ZIP archive and can be viewed with Trace Viewer built into Playwright.
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
Enable trace with `trace: true` option in a config:
|
|
419
|
+
|
|
420
|
+
```js
|
|
421
|
+
exports.config = {
|
|
422
|
+
helpers: {
|
|
423
|
+
Playwright: {
|
|
424
|
+
// ...
|
|
425
|
+
trace: true
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
When a test fails and trace was enabled, a trace file is shown under the `artifacts` section in the error message:
|
|
432
|
+
|
|
433
|
+
```
|
|
434
|
+
-- FAILURES:
|
|
435
|
+
|
|
436
|
+
1) GitHub
|
|
437
|
+
open:
|
|
438
|
+
|
|
439
|
+
Scenario Steps:
|
|
440
|
+
- I.amOnPage("https://gothub11.com/search") at Test.<anonymous> (./github_test.js:16:5)
|
|
441
|
+
|
|
442
|
+
Artifacts:
|
|
443
|
+
- screenshot: /home/davert/projects/codeceptjs/examples/output/open.failed.png
|
|
444
|
+
- trace: /home/davert/projects/codeceptjs/examples/output/trace/open.zip
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
Use Playwright's trace viewer to analyze the trace:
|
|
448
|
+
|
|
449
|
+
```
|
|
450
|
+
npx playwright show-trace {path-to-trace-file}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
For instance, this is how you can read a trace for a failed test from an example:
|
|
454
|
+
|
|
455
|
+
```
|
|
456
|
+
npx playwright show-trace /home/davert/projects/codeceptjs/examples/output/trace/open.zip
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
## Capturing code coverage
|
|
460
|
+
|
|
461
|
+
Code coverage can be captured, by enabling the `coverage` plugin in `codecept.config.js`.
|
|
462
|
+
|
|
463
|
+
```js
|
|
464
|
+
{
|
|
465
|
+
plugins: {
|
|
466
|
+
coverage: {
|
|
467
|
+
enabled: true
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
Once all the tests are completed, `codecept` will create and store coverage in `output/coverage` folder, as shown below.
|
|
474
|
+
|
|
475
|
+

|
|
476
|
+
|
|
477
|
+
### Converting `playwright` coverage to `istanbul` coverage
|
|
478
|
+
|
|
479
|
+
To convert coverage generated from `playwright` to `istanbul` coverage, you first need to install
|
|
480
|
+
- [`v8-to-istanbul`](https://www.npmjs.com/package/v8-to-istanbul)
|
|
481
|
+
|
|
482
|
+
Once installed, convert the coverage to a format which `istanbul` can recognize, by writing a script as shown below.
|
|
483
|
+
|
|
484
|
+
```js
|
|
485
|
+
const v8toIstanbul = require('v8-to-istanbul');
|
|
486
|
+
// read all the coverage file from output/coverage folder
|
|
487
|
+
const coverage = require('./output/coverage/Visit_Home_1630335005.coverage.json');
|
|
488
|
+
const fs = require('fs/promises');
|
|
489
|
+
|
|
490
|
+
(async () => {
|
|
491
|
+
for (const entry of coverage) {
|
|
492
|
+
// Used to get file name
|
|
493
|
+
const file = entry.url.match(/(?:http(s)*:\/\/.*\/)(?<file>.*)/);
|
|
494
|
+
const converter = new v8toIstanbul(file.groups.file, 0, {
|
|
495
|
+
source: entry.source
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
await converter.load();
|
|
499
|
+
converter.applyCoverage(entry.functions);
|
|
500
|
+
|
|
501
|
+
// Store converted coverage file which can later be used to generate report
|
|
502
|
+
await fs.writeFile('./coverage/final.json', JSON.stringify(converter.toIstanbul(), null, 2));
|
|
503
|
+
}
|
|
504
|
+
})();
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
Once the istanbul compatible coverage is generated, use [`nyc`](https://www.npmjs.com/package/nyc) to generate your coverage report in your desired format.
|
|
508
|
+
|
|
509
|
+
```
|
|
510
|
+
npx nyc report --reporter text -t coverage
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
The above command will generate a text report like shown below.
|
|
514
|
+
|
|
515
|
+

|
|
349
516
|
## Extending Helper
|
|
350
517
|
|
|
351
518
|
To create custom `I.*` commands using Playwright API you need to create a custom helper.
|
|
@@ -385,6 +552,6 @@ async setPermissions() {
|
|
|
385
552
|
}
|
|
386
553
|
```
|
|
387
554
|
|
|
388
|
-
> [▶ Learn more about BrowserContext](https://github.com/microsoft/playwright/blob/master/docs/api
|
|
555
|
+
> [▶ Learn more about BrowserContext](https://github.com/microsoft/playwright/blob/master/docs/src/api/class-browsercontext.md)
|
|
389
556
|
|
|
390
|
-
> [▶ Learn more about Helpers](
|
|
557
|
+
> [▶ Learn more about Helpers](https://codecept.io/helpers/)
|