codeceptjs 3.1.1 â 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 +27 -0
- package/docs/build/Appium.js +14 -0
- package/docs/build/Playwright.js +2 -2
- package/docs/build/Puppeteer.js +18 -2
- package/docs/changelog.md +27 -0
- package/docs/configuration.md +15 -2
- package/docs/helpers/Appium.md +15 -20
- package/docs/helpers/Puppeteer.md +17 -1
- package/docs/playwright.md +57 -0
- package/docs/plugins.md +60 -68
- package/lib/codecept.js +13 -2
- package/lib/helper/Appium.js +14 -0
- package/lib/helper/Playwright.js +2 -2
- package/lib/helper/Puppeteer.js +18 -2
- package/lib/mochaFactory.js +11 -6
- package/lib/plugin/{puppeteerCoverage.js â coverage.js} +10 -22
- package/lib/plugin/customLocator.js +2 -2
- package/lib/plugin/subtitles.js +88 -0
- package/lib/plugin/tryTo.js +1 -1
- package/lib/step.js +4 -2
- package/package.json +3 -2
- package/typings/types.d.ts +27 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
## 3.1.2
|
|
2
|
+
|
|
3
|
+
đŠī¸ Features:
|
|
4
|
+
|
|
5
|
+
* Added `coverage` plugin to generate code coverage for Playwright & Puppeteer. By @anirudh-modi
|
|
6
|
+
* Added `subtitle` plugin to generate subtitles for videos recorded with Playwright. By @anirudh-modi
|
|
7
|
+
* Configuration: `config.tests` to accept array of file patterns. See #2994 by @monsteramba
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
exports.config = {
|
|
11
|
+
tests: ['./*_test.js','./sampleTest.js'],
|
|
12
|
+
// ...
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
* Notification is shown for test files without `Feature()`. See #3011 by @PeterNgTr
|
|
16
|
+
|
|
17
|
+
đ Bugfixes:
|
|
18
|
+
|
|
19
|
+
* [Playwright] Fixed #2986 error is thrown when deleting a missing video. Fix by @hatufacci
|
|
20
|
+
* Fixed false positive result when invalid function is called in a helper. See #2997 by @abhimanyupandian
|
|
21
|
+
* [Appium] Removed full page mode for `saveScreenshot`. See #3002 by @nlespiaucq
|
|
22
|
+
* [Playwright] Fixed #3003 saving trace for a test with a long name. Fix by @hatufacci
|
|
23
|
+
|
|
24
|
+
đą Other:
|
|
25
|
+
|
|
26
|
+
* Deprecated `puppeteerCoverage` plugin in favor of `coverage` plugin.
|
|
27
|
+
|
|
1
28
|
## 3.1.1
|
|
2
29
|
|
|
3
30
|
* [Appium] Fixed #2759
|
package/docs/build/Appium.js
CHANGED
|
@@ -1551,6 +1551,20 @@ class Appium extends Webdriver {
|
|
|
1551
1551
|
return super.grabValueFrom(parseLocator.call(this, locator));
|
|
1552
1552
|
}
|
|
1553
1553
|
|
|
1554
|
+
/**
|
|
1555
|
+
* Saves a screenshot to ouput folder (set in codecept.json or codecept.conf.js).
|
|
1556
|
+
* Filename is relative to output folder.
|
|
1557
|
+
*
|
|
1558
|
+
* ```js
|
|
1559
|
+
* I.saveScreenshot('debug.png');
|
|
1560
|
+
* ```
|
|
1561
|
+
*
|
|
1562
|
+
* @param {string} fileName file name to save.
|
|
1563
|
+
*/
|
|
1564
|
+
async saveScreenshot(fileName) {
|
|
1565
|
+
return super.saveScreenshot(fileName, false);
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1554
1568
|
/**
|
|
1555
1569
|
* Scroll element into viewport.
|
|
1556
1570
|
*
|
package/docs/build/Playwright.js
CHANGED
|
@@ -2570,7 +2570,7 @@ class Playwright extends Helper {
|
|
|
2570
2570
|
}
|
|
2571
2571
|
|
|
2572
2572
|
if (this.options.trace) {
|
|
2573
|
-
const path = `${global.output_dir}/trace/${clearString(test.title)}.zip`;
|
|
2573
|
+
const path = `${global.output_dir}/trace/${clearString(test.title).slice(0, 255)}.zip`;
|
|
2574
2574
|
await this.browserContext.tracing.stop({ path });
|
|
2575
2575
|
test.artifacts.trace = path;
|
|
2576
2576
|
}
|
|
@@ -2581,7 +2581,7 @@ class Playwright extends Helper {
|
|
|
2581
2581
|
if (this.options.keepVideoForPassedTests) {
|
|
2582
2582
|
test.artifacts.video = await this.page.video().path();
|
|
2583
2583
|
} else {
|
|
2584
|
-
this.page.video().delete();
|
|
2584
|
+
this.page.video().delete().catch(e => {});
|
|
2585
2585
|
}
|
|
2586
2586
|
}
|
|
2587
2587
|
|
package/docs/build/Puppeteer.js
CHANGED
|
@@ -129,8 +129,9 @@ const consoleLogStore = new Console();
|
|
|
129
129
|
* }
|
|
130
130
|
* }
|
|
131
131
|
* ```
|
|
132
|
+
* > Note: When connecting to remote browser `show` and specific `chrome` options (e.g. `headless` or `devtools`) are ignored.
|
|
132
133
|
*
|
|
133
|
-
* #### Example #5: Target URL with provided basic authentication
|
|
134
|
+
* #### Example #5: Target URL with provided basic authentication
|
|
134
135
|
*
|
|
135
136
|
* ```js
|
|
136
137
|
* {
|
|
@@ -143,10 +144,25 @@ const consoleLogStore = new Console();
|
|
|
143
144
|
* }
|
|
144
145
|
* }
|
|
145
146
|
* ```
|
|
147
|
+
* #### Troubleshooting
|
|
146
148
|
*
|
|
149
|
+
* Error Message: `No usable sandbox!`
|
|
150
|
+
*
|
|
151
|
+
* When running Puppeteer on CI try to disable sandbox if you see that message
|
|
152
|
+
*
|
|
153
|
+
* ```
|
|
154
|
+
* helpers: {
|
|
155
|
+
* Puppeteer: {
|
|
156
|
+
* url: 'http://localhost',
|
|
157
|
+
* show: false,
|
|
158
|
+
* chrome: {
|
|
159
|
+
* args: ['--no-sandbox', '--disable-setuid-sandbox']
|
|
160
|
+
* }
|
|
161
|
+
* },
|
|
162
|
+
* }
|
|
163
|
+
* ```
|
|
147
164
|
*
|
|
148
165
|
*
|
|
149
|
-
* Note: When connecting to remote browser `show` and specific `chrome` options (e.g. `headless` or `devtools`) are ignored.
|
|
150
166
|
*
|
|
151
167
|
* ## Access From Helpers
|
|
152
168
|
*
|
package/docs/changelog.md
CHANGED
|
@@ -7,6 +7,33 @@ layout: Section
|
|
|
7
7
|
|
|
8
8
|
# Releases
|
|
9
9
|
|
|
10
|
+
## 3.1.2
|
|
11
|
+
|
|
12
|
+
đŠī¸ Features:
|
|
13
|
+
|
|
14
|
+
* Added `coverage` plugin to generate code coverage for Playwright & Puppeteer. By **[anirudh-modi](https://github.com/anirudh-modi)**
|
|
15
|
+
* Added `subtitle` plugin to generate subtitles for videos recorded with Playwright. By **[anirudh-modi](https://github.com/anirudh-modi)**
|
|
16
|
+
* Configuration: `config.tests` to accept array of file patterns. See [#2994](https://github.com/codeceptjs/CodeceptJS/issues/2994) by **[monsteramba](https://github.com/monsteramba)**
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
exports.config = {
|
|
20
|
+
tests: ['./*_test.js','./sampleTest.js'],
|
|
21
|
+
// ...
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
* Notification is shown for test files without `Feature()`. See [#3011](https://github.com/codeceptjs/CodeceptJS/issues/3011) by **[PeterNgTr](https://github.com/PeterNgTr)**
|
|
25
|
+
|
|
26
|
+
đ Bugfixes:
|
|
27
|
+
|
|
28
|
+
* **[Playwright]** Fixed [#2986](https://github.com/codeceptjs/CodeceptJS/issues/2986) error is thrown when deleting a missing video. Fix by **[hatufacci](https://github.com/hatufacci)**
|
|
29
|
+
* Fixed false positive result when invalid function is called in a helper. See [#2997](https://github.com/codeceptjs/CodeceptJS/issues/2997) by **[abhimanyupandian](https://github.com/abhimanyupandian)**
|
|
30
|
+
* **[Appium]** Removed full page mode for `saveScreenshot`. See [#3002](https://github.com/codeceptjs/CodeceptJS/issues/3002) by **[nlespiaucq](https://github.com/nlespiaucq)**
|
|
31
|
+
* **[Playwright]** Fixed [#3003](https://github.com/codeceptjs/CodeceptJS/issues/3003) saving trace for a test with a long name. Fix by **[hatufacci](https://github.com/hatufacci)**
|
|
32
|
+
|
|
33
|
+
đą Other:
|
|
34
|
+
|
|
35
|
+
* Deprecated `puppeteerCoverage` plugin in favor of `coverage` plugin.
|
|
36
|
+
|
|
10
37
|
## 3.1.1
|
|
11
38
|
|
|
12
39
|
* **[Appium]** Fixed [#2759](https://github.com/codeceptjs/CodeceptJS/issues/2759)
|
package/docs/configuration.md
CHANGED
|
@@ -11,7 +11,7 @@ After running `codeceptjs init` it should be saved in test root.
|
|
|
11
11
|
|
|
12
12
|
Here is an overview of available options with their defaults:
|
|
13
13
|
|
|
14
|
-
* **tests**: `"./*_test.js"` - pattern to locate tests. Allows to enter [glob pattern](https://github.com/isaacs/node-glob).
|
|
14
|
+
* **tests**: `"./*_test.js"` - pattern to locate tests. Allows to enter [glob pattern](https://github.com/isaacs/node-glob), Can either be a pattern to locate tests or an array of patterns to locate tests / test file names.
|
|
15
15
|
* **grep**: - pattern to filter tests by name
|
|
16
16
|
* **include**: `{}` - actors and page objects to be registered in DI container and included in tests. Accepts objects and module `require` paths
|
|
17
17
|
* **timeout**: `10000` - default tests timeout
|
|
@@ -47,7 +47,20 @@ exports.config = {
|
|
|
47
47
|
require: ["ts-node/register", "should"]
|
|
48
48
|
}
|
|
49
49
|
```
|
|
50
|
-
|
|
50
|
+
For array of test pattern
|
|
51
|
+
```js
|
|
52
|
+
exports.config = {
|
|
53
|
+
tests: ['./*_test.js','./sampleTest.js'],
|
|
54
|
+
timeout: 10000,
|
|
55
|
+
output: '',
|
|
56
|
+
helpers: {},
|
|
57
|
+
include: {},
|
|
58
|
+
bootstrap: false,
|
|
59
|
+
mocha: {},
|
|
60
|
+
// require modules
|
|
61
|
+
require: ["ts-node/register", "should"]
|
|
62
|
+
}
|
|
63
|
+
```
|
|
51
64
|
## Dynamic Configuration
|
|
52
65
|
|
|
53
66
|
By default `codecept.json` is used for configuration. You can override its values in runtime by using `--override` or `-o` option in command line, passing valid JSON as a value:
|
package/docs/helpers/Appium.md
CHANGED
|
@@ -1027,6 +1027,19 @@ let email = await I.grabValueFrom('input[name=email]');
|
|
|
1027
1027
|
|
|
1028
1028
|
Returns **[Promise][13]<[string][4]>** attribute value
|
|
1029
1029
|
|
|
1030
|
+
### saveScreenshot
|
|
1031
|
+
|
|
1032
|
+
Saves a screenshot to ouput folder (set in codecept.json or codecept.conf.js).
|
|
1033
|
+
Filename is relative to output folder.
|
|
1034
|
+
|
|
1035
|
+
```js
|
|
1036
|
+
I.saveScreenshot('debug.png');
|
|
1037
|
+
```
|
|
1038
|
+
|
|
1039
|
+
#### Parameters
|
|
1040
|
+
|
|
1041
|
+
- `fileName` **[string][4]** file name to save.
|
|
1042
|
+
|
|
1030
1043
|
### scrollIntoView
|
|
1031
1044
|
|
|
1032
1045
|
Scroll element into viewport.
|
|
@@ -1663,27 +1676,11 @@ I.saveElementScreenshot(`#submit`,'debug.png');
|
|
|
1663
1676
|
- `locator` **([string][4] \| [object][6])** element located by CSS|XPath|strict locator.
|
|
1664
1677
|
- `fileName` **[string][4]** file name to save.
|
|
1665
1678
|
|
|
1666
|
-
### saveScreenshot
|
|
1667
|
-
|
|
1668
|
-
Saves a screenshot to ouput folder (set in codecept.json or codecept.conf.js).
|
|
1669
|
-
Filename is relative to output folder.
|
|
1670
|
-
Optionally resize the window to the full available page `scrollHeight` and `scrollWidth` to capture the entire page by passing `true` in as the second argument.
|
|
1671
|
-
|
|
1672
|
-
```js
|
|
1673
|
-
I.saveScreenshot('debug.png');
|
|
1674
|
-
I.saveScreenshot('debug.png', true) //resizes to available scrollHeight and scrollWidth before taking screenshot
|
|
1675
|
-
```
|
|
1676
|
-
|
|
1677
|
-
#### Parameters
|
|
1678
|
-
|
|
1679
|
-
- `fileName` **[string][4]** file name to save.
|
|
1680
|
-
- `fullPage` **[boolean][20]** (optional, `false` by default) flag to enable fullscreen screenshot mode. (optional, default `false`)
|
|
1681
|
-
|
|
1682
1679
|
### type
|
|
1683
1680
|
|
|
1684
1681
|
Types out the given text into an active field.
|
|
1685
1682
|
To slow down typing use a second parameter, to set interval between key presses.
|
|
1686
|
-
_Note:_ Should be used when [`fillField`][
|
|
1683
|
+
_Note:_ Should be used when [`fillField`][20] is not an option.
|
|
1687
1684
|
|
|
1688
1685
|
```js
|
|
1689
1686
|
// passing in a string
|
|
@@ -1921,6 +1918,4 @@ Returns **([Promise][13]<DOMRect> | [Promise][13]<[number][8]>)** Element
|
|
|
1921
1918
|
|
|
1922
1919
|
[19]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined
|
|
1923
1920
|
|
|
1924
|
-
[20]:
|
|
1925
|
-
|
|
1926
|
-
[21]: #fillfield
|
|
1921
|
+
[20]: #fillfield
|
|
@@ -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/playwright.md
CHANGED
|
@@ -456,6 +456,63 @@ For instance, this is how you can read a trace for a failed test from an example
|
|
|
456
456
|
npx playwright show-trace /home/davert/projects/codeceptjs/examples/output/trace/open.zip
|
|
457
457
|
```
|
|
458
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
|
+

|
|
459
516
|
## Extending Helper
|
|
460
517
|
|
|
461
518
|
To create custom `I.*` commands using Playwright API you need to create a custom helper.
|
package/docs/plugins.md
CHANGED
|
@@ -409,6 +409,29 @@ Scenario('project update test', async (I) => {
|
|
|
409
409
|
|
|
410
410
|
- `config`
|
|
411
411
|
|
|
412
|
+
## coverage
|
|
413
|
+
|
|
414
|
+
Dumps code coverage from Playwright/Puppeteer after every test.
|
|
415
|
+
|
|
416
|
+
#### Configuration
|
|
417
|
+
|
|
418
|
+
```js
|
|
419
|
+
plugins: {
|
|
420
|
+
playwrightCoverage: {
|
|
421
|
+
enabled: true
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
Possible config options:
|
|
427
|
+
|
|
428
|
+
- `coverageDir`: directory to dump coverage files
|
|
429
|
+
- `uniqueFileName`: generate a unique filename by adding uuid
|
|
430
|
+
|
|
431
|
+
### Parameters
|
|
432
|
+
|
|
433
|
+
- `config`
|
|
434
|
+
|
|
412
435
|
## customLocator
|
|
413
436
|
|
|
414
437
|
Creates a [custom locator][3] by using special attributes in HTML.
|
|
@@ -441,7 +464,7 @@ Using `data-test` attribute with `$` prefix:
|
|
|
441
464
|
// in codecept.conf.js
|
|
442
465
|
plugins: {
|
|
443
466
|
customLocator: {
|
|
444
|
-
enabled: true
|
|
467
|
+
enabled: true,
|
|
445
468
|
attribute: 'data-test'
|
|
446
469
|
}
|
|
447
470
|
}
|
|
@@ -460,7 +483,7 @@ Using `data-qa` attribute with `=` prefix:
|
|
|
460
483
|
// in codecept.conf.js
|
|
461
484
|
plugins: {
|
|
462
485
|
customLocator: {
|
|
463
|
-
enabled: true
|
|
486
|
+
enabled: true,
|
|
464
487
|
prefix: '=',
|
|
465
488
|
attribute: 'data-qa'
|
|
466
489
|
}
|
|
@@ -536,45 +559,6 @@ Enable it manually on each run via `-p` option:
|
|
|
536
559
|
|
|
537
560
|
npx codeceptjs run -p pauseOnFail
|
|
538
561
|
|
|
539
|
-
## puppeteerCoverage
|
|
540
|
-
|
|
541
|
-
Dumps puppeteers code coverage after every test.
|
|
542
|
-
|
|
543
|
-
#### Configuration
|
|
544
|
-
|
|
545
|
-
Configuration can either be taken from a corresponding helper (deprecated) or a from plugin config (recommended).
|
|
546
|
-
|
|
547
|
-
```js
|
|
548
|
-
plugins: {
|
|
549
|
-
puppeteerCoverage: {
|
|
550
|
-
enabled: true
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
```
|
|
554
|
-
|
|
555
|
-
Possible config options:
|
|
556
|
-
|
|
557
|
-
- `coverageDir`: directory to dump coverage files
|
|
558
|
-
- `uniqueFileName`: generate a unique filename by adding uuid
|
|
559
|
-
|
|
560
|
-
First of all, your mileage may vary!
|
|
561
|
-
|
|
562
|
-
To work, you need the client javascript code to be NOT uglified. They need to be built in "development" mode.
|
|
563
|
-
And the end of your tests, you'll get a directory full of coverage per test run. Now what?
|
|
564
|
-
You'll need to convert the coverage code to something istanbul can read. Good news is someone wrote the code
|
|
565
|
-
for you (see puppeteer-to-istanbul link below). Then using istanbul you need to combine the converted
|
|
566
|
-
coverage and create a report. Good luck!
|
|
567
|
-
|
|
568
|
-
Links:
|
|
569
|
-
|
|
570
|
-
- [https://github.com/GoogleChrome/puppeteer/blob/v1.12.2/docs/api.md#class-coverage][7]
|
|
571
|
-
- [https://github.com/istanbuljs/puppeteer-to-istanbul][8]
|
|
572
|
-
- [https://github.com/gotwarlost/istanbul][9]
|
|
573
|
-
|
|
574
|
-
### Parameters
|
|
575
|
-
|
|
576
|
-
- `config`
|
|
577
|
-
|
|
578
562
|
## retryFailedStep
|
|
579
563
|
|
|
580
564
|
Retries each failed step in a test.
|
|
@@ -673,14 +657,14 @@ Possible config options:
|
|
|
673
657
|
|
|
674
658
|
## selenoid
|
|
675
659
|
|
|
676
|
-
[Selenoid][
|
|
660
|
+
[Selenoid][7] plugin automatically starts browsers and video recording.
|
|
677
661
|
Works with WebDriver helper.
|
|
678
662
|
|
|
679
663
|
### Prerequisite
|
|
680
664
|
|
|
681
665
|
This plugin **requires Docker** to be installed.
|
|
682
666
|
|
|
683
|
-
> If you have issues starting Selenoid with this plugin consider using the official [Configuration Manager][
|
|
667
|
+
> If you have issues starting Selenoid with this plugin consider using the official [Configuration Manager][8] tool from Selenoid
|
|
684
668
|
|
|
685
669
|
### Usage
|
|
686
670
|
|
|
@@ -709,7 +693,7 @@ plugins: {
|
|
|
709
693
|
}
|
|
710
694
|
```
|
|
711
695
|
|
|
712
|
-
When `autoCreate` is enabled it will pull the [latest Selenoid from DockerHub][
|
|
696
|
+
When `autoCreate` is enabled it will pull the [latest Selenoid from DockerHub][9] and start Selenoid automatically.
|
|
713
697
|
It will also create `browsers.json` file required by Selenoid.
|
|
714
698
|
|
|
715
699
|
In automatic mode the latest version of browser will be used for tests. It is recommended to specify exact version of each browser inside `browsers.json` file.
|
|
@@ -721,10 +705,10 @@ In automatic mode the latest version of browser will be used for tests. It is re
|
|
|
721
705
|
While this plugin can create containers for you for better control it is recommended to create and launch containers manually.
|
|
722
706
|
This is especially useful for Continous Integration server as you can configure scaling for Selenoid containers.
|
|
723
707
|
|
|
724
|
-
> Use [Selenoid Configuration Manager][
|
|
708
|
+
> Use [Selenoid Configuration Manager][8] to create and start containers semi-automatically.
|
|
725
709
|
|
|
726
710
|
1. Create `browsers.json` file in the same directory `codecept.conf.js` is located
|
|
727
|
-
[Refer to Selenoid documentation][
|
|
711
|
+
[Refer to Selenoid documentation][10] to know more about browsers.json.
|
|
728
712
|
|
|
729
713
|
_Sample browsers.json_
|
|
730
714
|
|
|
@@ -749,7 +733,7 @@ _Sample browsers.json_
|
|
|
749
733
|
|
|
750
734
|
2. Create Selenoid container
|
|
751
735
|
|
|
752
|
-
Run the following command to create a container. To know more [refer here][
|
|
736
|
+
Run the following command to create a container. To know more [refer here][11]
|
|
753
737
|
|
|
754
738
|
```bash
|
|
755
739
|
docker create \
|
|
@@ -782,7 +766,7 @@ When `allure` plugin is enabled a video is attached to report automatically.
|
|
|
782
766
|
| enableVideo | Enable video recording and use `video` folder of output (default: false) |
|
|
783
767
|
| enableLog | Enable log recording and use `logs` folder of output (default: false) |
|
|
784
768
|
| deletePassed | Delete video and logs of passed tests (default : true) |
|
|
785
|
-
| additionalParams | example: `additionalParams: '--env TEST=test'` [Refer here][
|
|
769
|
+
| additionalParams | example: `additionalParams: '--env TEST=test'` [Refer here][12] to know more |
|
|
786
770
|
|
|
787
771
|
### Parameters
|
|
788
772
|
|
|
@@ -790,7 +774,7 @@ When `allure` plugin is enabled a video is attached to report automatically.
|
|
|
790
774
|
|
|
791
775
|
## stepByStepReport
|
|
792
776
|
|
|
793
|
-
![step-by-step-report][
|
|
777
|
+
![step-by-step-report][13]
|
|
794
778
|
|
|
795
779
|
Generates step by step report for a test.
|
|
796
780
|
After each step in a test a screenshot is created. After test executed screenshots are combined into slideshow.
|
|
@@ -823,6 +807,20 @@ Possible config options:
|
|
|
823
807
|
|
|
824
808
|
- `config` **any**
|
|
825
809
|
|
|
810
|
+
## subtitles
|
|
811
|
+
|
|
812
|
+
Automatically captures steps as subtitle, and saves it as an artifact when a video is found for a failed test
|
|
813
|
+
|
|
814
|
+
#### Configuration
|
|
815
|
+
|
|
816
|
+
```js
|
|
817
|
+
plugins: {
|
|
818
|
+
subtitles: {
|
|
819
|
+
enabled: true
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
```
|
|
823
|
+
|
|
826
824
|
## tryTo
|
|
827
825
|
|
|
828
826
|
Adds global `tryTo` function inside of which all failed steps won't fail a test but will return true/false.
|
|
@@ -897,7 +895,7 @@ This plugin allows to run webdriverio services like:
|
|
|
897
895
|
- browserstack
|
|
898
896
|
- appium
|
|
899
897
|
|
|
900
|
-
A complete list of all available services can be found on [webdriverio website][
|
|
898
|
+
A complete list of all available services can be found on [webdriverio website][14].
|
|
901
899
|
|
|
902
900
|
#### Setup
|
|
903
901
|
|
|
@@ -909,7 +907,7 @@ See examples below:
|
|
|
909
907
|
|
|
910
908
|
#### Selenium Standalone Service
|
|
911
909
|
|
|
912
|
-
Install `@wdio/selenium-standalone-service` package, as [described here][
|
|
910
|
+
Install `@wdio/selenium-standalone-service` package, as [described here][15].
|
|
913
911
|
It is important to make sure it is compatible with current webdriverio version.
|
|
914
912
|
|
|
915
913
|
Enable `wdio` plugin in plugins list and add `selenium-standalone` service:
|
|
@@ -928,7 +926,7 @@ Please note, this service can be used with Protractor helper as well!
|
|
|
928
926
|
|
|
929
927
|
#### Sauce Service
|
|
930
928
|
|
|
931
|
-
Install `@wdio/sauce-service` package, as [described here][
|
|
929
|
+
Install `@wdio/sauce-service` package, as [described here][16].
|
|
932
930
|
It is important to make sure it is compatible with current webdriverio version.
|
|
933
931
|
|
|
934
932
|
Enable `wdio` plugin in plugins list and add `sauce` service:
|
|
@@ -970,28 +968,22 @@ In the same manner additional services from webdriverio can be installed, enable
|
|
|
970
968
|
|
|
971
969
|
[6]: /basics/#pause
|
|
972
970
|
|
|
973
|
-
[7]: https://
|
|
974
|
-
|
|
975
|
-
[8]: https://github.com/istanbuljs/puppeteer-to-istanbul
|
|
976
|
-
|
|
977
|
-
[9]: https://github.com/gotwarlost/istanbul
|
|
978
|
-
|
|
979
|
-
[10]: https://aerokube.com/selenoid/
|
|
971
|
+
[7]: https://aerokube.com/selenoid/
|
|
980
972
|
|
|
981
|
-
[
|
|
973
|
+
[8]: https://aerokube.com/cm/latest/
|
|
982
974
|
|
|
983
|
-
[
|
|
975
|
+
[9]: https://hub.docker.com/u/selenoid
|
|
984
976
|
|
|
985
|
-
[
|
|
977
|
+
[10]: https://aerokube.com/selenoid/latest/#_prepare_configuration
|
|
986
978
|
|
|
987
|
-
[
|
|
979
|
+
[11]: https://aerokube.com/selenoid/latest/#_option_2_start_selenoid_container
|
|
988
980
|
|
|
989
|
-
[
|
|
981
|
+
[12]: https://docs.docker.com/engine/reference/commandline/create/
|
|
990
982
|
|
|
991
|
-
[
|
|
983
|
+
[13]: https://codecept.io/img/codeceptjs-slideshow.gif
|
|
992
984
|
|
|
993
|
-
[
|
|
985
|
+
[14]: https://webdriver.io
|
|
994
986
|
|
|
995
|
-
[
|
|
987
|
+
[15]: https://webdriver.io/docs/selenium-standalone-service.html
|
|
996
988
|
|
|
997
|
-
[
|
|
989
|
+
[16]: https://webdriver.io/docs/sauce-service.html
|
package/lib/codecept.js
CHANGED
|
@@ -130,7 +130,16 @@ class Codecept {
|
|
|
130
130
|
let patterns = [pattern];
|
|
131
131
|
if (!pattern) {
|
|
132
132
|
patterns = [];
|
|
133
|
-
|
|
133
|
+
|
|
134
|
+
// If the user wants to test a specific set of test files as an array or string.
|
|
135
|
+
if (this.config.tests && !this.opts.features) {
|
|
136
|
+
if (Array.isArray(this.config.tests)) {
|
|
137
|
+
patterns.push(...this.config.tests);
|
|
138
|
+
} else {
|
|
139
|
+
patterns.push(this.config.tests);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
134
143
|
if (this.config.gherkin.features && !this.opts.tests) {
|
|
135
144
|
if (Array.isArray(this.config.gherkin.features)) {
|
|
136
145
|
this.config.gherkin.features.forEach(feature => {
|
|
@@ -147,7 +156,9 @@ class Codecept {
|
|
|
147
156
|
if (!fsPath.isAbsolute(file)) {
|
|
148
157
|
file = fsPath.join(global.codecept_dir, file);
|
|
149
158
|
}
|
|
150
|
-
this.testFiles.
|
|
159
|
+
if (!this.testFiles.includes(fsPath.resolve(file))) {
|
|
160
|
+
this.testFiles.push(fsPath.resolve(file));
|
|
161
|
+
}
|
|
151
162
|
});
|
|
152
163
|
}
|
|
153
164
|
}
|
package/lib/helper/Appium.js
CHANGED
|
@@ -1397,6 +1397,20 @@ class Appium extends Webdriver {
|
|
|
1397
1397
|
return super.grabValueFrom(parseLocator.call(this, locator));
|
|
1398
1398
|
}
|
|
1399
1399
|
|
|
1400
|
+
/**
|
|
1401
|
+
* Saves a screenshot to ouput folder (set in codecept.json or codecept.conf.js).
|
|
1402
|
+
* Filename is relative to output folder.
|
|
1403
|
+
*
|
|
1404
|
+
* ```js
|
|
1405
|
+
* I.saveScreenshot('debug.png');
|
|
1406
|
+
* ```
|
|
1407
|
+
*
|
|
1408
|
+
* @param {string} fileName file name to save.
|
|
1409
|
+
*/
|
|
1410
|
+
async saveScreenshot(fileName) {
|
|
1411
|
+
return super.saveScreenshot(fileName, false);
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1400
1414
|
/**
|
|
1401
1415
|
* {{> scrollIntoView }}
|
|
1402
1416
|
*
|
package/lib/helper/Playwright.js
CHANGED
|
@@ -1856,7 +1856,7 @@ class Playwright extends Helper {
|
|
|
1856
1856
|
}
|
|
1857
1857
|
|
|
1858
1858
|
if (this.options.trace) {
|
|
1859
|
-
const path = `${global.output_dir}/trace/${clearString(test.title)}.zip`;
|
|
1859
|
+
const path = `${global.output_dir}/trace/${clearString(test.title).slice(0, 255)}.zip`;
|
|
1860
1860
|
await this.browserContext.tracing.stop({ path });
|
|
1861
1861
|
test.artifacts.trace = path;
|
|
1862
1862
|
}
|
|
@@ -1867,7 +1867,7 @@ class Playwright extends Helper {
|
|
|
1867
1867
|
if (this.options.keepVideoForPassedTests) {
|
|
1868
1868
|
test.artifacts.video = await this.page.video().path();
|
|
1869
1869
|
} else {
|
|
1870
|
-
this.page.video().delete();
|
|
1870
|
+
this.page.video().delete().catch(e => {});
|
|
1871
1871
|
}
|
|
1872
1872
|
}
|
|
1873
1873
|
|
package/lib/helper/Puppeteer.js
CHANGED
|
@@ -129,8 +129,9 @@ const consoleLogStore = new Console();
|
|
|
129
129
|
* }
|
|
130
130
|
* }
|
|
131
131
|
* ```
|
|
132
|
+
* > Note: When connecting to remote browser `show` and specific `chrome` options (e.g. `headless` or `devtools`) are ignored.
|
|
132
133
|
*
|
|
133
|
-
* #### Example #5: Target URL with provided basic authentication
|
|
134
|
+
* #### Example #5: Target URL with provided basic authentication
|
|
134
135
|
*
|
|
135
136
|
* ```js
|
|
136
137
|
* {
|
|
@@ -143,10 +144,25 @@ const consoleLogStore = new Console();
|
|
|
143
144
|
* }
|
|
144
145
|
* }
|
|
145
146
|
* ```
|
|
147
|
+
* #### Troubleshooting
|
|
146
148
|
*
|
|
149
|
+
* Error Message: `No usable sandbox!`
|
|
150
|
+
*
|
|
151
|
+
* When running Puppeteer on CI try to disable sandbox if you see that message
|
|
152
|
+
*
|
|
153
|
+
* ```
|
|
154
|
+
* helpers: {
|
|
155
|
+
* Puppeteer: {
|
|
156
|
+
* url: 'http://localhost',
|
|
157
|
+
* show: false,
|
|
158
|
+
* chrome: {
|
|
159
|
+
* args: ['--no-sandbox', '--disable-setuid-sandbox']
|
|
160
|
+
* }
|
|
161
|
+
* },
|
|
162
|
+
* }
|
|
163
|
+
* ```
|
|
147
164
|
*
|
|
148
165
|
*
|
|
149
|
-
* Note: When connecting to remote browser `show` and specific `chrome` options (e.g. `headless` or `devtools`) are ignored.
|
|
150
166
|
*
|
|
151
167
|
* ## Access From Helpers
|
|
152
168
|
*
|
package/lib/mochaFactory.js
CHANGED
|
@@ -17,12 +17,6 @@ class MochaFactory {
|
|
|
17
17
|
output.process(opts.child);
|
|
18
18
|
mocha.ui(scenarioUi);
|
|
19
19
|
|
|
20
|
-
// process.on('unhandledRejection', (reason) => {
|
|
21
|
-
// output.error('Unhandled rejection');
|
|
22
|
-
// console.log(Error.captureStackTrace(reason));
|
|
23
|
-
// output.error(reason);
|
|
24
|
-
// });
|
|
25
|
-
|
|
26
20
|
Mocha.Runner.prototype.uncaught = function (err) {
|
|
27
21
|
if (err) {
|
|
28
22
|
if (err.toString().indexOf('ECONNREFUSED') >= 0) {
|
|
@@ -51,19 +45,30 @@ class MochaFactory {
|
|
|
51
45
|
|
|
52
46
|
// add ids for each test and check uniqueness
|
|
53
47
|
const dupes = [];
|
|
48
|
+
let missingFeatureInFile = [];
|
|
54
49
|
const seenTests = [];
|
|
55
50
|
mocha.suite.eachTest(test => {
|
|
56
51
|
test.id = genTestId(test);
|
|
52
|
+
|
|
57
53
|
const name = test.fullTitle();
|
|
58
54
|
if (seenTests.includes(test.id)) {
|
|
59
55
|
dupes.push(name);
|
|
60
56
|
}
|
|
61
57
|
seenTests.push(test.id);
|
|
58
|
+
|
|
59
|
+
if (name.slice(0, name.indexOf(':')) === '') {
|
|
60
|
+
missingFeatureInFile.push(test.file);
|
|
61
|
+
}
|
|
62
62
|
});
|
|
63
63
|
if (dupes.length) {
|
|
64
64
|
// ideally this should be no-op and throw (breaking change)...
|
|
65
65
|
output.error(`Duplicate test names detected - Feature + Scenario name should be unique:\n${dupes.join('\n')}`);
|
|
66
66
|
}
|
|
67
|
+
|
|
68
|
+
if (missingFeatureInFile.length) {
|
|
69
|
+
missingFeatureInFile = [...new Set(missingFeatureInFile)];
|
|
70
|
+
output.error(`Missing Feature section in:\n${missingFeatureInFile.join('\n')}`);
|
|
71
|
+
}
|
|
67
72
|
}
|
|
68
73
|
};
|
|
69
74
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const debugModule = require('debug');
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
|
|
@@ -13,7 +13,7 @@ const defaultConfig = {
|
|
|
13
13
|
uniqueFileName: true,
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
const supportedHelpers = ['Puppeteer'];
|
|
16
|
+
const supportedHelpers = ['Puppeteer', 'Playwright'];
|
|
17
17
|
|
|
18
18
|
function buildFileName(test, uniqueFileName) {
|
|
19
19
|
let fileName = clearString(test.title);
|
|
@@ -41,15 +41,14 @@ function buildFileName(test, uniqueFileName) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* Dumps
|
|
44
|
+
* Dumps code coverage from Playwright/Puppeteer after every test.
|
|
45
45
|
*
|
|
46
46
|
* #### Configuration
|
|
47
47
|
*
|
|
48
|
-
* Configuration can either be taken from a corresponding helper (deprecated) or a from plugin config (recommended).
|
|
49
48
|
*
|
|
50
49
|
* ```js
|
|
51
50
|
* plugins: {
|
|
52
|
-
*
|
|
51
|
+
* playwrightCoverage: {
|
|
53
52
|
* enabled: true
|
|
54
53
|
* }
|
|
55
54
|
* }
|
|
@@ -59,33 +58,22 @@ function buildFileName(test, uniqueFileName) {
|
|
|
59
58
|
*
|
|
60
59
|
* * `coverageDir`: directory to dump coverage files
|
|
61
60
|
* * `uniqueFileName`: generate a unique filename by adding uuid
|
|
62
|
-
*
|
|
63
|
-
* First of all, your mileage may vary!
|
|
64
|
-
*
|
|
65
|
-
* To work, you need the client javascript code to be NOT uglified. They need to be built in "development" mode.
|
|
66
|
-
* And the end of your tests, you'll get a directory full of coverage per test run. Now what?
|
|
67
|
-
* You'll need to convert the coverage code to something istanbul can read. Good news is someone wrote the code
|
|
68
|
-
* for you (see puppeteer-to-istanbul link below). Then using istanbul you need to combine the converted
|
|
69
|
-
* coverage and create a report. Good luck!
|
|
70
|
-
*
|
|
71
|
-
* Links:
|
|
72
|
-
* * https://github.com/GoogleChrome/puppeteer/blob/v1.12.2/docs/api.md#class-coverage
|
|
73
|
-
* * https://github.com/istanbuljs/puppeteer-to-istanbul
|
|
74
|
-
* * https://github.com/gotwarlost/istanbul
|
|
75
61
|
*/
|
|
76
62
|
module.exports = function (config) {
|
|
77
63
|
const helpers = Container.helpers();
|
|
78
64
|
let coverageRunning = false;
|
|
79
65
|
let helper;
|
|
80
66
|
|
|
67
|
+
let debug;
|
|
81
68
|
for (const helperName of supportedHelpers) {
|
|
82
69
|
if (Object.keys(helpers).indexOf(helperName) > -1) {
|
|
83
70
|
helper = helpers[helperName];
|
|
71
|
+
debug = debugModule(`codeceptjs:plugin:${helperName.toLowerCase()}Coverage`);
|
|
84
72
|
}
|
|
85
73
|
}
|
|
86
74
|
|
|
87
75
|
if (!helper) {
|
|
88
|
-
console.error('Coverage is only supported in Puppeteer');
|
|
76
|
+
console.error('Coverage is only supported in Puppeteer, Playwright');
|
|
89
77
|
return; // no helpers for screenshot
|
|
90
78
|
}
|
|
91
79
|
|
|
@@ -102,7 +90,7 @@ module.exports = function (config) {
|
|
|
102
90
|
'starting coverage',
|
|
103
91
|
async () => {
|
|
104
92
|
try {
|
|
105
|
-
if (!coverageRunning) {
|
|
93
|
+
if (!coverageRunning && helper.page && helper.page.coverage) {
|
|
106
94
|
debug('--> starting coverage <--');
|
|
107
95
|
coverageRunning = true;
|
|
108
96
|
await helper.page.coverage.startJSCoverage();
|
|
@@ -115,13 +103,13 @@ module.exports = function (config) {
|
|
|
115
103
|
);
|
|
116
104
|
});
|
|
117
105
|
|
|
118
|
-
// Save
|
|
106
|
+
// Save coverage data after every test run
|
|
119
107
|
event.dispatcher.on(event.test.after, async (test) => {
|
|
120
108
|
recorder.add(
|
|
121
109
|
'saving coverage',
|
|
122
110
|
async () => {
|
|
123
111
|
try {
|
|
124
|
-
if (coverageRunning) {
|
|
112
|
+
if (coverageRunning && helper.page && helper.page.coverage) {
|
|
125
113
|
debug('--> stopping coverage <--');
|
|
126
114
|
coverageRunning = false;
|
|
127
115
|
const coverage = await helper.page.coverage.stopJSCoverage();
|
|
@@ -38,7 +38,7 @@ const defaultConfig = {
|
|
|
38
38
|
* // in codecept.conf.js
|
|
39
39
|
* plugins: {
|
|
40
40
|
* customLocator: {
|
|
41
|
-
* enabled: true
|
|
41
|
+
* enabled: true,
|
|
42
42
|
* attribute: 'data-test'
|
|
43
43
|
* }
|
|
44
44
|
* }
|
|
@@ -57,7 +57,7 @@ const defaultConfig = {
|
|
|
57
57
|
* // in codecept.conf.js
|
|
58
58
|
* plugins: {
|
|
59
59
|
* customLocator: {
|
|
60
|
-
* enabled: true
|
|
60
|
+
* enabled: true,
|
|
61
61
|
* prefix: '=',
|
|
62
62
|
* attribute: 'data-qa'
|
|
63
63
|
* }
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const { v4: uuidv4 } = require('uuid');
|
|
2
|
+
const fsPromise = require('fs').promises;
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const event = require('../event');
|
|
5
|
+
|
|
6
|
+
// This will convert a given timestamp in milliseconds to
|
|
7
|
+
// an SRT recognized timestamp, ie HH:mm:ss,SSS
|
|
8
|
+
function formatTimestamp(timestampInMs) {
|
|
9
|
+
const date = new Date(0, 0, 0, 0, 0, 0, timestampInMs);
|
|
10
|
+
const hours = date.getHours();
|
|
11
|
+
const minutes = date.getMinutes();
|
|
12
|
+
const seconds = date.getSeconds();
|
|
13
|
+
const ms = timestampInMs - (hours * 3600000 + minutes * 60000 + seconds * 1000);
|
|
14
|
+
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')},${ms.toString().padStart(3, '0')}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let steps = {};
|
|
18
|
+
let testStartedAt;
|
|
19
|
+
/**
|
|
20
|
+
* Automatically captures steps as subtitle, and saves it as an artifact when a video is found for a failed test
|
|
21
|
+
*
|
|
22
|
+
* #### Configuration
|
|
23
|
+
* ```js
|
|
24
|
+
* plugins: {
|
|
25
|
+
* subtitles: {
|
|
26
|
+
* enabled: true
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
module.exports = function () {
|
|
32
|
+
event.dispatcher.on(event.test.before, (_) => {
|
|
33
|
+
testStartedAt = Date.now();
|
|
34
|
+
steps = {};
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
event.dispatcher.on(event.step.started, (step) => {
|
|
38
|
+
const stepStartedAt = Date.now();
|
|
39
|
+
step.id = uuidv4();
|
|
40
|
+
|
|
41
|
+
let title = `${step.actor}.${step.name}(${step.args ? step.args.join(',') : ''})`;
|
|
42
|
+
if (title.length > 100) {
|
|
43
|
+
title = `${title.substring(0, 100)}...`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
steps[step.id] = {
|
|
47
|
+
start: formatTimestamp(stepStartedAt - testStartedAt),
|
|
48
|
+
startedAt: stepStartedAt,
|
|
49
|
+
title,
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
event.dispatcher.on(event.step.finished, (step) => {
|
|
54
|
+
if (step && step.id && steps[step.id]) {
|
|
55
|
+
steps[step.id].end = formatTimestamp(Date.now() - testStartedAt);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
event.dispatcher.on(event.test.after, async (test) => {
|
|
60
|
+
if (test && test.artifacts && test.artifacts.video) {
|
|
61
|
+
const stepsSortedByStartTime = Object.values(steps);
|
|
62
|
+
stepsSortedByStartTime.sort((stepA, stepB) => {
|
|
63
|
+
return stepA.startedAt - stepB.startedAt;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
let subtitle = '';
|
|
67
|
+
|
|
68
|
+
// For an SRT file, every subtitle has to be in the format as mentioned below:
|
|
69
|
+
//
|
|
70
|
+
// 1
|
|
71
|
+
// HH:mm:ss,SSS --> HH:mm:ss,SSS
|
|
72
|
+
// [title]
|
|
73
|
+
stepsSortedByStartTime.forEach((step, index) => {
|
|
74
|
+
if (step.end) {
|
|
75
|
+
subtitle = `${subtitle}${index + 1}
|
|
76
|
+
${step.start} --> ${step.end}
|
|
77
|
+
${step.title}
|
|
78
|
+
|
|
79
|
+
`;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const { dir: artifactsDirectory, name: fileName } = path.parse(test.artifacts.video);
|
|
84
|
+
await fsPromise.writeFile(`${artifactsDirectory}/${fileName}.srt`, subtitle);
|
|
85
|
+
test.artifacts.subtitle = `${artifactsDirectory}/${fileName}.srt`;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
};
|
package/lib/plugin/tryTo.js
CHANGED
|
@@ -89,7 +89,7 @@ function tryTo(callback) {
|
|
|
89
89
|
recorder.session.catch((err) => {
|
|
90
90
|
result = false;
|
|
91
91
|
const msg = err.inspect ? err.inspect() : err.toString();
|
|
92
|
-
debug(`
|
|
92
|
+
debug(`Unsuccessful try > ${msg}`);
|
|
93
93
|
recorder.session.restore('tryTo');
|
|
94
94
|
return result;
|
|
95
95
|
});
|
package/lib/step.js
CHANGED
|
@@ -212,16 +212,18 @@ class MetaStep extends Step {
|
|
|
212
212
|
step.metaStep = this;
|
|
213
213
|
};
|
|
214
214
|
event.dispatcher.prependListener(event.step.before, registerStep);
|
|
215
|
+
let rethrownError = null;
|
|
215
216
|
try {
|
|
216
217
|
this.startTime = Date.now();
|
|
217
218
|
result = fn.apply(this.context, this.args);
|
|
218
219
|
} catch (error) {
|
|
219
|
-
this.
|
|
220
|
+
this.setStatus('failed');
|
|
221
|
+
rethrownError = error;
|
|
220
222
|
} finally {
|
|
221
223
|
this.endTime = Date.now();
|
|
222
|
-
|
|
223
224
|
event.dispatcher.removeListener(event.step.before, registerStep);
|
|
224
225
|
}
|
|
226
|
+
if (rethrownError) { throw rethrownError; }
|
|
225
227
|
return result;
|
|
226
228
|
}
|
|
227
229
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeceptjs",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.2",
|
|
4
4
|
"description": "Supercharged End 2 End Testing Framework for NodeJS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"acceptance",
|
|
@@ -84,7 +84,8 @@
|
|
|
84
84
|
"promise-retry": "^1.1.1",
|
|
85
85
|
"requireg": "^0.2.2",
|
|
86
86
|
"resq": "^1.10.0",
|
|
87
|
-
"sprintf-js": "^1.1.1"
|
|
87
|
+
"sprintf-js": "^1.1.1",
|
|
88
|
+
"uuid": "^8.3.2"
|
|
88
89
|
},
|
|
89
90
|
"devDependencies": {
|
|
90
91
|
"@codeceptjs/detox-helper": "^1.0.2",
|
package/typings/types.d.ts
CHANGED
|
@@ -948,6 +948,16 @@ declare namespace CodeceptJS {
|
|
|
948
948
|
* @returns attribute value
|
|
949
949
|
*/
|
|
950
950
|
grabValueFrom(locator: CodeceptJS.LocatorOrString): Promise<string>;
|
|
951
|
+
/**
|
|
952
|
+
* Saves a screenshot to ouput folder (set in codecept.json or codecept.conf.js).
|
|
953
|
+
* Filename is relative to output folder.
|
|
954
|
+
*
|
|
955
|
+
* ```js
|
|
956
|
+
* I.saveScreenshot('debug.png');
|
|
957
|
+
* ```
|
|
958
|
+
* @param fileName - file name to save.
|
|
959
|
+
*/
|
|
960
|
+
saveScreenshot(fileName: string): void;
|
|
951
961
|
/**
|
|
952
962
|
* Scroll element into viewport.
|
|
953
963
|
*
|
|
@@ -5374,6 +5384,7 @@ declare namespace CodeceptJS {
|
|
|
5374
5384
|
* }
|
|
5375
5385
|
* }
|
|
5376
5386
|
* ```
|
|
5387
|
+
* > Note: When connecting to remote browser `show` and specific `chrome` options (e.g. `headless` or `devtools`) are ignored.
|
|
5377
5388
|
*
|
|
5378
5389
|
* #### Example #5: Target URL with provided basic authentication
|
|
5379
5390
|
*
|
|
@@ -5388,10 +5399,25 @@ declare namespace CodeceptJS {
|
|
|
5388
5399
|
* }
|
|
5389
5400
|
* }
|
|
5390
5401
|
* ```
|
|
5402
|
+
* #### Troubleshooting
|
|
5391
5403
|
*
|
|
5404
|
+
* Error Message: `No usable sandbox!`
|
|
5405
|
+
*
|
|
5406
|
+
* When running Puppeteer on CI try to disable sandbox if you see that message
|
|
5407
|
+
*
|
|
5408
|
+
* ```
|
|
5409
|
+
* helpers: {
|
|
5410
|
+
* Puppeteer: {
|
|
5411
|
+
* url: 'http://localhost',
|
|
5412
|
+
* show: false,
|
|
5413
|
+
* chrome: {
|
|
5414
|
+
* args: ['--no-sandbox', '--disable-setuid-sandbox']
|
|
5415
|
+
* }
|
|
5416
|
+
* },
|
|
5417
|
+
* }
|
|
5418
|
+
* ```
|
|
5392
5419
|
*
|
|
5393
5420
|
*
|
|
5394
|
-
* Note: When connecting to remote browser `show` and specific `chrome` options (e.g. `headless` or `devtools`) are ignored.
|
|
5395
5421
|
*
|
|
5396
5422
|
* ## Access From Helpers
|
|
5397
5423
|
*
|