codeceptjs 3.5.7-beta.1 → 3.5.7
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/README.md +5 -1
- package/docs/advanced.md +1 -1
- package/docs/build/Appium.js +1 -0
- package/docs/build/Playwright.js +36 -0
- package/docs/build/Puppeteer.js +45 -2
- package/docs/changelog.md +174 -0
- package/docs/helpers/Playwright.md +86 -56
- package/docs/helpers/Puppeteer.md +14 -2
- package/docs/webdriver.md +1 -1
- package/lib/ai.js +3 -12
- package/lib/helper/Appium.js +1 -0
- package/lib/helper/Playwright.js +36 -0
- package/lib/helper/Puppeteer.js +45 -2
- package/lib/html.js +3 -3
- package/lib/pause.js +3 -6
- package/lib/plugin/autoLogin.js +6 -0
- package/lib/plugin/heal.js +7 -40
- package/lib/recorder.js +5 -12
- package/lib/utils.js +1 -1
- package/lib/workers.js +23 -2
- package/package.json +13 -11
- package/typings/promiseBasedTypes.d.ts +24 -0
- package/typings/types.d.ts +28 -0
- package/CHANGELOG.md +0 -2950
package/lib/plugin/heal.js
CHANGED
|
@@ -8,7 +8,6 @@ const output = require('../output');
|
|
|
8
8
|
const supportedHelpers = require('./standardActingHelpers');
|
|
9
9
|
|
|
10
10
|
const defaultConfig = {
|
|
11
|
-
healTries: 1,
|
|
12
11
|
healLimit: 2,
|
|
13
12
|
healSteps: [
|
|
14
13
|
'click',
|
|
@@ -55,14 +54,11 @@ const defaultConfig = {
|
|
|
55
54
|
*
|
|
56
55
|
*/
|
|
57
56
|
module.exports = function (config = {}) {
|
|
58
|
-
const aiAssistant = AiAssistant
|
|
57
|
+
const aiAssistant = new AiAssistant();
|
|
59
58
|
|
|
60
59
|
let currentTest = null;
|
|
61
60
|
let currentStep = null;
|
|
62
61
|
let healedSteps = 0;
|
|
63
|
-
let caughtError;
|
|
64
|
-
let healTries = 0;
|
|
65
|
-
let isHealing = false;
|
|
66
62
|
|
|
67
63
|
const healSuggestions = [];
|
|
68
64
|
|
|
@@ -71,35 +67,20 @@ module.exports = function (config = {}) {
|
|
|
71
67
|
event.dispatcher.on(event.test.before, (test) => {
|
|
72
68
|
currentTest = test;
|
|
73
69
|
healedSteps = 0;
|
|
74
|
-
caughtError = null;
|
|
75
70
|
});
|
|
76
71
|
|
|
77
72
|
event.dispatcher.on(event.step.started, step => currentStep = step);
|
|
78
73
|
|
|
79
|
-
event.dispatcher.on(event.step.
|
|
80
|
-
if (isHealing) return;
|
|
74
|
+
event.dispatcher.on(event.step.before, () => {
|
|
81
75
|
const store = require('../store');
|
|
82
76
|
if (store.debugMode) return;
|
|
77
|
+
|
|
83
78
|
recorder.catchWithoutStop(async (err) => {
|
|
84
|
-
|
|
85
|
-
if (caughtError === err) throw err; // avoid double handling
|
|
86
|
-
caughtError = err;
|
|
87
|
-
if (!aiAssistant.isEnabled) {
|
|
88
|
-
output.print(colors.yellow('Heal plugin can\'t operate, AI assistant is disabled. Please set OPENAI_API_KEY env variable to enable it.'));
|
|
89
|
-
throw err;
|
|
90
|
-
}
|
|
79
|
+
if (!aiAssistant.isEnabled) throw err;
|
|
91
80
|
if (!currentStep) throw err;
|
|
92
81
|
if (!config.healSteps.includes(currentStep.name)) throw err;
|
|
93
82
|
const test = currentTest;
|
|
94
83
|
|
|
95
|
-
if (healTries >= config.healTries) {
|
|
96
|
-
output.print(colors.bold.red(`Healing failed for ${config.healTries} time(s)`));
|
|
97
|
-
output.print('AI couldn\'t identify the correct solution');
|
|
98
|
-
output.print('Probably the entire flow has changed and the test should be updated');
|
|
99
|
-
|
|
100
|
-
throw err;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
84
|
if (healedSteps >= config.healLimit) {
|
|
104
85
|
output.print(colors.bold.red(`Can't heal more than ${config.healLimit} step(s) in a test`));
|
|
105
86
|
output.print('Entire flow can be broken, please check it manually');
|
|
@@ -130,17 +111,9 @@ module.exports = function (config = {}) {
|
|
|
130
111
|
|
|
131
112
|
if (!html) throw err;
|
|
132
113
|
|
|
133
|
-
|
|
134
|
-
await aiAssistant.setHtmlContext(html);
|
|
114
|
+
aiAssistant.setHtmlContext(html);
|
|
135
115
|
await tryToHeal(step, err);
|
|
136
|
-
|
|
137
|
-
recorder.add('close healing session', () => {
|
|
138
|
-
recorder.session.restore('heal');
|
|
139
|
-
recorder.ignoreErr(err);
|
|
140
|
-
});
|
|
141
|
-
await recorder.promise();
|
|
142
|
-
|
|
143
|
-
isHealing = false;
|
|
116
|
+
recorder.session.restore();
|
|
144
117
|
});
|
|
145
118
|
});
|
|
146
119
|
|
|
@@ -182,9 +155,6 @@ module.exports = function (config = {}) {
|
|
|
182
155
|
for (const codeSnippet of codeSnippets) {
|
|
183
156
|
try {
|
|
184
157
|
debug('Executing', codeSnippet);
|
|
185
|
-
recorder.catch((e) => {
|
|
186
|
-
console.log(e);
|
|
187
|
-
});
|
|
188
158
|
await eval(codeSnippet); // eslint-disable-line
|
|
189
159
|
|
|
190
160
|
healSuggestions.push({
|
|
@@ -193,17 +163,14 @@ module.exports = function (config = {}) {
|
|
|
193
163
|
snippet: codeSnippet,
|
|
194
164
|
});
|
|
195
165
|
|
|
196
|
-
|
|
166
|
+
output.print(colors.bold.green(' Code healed successfully'));
|
|
197
167
|
healedSteps++;
|
|
198
168
|
return;
|
|
199
169
|
} catch (err) {
|
|
200
170
|
debug('Failed to execute code', err);
|
|
201
|
-
recorder.ignoreErr(err); // healing ded not help
|
|
202
|
-
// recorder.catch(() => output.print(colors.bold.red(' Failed healing code')));
|
|
203
171
|
}
|
|
204
172
|
}
|
|
205
173
|
|
|
206
174
|
output.debug(`Couldn't heal the code for ${failedStep.toCode()}`);
|
|
207
175
|
}
|
|
208
|
-
return recorder.promise();
|
|
209
176
|
};
|
package/lib/recorder.js
CHANGED
|
@@ -11,7 +11,6 @@ let errFn;
|
|
|
11
11
|
let queueId = 0;
|
|
12
12
|
let sessionId = null;
|
|
13
13
|
let asyncErr = null;
|
|
14
|
-
let ignoredErrs = [];
|
|
15
14
|
|
|
16
15
|
let tasks = [];
|
|
17
16
|
let oldPromises = [];
|
|
@@ -94,7 +93,6 @@ module.exports = {
|
|
|
94
93
|
promise = Promise.resolve();
|
|
95
94
|
oldPromises = [];
|
|
96
95
|
tasks = [];
|
|
97
|
-
ignoredErrs = [];
|
|
98
96
|
this.session.running = false;
|
|
99
97
|
// reset this retries makes the retryFailedStep plugin won't work if there is Before/BeforeSuit block due to retries is undefined on Scenario
|
|
100
98
|
// this.retries = [];
|
|
@@ -228,10 +226,9 @@ module.exports = {
|
|
|
228
226
|
* @inner
|
|
229
227
|
*/
|
|
230
228
|
catch(customErrFn) {
|
|
231
|
-
|
|
232
|
-
debug(`${currentQueue()}Queued | catch with error handler ${fnDescription || ''}`);
|
|
229
|
+
debug(`${currentQueue()}Queued | catch with error handler`);
|
|
233
230
|
return promise = promise.catch((err) => {
|
|
234
|
-
log(`${currentQueue()}Error | ${err}
|
|
231
|
+
log(`${currentQueue()}Error | ${err}`);
|
|
235
232
|
if (!(err instanceof Error)) { // strange things may happen
|
|
236
233
|
err = new Error(`[Wrapped Error] ${printObjectProperties(err)}`); // we should be prepared for them
|
|
237
234
|
}
|
|
@@ -250,15 +247,15 @@ module.exports = {
|
|
|
250
247
|
* @inner
|
|
251
248
|
*/
|
|
252
249
|
catchWithoutStop(customErrFn) {
|
|
253
|
-
const fnDescription = customErrFn?.toString()?.replace(/\s{2,}/g, ' ').replace(/\n/g, ' ')?.slice(0, 50);
|
|
254
250
|
return promise = promise.catch((err) => {
|
|
255
|
-
|
|
256
|
-
log(`${currentQueue()}Error (Non-Terminated) | ${err} | ${fnDescription || ''}...`);
|
|
251
|
+
log(`${currentQueue()}Error | ${err}`);
|
|
257
252
|
if (!(err instanceof Error)) { // strange things may happen
|
|
258
253
|
err = new Error(`[Wrapped Error] ${JSON.stringify(err)}`); // we should be prepared for them
|
|
259
254
|
}
|
|
260
255
|
if (customErrFn) {
|
|
261
256
|
return customErrFn(err);
|
|
257
|
+
} if (errFn) {
|
|
258
|
+
return errFn(err);
|
|
262
259
|
}
|
|
263
260
|
});
|
|
264
261
|
},
|
|
@@ -277,10 +274,6 @@ module.exports = {
|
|
|
277
274
|
});
|
|
278
275
|
},
|
|
279
276
|
|
|
280
|
-
ignoreErr(err) {
|
|
281
|
-
ignoredErrs.push(err);
|
|
282
|
-
},
|
|
283
|
-
|
|
284
277
|
/**
|
|
285
278
|
* @param {*} err
|
|
286
279
|
* @inner
|
package/lib/utils.js
CHANGED
|
@@ -11,7 +11,7 @@ function deepMerge(target, source) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
module.exports.genTestId = (test) => {
|
|
14
|
-
return require('crypto').createHash('
|
|
14
|
+
return require('crypto').createHash('sha256').update(test.fullTitle()).digest('base64')
|
|
15
15
|
.slice(0, -2);
|
|
16
16
|
};
|
|
17
17
|
|
package/lib/workers.js
CHANGED
|
@@ -94,10 +94,31 @@ const createWorkerObjects = (testGroups, config, testRoot, options, selectedRuns
|
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
96
|
const workersToExecute = [];
|
|
97
|
+
|
|
98
|
+
const currentOutputFolder = config.output;
|
|
99
|
+
let currentMochawesomeReportDir;
|
|
100
|
+
let currentMochaJunitReporterFile;
|
|
101
|
+
|
|
102
|
+
if (config.mocha && config.mocha.reporterOptions) {
|
|
103
|
+
currentMochawesomeReportDir = config.mocha.reporterOptions?.mochawesome.options.reportDir;
|
|
104
|
+
currentMochaJunitReporterFile = config.mocha.reporterOptions['mocha-junit-reporter'].options.mochaFile;
|
|
105
|
+
}
|
|
106
|
+
|
|
97
107
|
collection.createRuns(selectedRuns, config).forEach((worker) => {
|
|
98
|
-
const
|
|
108
|
+
const separator = path.sep;
|
|
109
|
+
const _config = { ...config };
|
|
110
|
+
let workerName = worker.name.replace(':', '_');
|
|
111
|
+
_config.output = `${currentOutputFolder}${separator}${workerName}`;
|
|
112
|
+
if (config.mocha && config.mocha.reporterOptions) {
|
|
113
|
+
_config.mocha.reporterOptions.mochawesome.options.reportDir = `${currentMochawesomeReportDir}${separator}${workerName}`;
|
|
114
|
+
|
|
115
|
+
const _tempArray = currentMochaJunitReporterFile.split(separator);
|
|
116
|
+
_tempArray.splice(_tempArray.findIndex(item => item.includes('.xml')), 0, workerName);
|
|
117
|
+
_config.mocha.reporterOptions['mocha-junit-reporter'].options.mochaFile = _tempArray.join(separator);
|
|
118
|
+
}
|
|
119
|
+
workerName = worker.getOriginalName() || worker.getName();
|
|
99
120
|
const workerConfig = worker.getConfig();
|
|
100
|
-
workersToExecute.push(getOverridenConfig(workerName, workerConfig,
|
|
121
|
+
workersToExecute.push(getOverridenConfig(workerName, workerConfig, _config));
|
|
101
122
|
});
|
|
102
123
|
const workers = [];
|
|
103
124
|
let index = 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeceptjs",
|
|
3
|
-
"version": "3.5.7
|
|
3
|
+
"version": "3.5.7",
|
|
4
4
|
"description": "Supercharged End 2 End Testing Framework for NodeJS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"acceptance",
|
|
@@ -43,8 +43,10 @@
|
|
|
43
43
|
"test:unit": "mocha test/unit --recursive --timeout 10000",
|
|
44
44
|
"test:runner": "mocha test/runner --recursive --timeout 10000",
|
|
45
45
|
"test": "npm run test:unit && npm run test:runner",
|
|
46
|
-
"test:appium-quick": "mocha test/helper/
|
|
47
|
-
"test:appium-other": "mocha test/helper/
|
|
46
|
+
"test:appium-quick": "mocha test/helper/AppiumV2_test.js --grep 'quick'",
|
|
47
|
+
"test:appium-other": "mocha test/helper/AppiumV2_test.js --grep 'second'",
|
|
48
|
+
"test:ios:appium-quick": "mocha test/helper/AppiumV2_ios_test.js --grep 'quick'",
|
|
49
|
+
"test:ios:appium-other": "mocha test/helper/AppiumV2_ios_test.js --grep 'second'",
|
|
48
50
|
"test-app:start": "php -S 127.0.0.1:8000 -t test/data/app",
|
|
49
51
|
"test-app:stop": "kill -9 $(lsof -t -i:8000)",
|
|
50
52
|
"test:unit:webbapi:playwright": "mocha test/helper/Playwright_test.js",
|
|
@@ -86,9 +88,9 @@
|
|
|
86
88
|
"fn-args": "4.0.0",
|
|
87
89
|
"fs-extra": "8.1.0",
|
|
88
90
|
"glob": "6.0.1",
|
|
89
|
-
"html-minifier
|
|
91
|
+
"html-minifier": "4.0.0",
|
|
90
92
|
"inquirer": "6.5.2",
|
|
91
|
-
"joi": "17.
|
|
93
|
+
"joi": "17.11.0",
|
|
92
94
|
"js-beautify": "1.14.9",
|
|
93
95
|
"lodash.clonedeep": "4.5.0",
|
|
94
96
|
"lodash.merge": "4.6.2",
|
|
@@ -115,17 +117,17 @@
|
|
|
115
117
|
"@types/node": "20.4.4",
|
|
116
118
|
"@wdio/sauce-service": "8.3.8",
|
|
117
119
|
"@wdio/selenium-standalone-service": "8.3.2",
|
|
118
|
-
"@wdio/utils": "8.
|
|
120
|
+
"@wdio/utils": "8.20.3",
|
|
119
121
|
"apollo-server-express": "2.25.3",
|
|
120
122
|
"chai-as-promised": "7.1.1",
|
|
121
123
|
"chai-subset": "1.6.0",
|
|
122
|
-
"contributor-faces": "1.0
|
|
124
|
+
"contributor-faces": "1.1.0",
|
|
123
125
|
"documentation": "12.3.0",
|
|
124
126
|
"dtslint": "4.1.6",
|
|
125
127
|
"electron": "27.0.2",
|
|
126
|
-
"eslint": "8.
|
|
128
|
+
"eslint": "8.53.0",
|
|
127
129
|
"eslint-config-airbnb-base": "15.0.0",
|
|
128
|
-
"eslint-plugin-import": "2.
|
|
130
|
+
"eslint-plugin-import": "2.29.0",
|
|
129
131
|
"eslint-plugin-mocha": "6.3.0",
|
|
130
132
|
"expect": "29.7.0",
|
|
131
133
|
"express": "4.17.2",
|
|
@@ -140,13 +142,13 @@
|
|
|
140
142
|
"qrcode-terminal": "0.12.0",
|
|
141
143
|
"rosie": "2.1.0",
|
|
142
144
|
"runok": "0.9.3",
|
|
143
|
-
"sinon": "
|
|
145
|
+
"sinon": "17.0.1",
|
|
144
146
|
"sinon-chai": "3.7.0",
|
|
145
147
|
"testcafe": "3.3.0",
|
|
146
148
|
"ts-morph": "19.0.0",
|
|
147
149
|
"ts-node": "10.9.1",
|
|
148
150
|
"tsd-jsdoc": "2.5.0",
|
|
149
|
-
"typedoc": "0.
|
|
151
|
+
"typedoc": "0.25.3",
|
|
150
152
|
"typedoc-plugin-markdown": "3.13.4",
|
|
151
153
|
"typescript": "5.2.2",
|
|
152
154
|
"wdio-docker-service": "1.5.0",
|
|
@@ -2816,6 +2816,10 @@ declare namespace CodeceptJS {
|
|
|
2816
2816
|
* npm i playwright-core@^1.18 --save
|
|
2817
2817
|
* ```
|
|
2818
2818
|
*
|
|
2819
|
+
* Breaking Changes: if you use Playwright v1.38 and later, it will no longer download browsers automatically.
|
|
2820
|
+
*
|
|
2821
|
+
* Run `npx playwright install` to download browsers after `npm install`.
|
|
2822
|
+
*
|
|
2819
2823
|
* Using playwright-core package, will prevent the download of browser binaries and allow connecting to an existing browser installation or for connecting to a remote one.
|
|
2820
2824
|
*
|
|
2821
2825
|
*
|
|
@@ -3178,6 +3182,18 @@ declare namespace CodeceptJS {
|
|
|
3178
3182
|
* @returns automatically synchronized promise through #recorder
|
|
3179
3183
|
*/
|
|
3180
3184
|
blur(locator: CodeceptJS.LocatorOrString, options?: any): Promise<void>;
|
|
3185
|
+
/**
|
|
3186
|
+
* Return the checked status of given element.
|
|
3187
|
+
* @param locator - element located by CSS|XPath|strict locator.
|
|
3188
|
+
* @param [options] - See https://playwright.dev/docs/api/class-locator#locator-is-checked
|
|
3189
|
+
*/
|
|
3190
|
+
grabCheckedElementStatus(locator: CodeceptJS.LocatorOrString, options?: any): Promise<boolean>;
|
|
3191
|
+
/**
|
|
3192
|
+
* Return the disabled status of given element.
|
|
3193
|
+
* @param locator - element located by CSS|XPath|strict locator.
|
|
3194
|
+
* @param [options] - See https://playwright.dev/docs/api/class-locator#locator-is-disabled
|
|
3195
|
+
*/
|
|
3196
|
+
grabDisabledElementStatus(locator: CodeceptJS.LocatorOrString, options?: any): Promise<boolean>;
|
|
3181
3197
|
/**
|
|
3182
3198
|
* Drag an item to a destination element.
|
|
3183
3199
|
*
|
|
@@ -6171,6 +6187,14 @@ declare namespace CodeceptJS {
|
|
|
6171
6187
|
*
|
|
6172
6188
|
* <!-- configuration -->
|
|
6173
6189
|
*
|
|
6190
|
+
* #### Trace Recording Customization
|
|
6191
|
+
*
|
|
6192
|
+
* Trace recording provides complete information on test execution and includes screenshots, and network requests logged during run.
|
|
6193
|
+
* Traces will be saved to `output/trace`
|
|
6194
|
+
*
|
|
6195
|
+
* * `trace`: enables trace recording for failed tests; trace are saved into `output/trace` folder
|
|
6196
|
+
* * `keepTraceForPassedTests`: - save trace for passed tests
|
|
6197
|
+
*
|
|
6174
6198
|
* #### Example #1: Wait for 0 network connections.
|
|
6175
6199
|
*
|
|
6176
6200
|
* ```js
|
package/typings/types.d.ts
CHANGED
|
@@ -2903,6 +2903,10 @@ declare namespace CodeceptJS {
|
|
|
2903
2903
|
* npm i playwright-core@^1.18 --save
|
|
2904
2904
|
* ```
|
|
2905
2905
|
*
|
|
2906
|
+
* Breaking Changes: if you use Playwright v1.38 and later, it will no longer download browsers automatically.
|
|
2907
|
+
*
|
|
2908
|
+
* Run `npx playwright install` to download browsers after `npm install`.
|
|
2909
|
+
*
|
|
2906
2910
|
* Using playwright-core package, will prevent the download of browser binaries and allow connecting to an existing browser installation or for connecting to a remote one.
|
|
2907
2911
|
*
|
|
2908
2912
|
*
|
|
@@ -3265,6 +3269,18 @@ declare namespace CodeceptJS {
|
|
|
3265
3269
|
* @returns automatically synchronized promise through #recorder
|
|
3266
3270
|
*/
|
|
3267
3271
|
blur(locator: CodeceptJS.LocatorOrString, options?: any): Promise<void>;
|
|
3272
|
+
/**
|
|
3273
|
+
* Return the checked status of given element.
|
|
3274
|
+
* @param locator - element located by CSS|XPath|strict locator.
|
|
3275
|
+
* @param [options] - See https://playwright.dev/docs/api/class-locator#locator-is-checked
|
|
3276
|
+
*/
|
|
3277
|
+
grabCheckedElementStatus(locator: CodeceptJS.LocatorOrString, options?: any): Promise<boolean>;
|
|
3278
|
+
/**
|
|
3279
|
+
* Return the disabled status of given element.
|
|
3280
|
+
* @param locator - element located by CSS|XPath|strict locator.
|
|
3281
|
+
* @param [options] - See https://playwright.dev/docs/api/class-locator#locator-is-disabled
|
|
3282
|
+
*/
|
|
3283
|
+
grabDisabledElementStatus(locator: CodeceptJS.LocatorOrString, options?: any): Promise<boolean>;
|
|
3268
3284
|
/**
|
|
3269
3285
|
* Drag an item to a destination element.
|
|
3270
3286
|
*
|
|
@@ -6258,6 +6274,8 @@ declare namespace CodeceptJS {
|
|
|
6258
6274
|
* @property [disableScreenshots = false] - don't save screenshot on failure.
|
|
6259
6275
|
* @property [fullPageScreenshots = false] - make full page screenshots on failure.
|
|
6260
6276
|
* @property [uniqueScreenshotNames = false] - option to prevent screenshot override if you have scenarios with the same name in different suites.
|
|
6277
|
+
* @property [trace = false] - record [tracing information](https://pptr.dev/api/puppeteer.tracing) with screenshots.
|
|
6278
|
+
* @property [keepTraceForPassedTests = false] - save trace for passed tests.
|
|
6261
6279
|
* @property [keepBrowserState = false] - keep browser state between tests when `restart` is set to false.
|
|
6262
6280
|
* @property [keepCookies = false] - keep cookies between tests when `restart` is set to false.
|
|
6263
6281
|
* @property [waitForAction = 100] - how long to wait after click, doubleClick or PressKey actions in ms. Default: 100.
|
|
@@ -6280,6 +6298,8 @@ declare namespace CodeceptJS {
|
|
|
6280
6298
|
disableScreenshots?: boolean;
|
|
6281
6299
|
fullPageScreenshots?: boolean;
|
|
6282
6300
|
uniqueScreenshotNames?: boolean;
|
|
6301
|
+
trace?: boolean;
|
|
6302
|
+
keepTraceForPassedTests?: boolean;
|
|
6283
6303
|
keepBrowserState?: boolean;
|
|
6284
6304
|
keepCookies?: boolean;
|
|
6285
6305
|
waitForAction?: number;
|
|
@@ -6313,6 +6333,14 @@ declare namespace CodeceptJS {
|
|
|
6313
6333
|
*
|
|
6314
6334
|
* <!-- configuration -->
|
|
6315
6335
|
*
|
|
6336
|
+
* #### Trace Recording Customization
|
|
6337
|
+
*
|
|
6338
|
+
* Trace recording provides complete information on test execution and includes screenshots, and network requests logged during run.
|
|
6339
|
+
* Traces will be saved to `output/trace`
|
|
6340
|
+
*
|
|
6341
|
+
* * `trace`: enables trace recording for failed tests; trace are saved into `output/trace` folder
|
|
6342
|
+
* * `keepTraceForPassedTests`: - save trace for passed tests
|
|
6343
|
+
*
|
|
6316
6344
|
* #### Example #1: Wait for 0 network connections.
|
|
6317
6345
|
*
|
|
6318
6346
|
* ```js
|