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.
Files changed (62) hide show
  1. package/CHANGELOG.md +92 -8
  2. package/README.md +9 -1
  3. package/bin/codecept.js +28 -17
  4. package/docs/build/Appium.js +69 -0
  5. package/docs/build/GraphQL.js +9 -10
  6. package/docs/build/Playwright.js +271 -63
  7. package/docs/build/Protractor.js +2 -0
  8. package/docs/build/Puppeteer.js +56 -18
  9. package/docs/build/REST.js +16 -3
  10. package/docs/build/WebDriver.js +82 -16
  11. package/docs/changelog.md +93 -9
  12. package/docs/configuration.md +15 -2
  13. package/docs/email.md +8 -8
  14. package/docs/examples.md +3 -3
  15. package/docs/helpers/Appium.md +66 -68
  16. package/docs/helpers/MockRequest.md +3 -3
  17. package/docs/helpers/Playwright.md +269 -203
  18. package/docs/helpers/Puppeteer.md +17 -1
  19. package/docs/helpers/REST.md +23 -9
  20. package/docs/helpers/WebDriver.md +3 -2
  21. package/docs/locators.md +27 -0
  22. package/docs/mobile.md +2 -1
  23. package/docs/nightmare.md +0 -5
  24. package/docs/parallel.md +14 -7
  25. package/docs/playwright.md +178 -11
  26. package/docs/plugins.md +61 -69
  27. package/docs/react.md +1 -1
  28. package/docs/reports.md +5 -4
  29. package/lib/actor.js +1 -2
  30. package/lib/codecept.js +13 -2
  31. package/lib/command/definitions.js +8 -1
  32. package/lib/command/interactive.js +4 -2
  33. package/lib/command/run-multiple/collection.js +4 -0
  34. package/lib/container.js +3 -3
  35. package/lib/helper/Appium.js +41 -0
  36. package/lib/helper/GraphQL.js +9 -10
  37. package/lib/helper/Playwright.js +218 -70
  38. package/lib/helper/Protractor.js +2 -0
  39. package/lib/helper/Puppeteer.js +56 -18
  40. package/lib/helper/REST.js +12 -0
  41. package/lib/helper/WebDriver.js +82 -16
  42. package/lib/helper/errors/ConnectionRefused.js +1 -1
  43. package/lib/helper/extras/Popup.js +1 -1
  44. package/lib/helper/extras/React.js +44 -32
  45. package/lib/interfaces/gherkin.js +1 -0
  46. package/lib/listener/exit.js +2 -4
  47. package/lib/listener/helpers.js +3 -4
  48. package/lib/locator.js +7 -0
  49. package/lib/mochaFactory.js +11 -6
  50. package/lib/output.js +5 -2
  51. package/lib/plugin/allure.js +7 -18
  52. package/lib/plugin/commentStep.js +1 -1
  53. package/lib/plugin/{puppeteerCoverage.js → coverage.js} +10 -22
  54. package/lib/plugin/customLocator.js +2 -2
  55. package/lib/plugin/screenshotOnFail.js +5 -0
  56. package/lib/plugin/subtitles.js +88 -0
  57. package/lib/plugin/tryTo.js +1 -1
  58. package/lib/step.js +4 -2
  59. package/lib/ui.js +6 -2
  60. package/package.json +5 -4
  61. package/typings/index.d.ts +44 -21
  62. 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
- Note: When connecting to remote browser `show` and specific `chrome` options (e.g. `headless` or `devtools`) are ignored.
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
 
@@ -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][2]** the headers object to be sent. By default it is sent as an empty 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][2]** the headers object to be sent. By default it is sent as an empty 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][3]**
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][2]** the headers object to be sent. By default it is sent as an empty 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][2]** the headers object to be sent. By default it is sent as an empty 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][3]**
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][2]** the headers object to be sent. By default it is sent as an empty 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/Object
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
- [3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
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 valueAppium: can be used for apps only with several values ("contentDescription", "text", "className", "resourceId")
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 valueAppium: can be used for apps only with several values ("contentDescription", "text", "className", "resourceId")
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 avaible workers this may lead to multiple execution of `BeforeSuite()`. Use the option `--suites` to assigne the suites one by one to the workers.
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 initialized data first. Inside `bootstrap` function of the config we execute the `share` function with `local: true` to initialize value locally:
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 for current worker
209
- share({ userData: false }, { local: true });
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
+ ```
@@ -3,11 +3,11 @@ permalink: /playwright
3
3
  title: Testing with Playwright
4
4
  ---
5
5
 
6
- # Testing with Playwright <Badge text="Since 2.5" type="warning"/>
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 automaiton.
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/Microsoft/playwright/blob/master/src/deviceDescriptors.ts) to emulate, for instance this is how you can enable iPhone 6 emulation for all tests:
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#browsernewcontextoptions)
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://github.com/microsoft/playwright/blob/master/docs/api.md) inside a test use `I.usePlaywrightTo` method with a callback.
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, context, page }) => {
336
+ I.usePlaywrightTo('emulate offline mode', async ({ browser, browserContext, page }) => {
330
337
  // use browser, page, context objects inside this function
331
- await context.setOffline(true);
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 Playwrigth API with CodeceptJS API:
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.context.setOffline(true);
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
+ ![](https://user-images.githubusercontent.com/220264/128403246-7e1b9b33-9ce2-42d5-b87b-b8749d5d7a78.png)
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
+ ![](https://user-images.githubusercontent.com/16587779/131362352-30ee9c51-705f-4098-b665-53035ea9275f.png)
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
+ ![](https://user-images.githubusercontent.com/16587779/131363170-b03b4398-5e9a-4142-bc32-764a5f4a5e11.png)
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.md#class-browsercontext)
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](http://codecept.io/helpers/)
557
+ > [▶ Learn more about Helpers](https://codecept.io/helpers/)