codeceptjs 3.3.7 → 3.4.0-beta.1
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 +2422 -0
- package/README.md +31 -32
- package/docs/advanced.md +48 -24
- package/docs/basics.md +115 -40
- package/docs/best.md +2 -2
- package/docs/build/ApiDataFactory.js +6 -6
- package/docs/build/Appium.js +2 -19
- package/docs/build/FileSystem.js +2 -2
- package/docs/build/GraphQLDataFactory.js +2 -2
- package/docs/build/Playwright.js +3 -2
- package/docs/build/TestCafe.js +4 -4
- package/docs/build/WebDriver.js +29 -164
- package/docs/helpers/ApiDataFactory.md +6 -6
- package/docs/helpers/FileSystem.md +2 -2
- package/docs/helpers/GraphQLDataFactory.md +2 -2
- package/docs/helpers/Playwright.md +2 -1
- package/docs/index.md +1 -1
- package/docs/plugins.md +73 -48
- package/docs/reports.md +0 -56
- package/docs/typescript.md +2 -8
- package/lib/actor.js +2 -1
- package/lib/cli.js +3 -3
- package/lib/codecept.js +2 -1
- package/lib/command/generate.js +3 -1
- package/lib/command/gherkin/snippets.js +8 -4
- package/lib/command/init.js +0 -8
- package/lib/command/run-workers.js +3 -6
- package/lib/command/utils.js +0 -10
- package/lib/command/workers/runTests.js +2 -2
- package/lib/config.js +5 -1
- package/lib/helper/ApiDataFactory.js +7 -7
- package/lib/helper/Appium.js +2 -19
- package/lib/helper/FileSystem.js +3 -3
- package/lib/helper/GraphQL.js +1 -1
- package/lib/helper/GraphQLDataFactory.js +3 -3
- package/lib/helper/JSONResponse.js +1 -1
- package/lib/helper/Mochawesome.js +1 -1
- package/lib/helper/Nightmare.js +1 -1
- package/lib/helper/Playwright.js +4 -3
- package/lib/helper/Protractor.js +1 -1
- package/lib/helper/Puppeteer.js +1 -1
- package/lib/helper/REST.js +1 -1
- package/lib/helper/TestCafe.js +5 -5
- package/lib/helper/WebDriver.js +30 -165
- package/lib/helper.js +0 -2
- package/lib/interfaces/bdd.js +1 -1
- package/lib/interfaces/featureConfig.js +1 -0
- package/lib/interfaces/gherkin.js +38 -25
- package/lib/listener/exit.js +2 -2
- package/lib/listener/retry.js +67 -0
- package/lib/listener/steps.js +1 -1
- package/lib/listener/timeout.js +47 -10
- package/lib/mochaFactory.js +3 -3
- package/lib/plugin/allure.js +14 -323
- package/lib/plugin/fakerTransform.js +2 -2
- package/lib/recorder.js +1 -1
- package/lib/scenario.js +20 -21
- package/lib/utils.js +6 -0
- package/lib/workers.js +4 -7
- package/package.json +13 -17
- package/typings/index.d.ts +66 -1
- package/typings/promiseBasedTypes.d.ts +12 -12
- package/typings/types.d.ts +95 -262
package/lib/scenario.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
const promiseRetry = require('promise-retry');
|
|
1
2
|
const event = require('./event');
|
|
2
3
|
const recorder = require('./recorder');
|
|
3
4
|
const assertThrown = require('./assert/throws');
|
|
4
|
-
const { isAsyncFunction } = require('./utils');
|
|
5
|
+
const { ucfirst, isAsyncFunction } = require('./utils');
|
|
5
6
|
const parser = require('./parser');
|
|
6
7
|
|
|
7
8
|
const injectHook = function (inject, suite) {
|
|
@@ -124,17 +125,31 @@ module.exports.injected = function (fn, suite, hookName) {
|
|
|
124
125
|
if (!fn) throw new Error('fn is not defined');
|
|
125
126
|
|
|
126
127
|
event.emit(event.hook.started, suite);
|
|
128
|
+
|
|
129
|
+
this.test.body = fn.toString();
|
|
130
|
+
|
|
127
131
|
if (!recorder.isRunning()) {
|
|
128
|
-
recorder.start();
|
|
129
132
|
recorder.errHandler((err) => {
|
|
130
133
|
errHandler(err);
|
|
131
134
|
});
|
|
132
135
|
}
|
|
133
136
|
|
|
134
|
-
|
|
137
|
+
const opts = suite.opts || {};
|
|
138
|
+
const retries = opts[`retry${ucfirst(hookName)}`] || 0;
|
|
135
139
|
|
|
136
|
-
|
|
137
|
-
|
|
140
|
+
promiseRetry(async (retry) => {
|
|
141
|
+
try {
|
|
142
|
+
recorder.startUnlessRunning();
|
|
143
|
+
await fn.call(this, getInjectedArguments(fn));
|
|
144
|
+
await recorder.promise();
|
|
145
|
+
} catch (err) {
|
|
146
|
+
retry(err);
|
|
147
|
+
} finally {
|
|
148
|
+
recorder.stop();
|
|
149
|
+
recorder.start();
|
|
150
|
+
}
|
|
151
|
+
}, { retries })
|
|
152
|
+
.then(() => {
|
|
138
153
|
recorder.add('fire hook.passed', () => event.emit(event.hook.passed, suite));
|
|
139
154
|
recorder.add(`finish ${hookName} hook`, () => done());
|
|
140
155
|
recorder.catch();
|
|
@@ -146,22 +161,6 @@ module.exports.injected = function (fn, suite, hookName) {
|
|
|
146
161
|
});
|
|
147
162
|
recorder.add('fire hook.failed', () => event.emit(event.hook.failed, suite, e));
|
|
148
163
|
});
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
try {
|
|
153
|
-
fn.call(this, getInjectedArguments(fn));
|
|
154
|
-
recorder.add('fire hook.passed', () => event.emit(event.hook.passed, suite));
|
|
155
|
-
recorder.add(`finish ${hookName} hook`, () => done());
|
|
156
|
-
recorder.catch();
|
|
157
|
-
} catch (err) {
|
|
158
|
-
recorder.throw(err);
|
|
159
|
-
recorder.catch((e) => {
|
|
160
|
-
const err = (recorder.getAsyncErr() === null) ? e : recorder.getAsyncErr();
|
|
161
|
-
errHandler(err);
|
|
162
|
-
});
|
|
163
|
-
recorder.add('fire hook.failed', () => event.emit(event.hook.failed, suite, err));
|
|
164
|
-
}
|
|
165
164
|
};
|
|
166
165
|
};
|
|
167
166
|
|
package/lib/utils.js
CHANGED
|
@@ -449,3 +449,9 @@ module.exports.requireWithFallback = function (...packages) {
|
|
|
449
449
|
|
|
450
450
|
throw new Error(`Cannot find modules ${packages.join(',')}`);
|
|
451
451
|
};
|
|
452
|
+
|
|
453
|
+
module.exports.isNotSet = function (obj) {
|
|
454
|
+
if (obj === null) return true;
|
|
455
|
+
if (obj === undefined) return true;
|
|
456
|
+
return false;
|
|
457
|
+
};
|
package/lib/workers.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/* eslint-disable max-classes-per-file */
|
|
2
|
-
const { EventEmitter } = require('events');
|
|
3
2
|
const path = require('path');
|
|
4
3
|
const mkdirp = require('mkdirp');
|
|
5
4
|
const { Worker } = require('worker_threads');
|
|
6
5
|
const { Suite, Test, reporters: { Base } } = require('mocha');
|
|
6
|
+
const { EventEmitter } = require('events');
|
|
7
7
|
const ms = require('ms');
|
|
8
8
|
const Codecept = require('./codecept');
|
|
9
9
|
const MochaFactory = require('./mochaFactory');
|
|
@@ -107,8 +107,7 @@ const convertToMochaTests = (testGroup) => {
|
|
|
107
107
|
mocha.files = testGroup;
|
|
108
108
|
mocha.loadFiles();
|
|
109
109
|
mocha.suite.eachTest((test) => {
|
|
110
|
-
|
|
111
|
-
group.push(id);
|
|
110
|
+
group.push(test.uid);
|
|
112
111
|
});
|
|
113
112
|
mocha.unloadFiles();
|
|
114
113
|
}
|
|
@@ -242,8 +241,7 @@ class Workers extends EventEmitter {
|
|
|
242
241
|
mocha.suite.eachTest((test) => {
|
|
243
242
|
const i = groupCounter % groups.length;
|
|
244
243
|
if (test) {
|
|
245
|
-
|
|
246
|
-
groups[i].push(id);
|
|
244
|
+
groups[i].push(test.uid);
|
|
247
245
|
groupCounter++;
|
|
248
246
|
}
|
|
249
247
|
});
|
|
@@ -264,8 +262,7 @@ class Workers extends EventEmitter {
|
|
|
264
262
|
const i = indexOfSmallestElement(groups);
|
|
265
263
|
suite.tests.forEach((test) => {
|
|
266
264
|
if (test) {
|
|
267
|
-
|
|
268
|
-
groups[i].push(id);
|
|
265
|
+
groups[i].push(test.uid);
|
|
269
266
|
}
|
|
270
267
|
});
|
|
271
268
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeceptjs",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0-beta.1",
|
|
4
4
|
"description": "Supercharged End 2 End Testing Framework for NodeJS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"acceptance",
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
},
|
|
36
36
|
"repository": "Codeception/codeceptjs",
|
|
37
37
|
"scripts": {
|
|
38
|
-
"build": "tsc -p ./",
|
|
39
38
|
"json-server": "./node_modules/json-server/bin/index.js test/data/rest/db.json -p 8010 --watch -m test/data/rest/headers.js",
|
|
40
39
|
"json-server:graphql": "node test/data/graphql/index.js",
|
|
41
40
|
"lint": "eslint bin/ examples/ lib/ test/ translations/ runok.js",
|
|
@@ -56,23 +55,23 @@
|
|
|
56
55
|
"dependencies": {
|
|
57
56
|
"@codeceptjs/configure": "^0.8.0",
|
|
58
57
|
"@codeceptjs/helper": "^1.0.2",
|
|
58
|
+
"@cucumber/cucumber-expressions": "^16",
|
|
59
|
+
"@cucumber/gherkin": "^26",
|
|
60
|
+
"@cucumber/messages": "^21.0.1",
|
|
59
61
|
"acorn": "^7.4.1",
|
|
60
|
-
"allure-js-commons": "^1.3.2",
|
|
61
62
|
"arrify": "^2.0.1",
|
|
62
|
-
"axios": "^
|
|
63
|
+
"axios": "^1.3.3",
|
|
63
64
|
"chai": "^4.3.6",
|
|
64
65
|
"chai-deep-match": "^1.2.1",
|
|
65
66
|
"chalk": "^4.1.2",
|
|
66
67
|
"commander": "^2.20.3",
|
|
67
68
|
"cross-spawn": "^7.0.3",
|
|
68
69
|
"css-to-xpath": "^0.1.0",
|
|
69
|
-
"cucumber-expressions": "^6.6.2",
|
|
70
70
|
"envinfo": "^7.8.1",
|
|
71
71
|
"escape-string-regexp": "^1.0.3",
|
|
72
72
|
"figures": "^3.2.0",
|
|
73
73
|
"fn-args": "^4.0.0",
|
|
74
74
|
"fs-extra": "^8.1.0",
|
|
75
|
-
"gherkin": "^5.1.0",
|
|
76
75
|
"glob": "^6.0.1",
|
|
77
76
|
"inquirer": "^6.5.2",
|
|
78
77
|
"joi": "^17.6.0",
|
|
@@ -80,21 +79,19 @@
|
|
|
80
79
|
"lodash.clonedeep": "^4.5.0",
|
|
81
80
|
"lodash.merge": "^4.6.2",
|
|
82
81
|
"mkdirp": "^1.0.4",
|
|
83
|
-
"mocha": "8.
|
|
84
|
-
"mocha-junit-reporter": "1.23.
|
|
82
|
+
"mocha": "^8.2.0",
|
|
83
|
+
"mocha-junit-reporter": "^1.23.3",
|
|
85
84
|
"ms": "^2.1.3",
|
|
86
85
|
"parse-function": "^5.6.4",
|
|
87
86
|
"promise-retry": "^1.1.1",
|
|
88
|
-
"requireg": "^0.2.2",
|
|
89
87
|
"resq": "^1.10.2",
|
|
90
|
-
"semver": "^6.3.0",
|
|
91
88
|
"sprintf-js": "^1.1.1",
|
|
92
|
-
"uuid": "^
|
|
89
|
+
"uuid": "^9.0"
|
|
93
90
|
},
|
|
94
91
|
"devDependencies": {
|
|
95
92
|
"@codeceptjs/detox-helper": "^1.0.2",
|
|
96
93
|
"@codeceptjs/mock-request": "^0.3.1",
|
|
97
|
-
"@faker-js/faker": "^
|
|
94
|
+
"@faker-js/faker": "^7.6.0",
|
|
98
95
|
"@pollyjs/adapter-puppeteer": "^5.1.0",
|
|
99
96
|
"@pollyjs/core": "^5.1.0",
|
|
100
97
|
"@types/inquirer": "^0.0.35",
|
|
@@ -118,10 +115,10 @@
|
|
|
118
115
|
"form-data": "^3.0.1",
|
|
119
116
|
"graphql": "^14.6.0",
|
|
120
117
|
"husky": "^8.0.1",
|
|
118
|
+
"inquirer-test": "^2.0.1",
|
|
121
119
|
"jsdoc": "^3.6.10",
|
|
122
120
|
"jsdoc-typeof-plugin": "^1.0.0",
|
|
123
121
|
"json-server": "^0.10.1",
|
|
124
|
-
"mocha-parallel-tests": "^2.3.0",
|
|
125
122
|
"nightmare": "^3.0.2",
|
|
126
123
|
"nodemon": "^1.19.4",
|
|
127
124
|
"playwright": "^1.23.2",
|
|
@@ -131,7 +128,7 @@
|
|
|
131
128
|
"runok": "^0.9.2",
|
|
132
129
|
"sinon": "^9.2.4",
|
|
133
130
|
"sinon-chai": "^3.7.0",
|
|
134
|
-
"testcafe": "^1.
|
|
131
|
+
"testcafe": "^2.1.0",
|
|
135
132
|
"ts-morph": "^3.1.3",
|
|
136
133
|
"ts-node": "^10.9.1",
|
|
137
134
|
"tsd-jsdoc": "https://github.com/englercj/tsd-jsdoc.git",
|
|
@@ -139,11 +136,10 @@
|
|
|
139
136
|
"typedoc-plugin-markdown": "^3.13.4",
|
|
140
137
|
"typescript": "^4.8.4",
|
|
141
138
|
"wdio-docker-service": "^1.5.0",
|
|
142
|
-
"webdriverio": "^
|
|
139
|
+
"webdriverio": "^8.3.8",
|
|
143
140
|
"xml2js": "^0.4.23",
|
|
144
141
|
"xmldom": "^0.1.31",
|
|
145
|
-
"xpath": "0.0.27"
|
|
146
|
-
"inquirer-test": "^2.0.1"
|
|
142
|
+
"xpath": "0.0.27"
|
|
147
143
|
},
|
|
148
144
|
"engines": {
|
|
149
145
|
"node": ">=8.9.1",
|
package/typings/index.d.ts
CHANGED
|
@@ -17,6 +17,22 @@ declare namespace CodeceptJS {
|
|
|
17
17
|
path?: string,
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
type RetryConfig = {
|
|
21
|
+
grep: string;
|
|
22
|
+
Feature: number;
|
|
23
|
+
Scenario: number;
|
|
24
|
+
Before: number;
|
|
25
|
+
After: number;
|
|
26
|
+
BeforeSuite: number;
|
|
27
|
+
AfterSuite: number;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
type TimeoutConfig = {
|
|
31
|
+
grep: string;
|
|
32
|
+
Feature: number;
|
|
33
|
+
Scenario: number;
|
|
34
|
+
};
|
|
35
|
+
|
|
20
36
|
type MainConfig = {
|
|
21
37
|
/** Pattern to locate CodeceptJS tests.
|
|
22
38
|
* Allows to enter glob pattern or an Array<string> of patterns to match tests / test file names.
|
|
@@ -172,8 +188,57 @@ declare namespace CodeceptJS {
|
|
|
172
188
|
* ```js
|
|
173
189
|
* timeout: 20,
|
|
174
190
|
* ```
|
|
191
|
+
*
|
|
192
|
+
* Can be customized to use different timeouts for a subset of tests:
|
|
193
|
+
*
|
|
194
|
+
* ```js
|
|
195
|
+
* timeout: [
|
|
196
|
+
* 10,
|
|
197
|
+
* {
|
|
198
|
+
* grep: '@slow',
|
|
199
|
+
* Scenario: 20
|
|
200
|
+
* }
|
|
201
|
+
* ]
|
|
202
|
+
* ```
|
|
175
203
|
*/
|
|
176
|
-
timeout?: number;
|
|
204
|
+
timeout?: number | Array<TimeoutConfig> | TimeoutConfig;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Configure retry strategy for tests
|
|
208
|
+
*
|
|
209
|
+
* To retry all tests 3 times:
|
|
210
|
+
*
|
|
211
|
+
* ```js
|
|
212
|
+
* retry: 3
|
|
213
|
+
* ```
|
|
214
|
+
*
|
|
215
|
+
* To retry only Before hook 3 times:
|
|
216
|
+
*
|
|
217
|
+
* ```js
|
|
218
|
+
* retry: {
|
|
219
|
+
* Before: 3
|
|
220
|
+
* }
|
|
221
|
+
* ```
|
|
222
|
+
*
|
|
223
|
+
* To retry tests marked as flaky 3 times, other 1 time:
|
|
224
|
+
*
|
|
225
|
+
* ```js
|
|
226
|
+
* retry: [
|
|
227
|
+
* {
|
|
228
|
+
* Scenario: 1,
|
|
229
|
+
* Before: 1
|
|
230
|
+
* },
|
|
231
|
+
* {
|
|
232
|
+
* grep: '@flaky',
|
|
233
|
+
* Scenario: 3
|
|
234
|
+
* Before: 3
|
|
235
|
+
* }
|
|
236
|
+
* ]
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
retry?: number | Array<RetryConfig> | RetryConfig;
|
|
240
|
+
|
|
241
|
+
|
|
177
242
|
/** Disable registering global functions (Before, Scenario, etc). Not recommended */
|
|
178
243
|
noGlobals?: boolean;
|
|
179
244
|
/**
|
|
@@ -42,8 +42,8 @@ declare namespace CodeceptJS {
|
|
|
42
42
|
* ```js
|
|
43
43
|
* // tests/factories/posts.js
|
|
44
44
|
*
|
|
45
|
-
* const Factory = require('rosie')
|
|
46
|
-
* const faker = require('@faker-js/faker');
|
|
45
|
+
* const { Factory } = require('rosie');
|
|
46
|
+
* const { faker } = require('@faker-js/faker');
|
|
47
47
|
*
|
|
48
48
|
* module.exports = new Factory()
|
|
49
49
|
* // no need to set id, it will be set by REST API
|
|
@@ -190,10 +190,10 @@ declare namespace CodeceptJS {
|
|
|
190
190
|
* I.have('user', { }, { age: 33, height: 55 })
|
|
191
191
|
* ```
|
|
192
192
|
* @param factory - factory to use
|
|
193
|
-
* @param params - predefined parameters
|
|
194
|
-
* @param options - options for programmatically generate the attributes
|
|
193
|
+
* @param [params] - predefined parameters
|
|
194
|
+
* @param [options] - options for programmatically generate the attributes
|
|
195
195
|
*/
|
|
196
|
-
have(factory: any, params
|
|
196
|
+
have(factory: any, params?: any, options?: any): Promise<any>;
|
|
197
197
|
/**
|
|
198
198
|
* Generates bunch of records and saves multiple API requests to store them.
|
|
199
199
|
*
|
|
@@ -208,7 +208,7 @@ declare namespace CodeceptJS {
|
|
|
208
208
|
* I.haveMultiple('post', 3, { author: 'davert' }, { publish_date: '01.01.1997' });
|
|
209
209
|
* ```
|
|
210
210
|
*/
|
|
211
|
-
haveMultiple(factory: any, times: any, params
|
|
211
|
+
haveMultiple(factory: any, times: any, params?: any, options?: any): Promise<any>;
|
|
212
212
|
/**
|
|
213
213
|
* Executes request to create a record in API.
|
|
214
214
|
* Can be replaced from a in custom helper.
|
|
@@ -1153,10 +1153,10 @@ declare namespace CodeceptJS {
|
|
|
1153
1153
|
*/
|
|
1154
1154
|
seeFile(name: string): Promise<any>;
|
|
1155
1155
|
/**
|
|
1156
|
-
* Waits for file to be present in current directory.
|
|
1156
|
+
* Waits for the file to be present in the current directory.
|
|
1157
1157
|
*
|
|
1158
1158
|
* ```js
|
|
1159
|
-
* I.handleDownloads();
|
|
1159
|
+
* I.handleDownloads('downloads/largeFilesName.txt');
|
|
1160
1160
|
* I.click('Download large File');
|
|
1161
1161
|
* I.amInPath('output/downloads');
|
|
1162
1162
|
* I.waitForFile('largeFilesName.txt', 10); // wait 10 seconds for file
|
|
@@ -1337,8 +1337,8 @@ declare namespace CodeceptJS {
|
|
|
1337
1337
|
* ```js
|
|
1338
1338
|
* // tests/factories/users.js
|
|
1339
1339
|
*
|
|
1340
|
-
* const Factory = require('rosie').Factory;
|
|
1341
|
-
* const faker = require('@faker-js/faker');
|
|
1340
|
+
* const { Factory } = require('rosie').Factory;
|
|
1341
|
+
* const { faker } = require('@faker-js/faker');
|
|
1342
1342
|
*
|
|
1343
1343
|
* // Used with a constructor function passed to Factory, so that the final build
|
|
1344
1344
|
* // object matches the necessary pattern to be sent as the variables object.
|
|
@@ -3271,9 +3271,9 @@ declare namespace CodeceptJS {
|
|
|
3271
3271
|
* I.waitForFile('avatar.jpg', 5);
|
|
3272
3272
|
*
|
|
3273
3273
|
* ```
|
|
3274
|
-
* @param
|
|
3274
|
+
* @param fileName - set filename for downloaded file
|
|
3275
3275
|
*/
|
|
3276
|
-
handleDownloads(fileName
|
|
3276
|
+
handleDownloads(fileName: string): Promise<void>;
|
|
3277
3277
|
/**
|
|
3278
3278
|
* Perform a click on a link or a button, given by a locator.
|
|
3279
3279
|
* If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string.
|