codeceptjs 3.3.8-beta.1 → 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 +47 -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 +25 -18
- 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
|
@@ -2,7 +2,7 @@ const promiseRetry = require('promise-retry');
|
|
|
2
2
|
const event = require('./event');
|
|
3
3
|
const recorder = require('./recorder');
|
|
4
4
|
const assertThrown = require('./assert/throws');
|
|
5
|
-
const { isAsyncFunction } = require('./utils');
|
|
5
|
+
const { ucfirst, isAsyncFunction } = require('./utils');
|
|
6
6
|
const parser = require('./parser');
|
|
7
7
|
|
|
8
8
|
const injectHook = function (inject, suite) {
|
|
@@ -107,7 +107,7 @@ module.exports.test = (test) => {
|
|
|
107
107
|
/**
|
|
108
108
|
* Injects arguments to function from controller
|
|
109
109
|
*/
|
|
110
|
-
module.exports.injected = function (fn, suite, hookName) {
|
|
110
|
+
module.exports.injected = function (fn, suite, hookName) {
|
|
111
111
|
return function (done) {
|
|
112
112
|
const errHandler = (err) => {
|
|
113
113
|
recorder.session.start('teardown');
|
|
@@ -125,35 +125,42 @@ module.exports.injected = function (fn, suite, hookName) {
|
|
|
125
125
|
if (!fn) throw new Error('fn is not defined');
|
|
126
126
|
|
|
127
127
|
event.emit(event.hook.started, suite);
|
|
128
|
+
|
|
129
|
+
this.test.body = fn.toString();
|
|
130
|
+
|
|
128
131
|
if (!recorder.isRunning()) {
|
|
129
|
-
recorder.start();
|
|
130
132
|
recorder.errHandler((err) => {
|
|
131
133
|
errHandler(err);
|
|
132
134
|
});
|
|
133
135
|
}
|
|
134
136
|
|
|
135
|
-
|
|
137
|
+
const opts = suite.opts || {};
|
|
138
|
+
const retries = opts[`retry${ucfirst(hookName)}`] || 0;
|
|
136
139
|
|
|
137
|
-
recorder.retry(suite.retries());
|
|
138
140
|
promiseRetry(async (retry) => {
|
|
139
141
|
try {
|
|
140
|
-
|
|
142
|
+
recorder.startUnlessRunning();
|
|
143
|
+
await fn.call(this, getInjectedArguments(fn));
|
|
144
|
+
await recorder.promise();
|
|
141
145
|
} catch (err) {
|
|
142
146
|
retry(err);
|
|
147
|
+
} finally {
|
|
148
|
+
recorder.stop();
|
|
149
|
+
recorder.start();
|
|
143
150
|
}
|
|
144
|
-
}, { retries
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
}, { retries })
|
|
152
|
+
.then(() => {
|
|
153
|
+
recorder.add('fire hook.passed', () => event.emit(event.hook.passed, suite));
|
|
154
|
+
recorder.add(`finish ${hookName} hook`, () => done());
|
|
155
|
+
recorder.catch();
|
|
156
|
+
}).catch((e) => {
|
|
157
|
+
recorder.throw(e);
|
|
158
|
+
recorder.catch((e) => {
|
|
159
|
+
const err = (recorder.getAsyncErr() === null) ? e : recorder.getAsyncErr();
|
|
160
|
+
errHandler(err);
|
|
161
|
+
});
|
|
162
|
+
recorder.add('fire hook.failed', () => event.emit(event.hook.failed, suite, e));
|
|
154
163
|
});
|
|
155
|
-
recorder.add('fire hook.failed', () => event.emit(event.hook.failed, suite, e));
|
|
156
|
-
});
|
|
157
164
|
};
|
|
158
165
|
};
|
|
159
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.
|