codeceptjs 4.0.0-beta.2 → 4.0.0-beta.3
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/bin/codecept.js +84 -81
- package/lib/actor.js +13 -13
- package/lib/ai.js +10 -13
- package/lib/assert/empty.js +20 -21
- package/lib/assert/equal.js +37 -39
- package/lib/assert/error.js +14 -14
- package/lib/assert/include.js +46 -47
- package/lib/assert/throws.js +13 -11
- package/lib/assert/truth.js +19 -22
- package/lib/assert.js +4 -2
- package/lib/cli.js +57 -49
- package/lib/codecept.js +142 -155
- package/lib/colorUtils.js +3 -3
- package/lib/command/configMigrate.js +58 -52
- package/lib/command/definitions.js +88 -89
- package/lib/command/dryRun.js +71 -68
- package/lib/command/generate.js +197 -188
- package/lib/command/gherkin/init.js +27 -16
- package/lib/command/gherkin/snippets.js +20 -20
- package/lib/command/gherkin/steps.js +8 -8
- package/lib/command/info.js +40 -38
- package/lib/command/init.js +290 -288
- package/lib/command/interactive.js +32 -32
- package/lib/command/list.js +26 -26
- package/lib/command/run-multiple/chunk.js +5 -5
- package/lib/command/run-multiple/collection.js +3 -3
- package/lib/command/run-multiple/run.js +6 -2
- package/lib/command/run-multiple.js +113 -93
- package/lib/command/run-rerun.js +20 -25
- package/lib/command/run-workers.js +64 -66
- package/lib/command/run.js +26 -29
- package/lib/command/utils.js +80 -65
- package/lib/command/workers/runTests.js +10 -10
- package/lib/config.js +10 -9
- package/lib/container.js +40 -48
- package/lib/data/context.js +60 -59
- package/lib/data/dataScenarioConfig.js +47 -47
- package/lib/data/dataTableArgument.js +29 -29
- package/lib/data/table.js +26 -20
- package/lib/event.js +163 -167
- package/lib/heal.js +13 -17
- package/lib/helper/AI.js +130 -41
- package/lib/helper/ApiDataFactory.js +73 -69
- package/lib/helper/Appium.js +413 -382
- package/lib/helper/ExpectHelper.js +40 -48
- package/lib/helper/FileSystem.js +80 -79
- package/lib/helper/GraphQL.js +44 -43
- package/lib/helper/GraphQLDataFactory.js +50 -50
- package/lib/helper/JSONResponse.js +65 -62
- package/lib/helper/Mochawesome.js +28 -28
- package/lib/helper/MockServer.js +12 -14
- package/lib/helper/Nightmare.js +662 -566
- package/lib/helper/Playwright.js +1361 -1216
- package/lib/helper/Protractor.js +663 -627
- package/lib/helper/Puppeteer.js +1231 -1128
- package/lib/helper/REST.js +159 -68
- package/lib/helper/SoftExpectHelper.js +2 -2
- package/lib/helper/TestCafe.js +490 -484
- package/lib/helper/WebDriver.js +1297 -1156
- package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
- package/lib/helper/errors/ConnectionRefused.js +1 -1
- package/lib/helper/errors/ElementAssertion.js +2 -2
- package/lib/helper/errors/ElementNotFound.js +2 -2
- package/lib/helper/errors/RemoteBrowserConnectionRefused.js +1 -1
- package/lib/helper/extras/Console.js +1 -1
- package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
- package/lib/helper/extras/PlaywrightReactVueLocator.js +1 -1
- package/lib/helper/extras/PlaywrightRestartOpts.js +21 -18
- package/lib/helper/extras/Popup.js +1 -1
- package/lib/helper/extras/React.js +3 -3
- package/lib/helper/network/actions.js +14 -7
- package/lib/helper/network/utils.js +3 -2
- package/lib/helper/scripts/blurElement.js +1 -1
- package/lib/helper/scripts/focusElement.js +1 -1
- package/lib/helper/scripts/highlightElement.js +1 -1
- package/lib/helper/scripts/isElementClickable.js +1 -1
- package/lib/helper/testcafe/testControllerHolder.js +1 -1
- package/lib/helper/testcafe/testcafe-utils.js +6 -7
- package/lib/helper.js +1 -3
- package/lib/history.js +6 -5
- package/lib/hooks.js +6 -6
- package/lib/html.js +7 -7
- package/lib/index.js +25 -41
- package/lib/interfaces/bdd.js +47 -64
- package/lib/interfaces/featureConfig.js +19 -19
- package/lib/interfaces/gherkin.js +124 -118
- package/lib/interfaces/scenarioConfig.js +29 -29
- package/lib/listener/artifacts.js +9 -9
- package/lib/listener/config.js +24 -24
- package/lib/listener/exit.js +12 -12
- package/lib/listener/helpers.js +42 -42
- package/lib/listener/mocha.js +11 -11
- package/lib/listener/retry.js +32 -30
- package/lib/listener/steps.js +50 -53
- package/lib/listener/timeout.js +54 -54
- package/lib/locator.js +6 -10
- package/lib/mochaFactory.js +18 -15
- package/lib/output.js +6 -10
- package/lib/parser.js +15 -12
- package/lib/pause.js +40 -33
- package/lib/plugin/allure.js +15 -15
- package/lib/plugin/autoDelay.js +29 -37
- package/lib/plugin/autoLogin.js +70 -65
- package/lib/plugin/commentStep.js +18 -18
- package/lib/plugin/coverage.js +115 -67
- package/lib/plugin/customLocator.js +21 -20
- package/lib/plugin/debugErrors.js +24 -24
- package/lib/plugin/eachElement.js +38 -38
- package/lib/plugin/fakerTransform.js +6 -6
- package/lib/plugin/heal.js +67 -108
- package/lib/plugin/pauseOnFail.js +11 -11
- package/lib/plugin/retryFailedStep.js +32 -39
- package/lib/plugin/retryTo.js +46 -40
- package/lib/plugin/screenshotOnFail.js +109 -87
- package/lib/plugin/selenoid.js +131 -118
- package/lib/plugin/standardActingHelpers.js +2 -8
- package/lib/plugin/stepByStepReport.js +110 -91
- package/lib/plugin/stepTimeout.js +24 -23
- package/lib/plugin/subtitles.js +34 -35
- package/lib/plugin/tryTo.js +40 -30
- package/lib/plugin/wdio.js +78 -75
- package/lib/recorder.js +14 -17
- package/lib/rerun.js +11 -10
- package/lib/scenario.js +25 -23
- package/lib/secret.js +4 -2
- package/lib/session.js +10 -10
- package/lib/step.js +12 -9
- package/lib/store.js +2 -3
- package/lib/transform.js +1 -1
- package/lib/translation.js +7 -8
- package/lib/ui.js +12 -14
- package/lib/utils.js +70 -72
- package/lib/within.js +10 -10
- package/lib/workerStorage.js +27 -25
- package/lib/workers.js +29 -32
- package/package.json +56 -57
- package/translations/de-DE.js +1 -1
- package/translations/fr-FR.js +1 -1
- package/translations/index.js +9 -13
- package/translations/it-IT.js +1 -1
- package/translations/ja-JP.js +1 -1
- package/translations/pl-PL.js +1 -1
- package/translations/pt-BR.js +1 -1
- package/translations/ru-RU.js +1 -1
- package/translations/zh-CN.js +1 -1
- package/translations/zh-TW.js +1 -1
- package/typings/index.d.ts +415 -65
- package/typings/promiseBasedTypes.d.ts +32 -0
- package/typings/types.d.ts +32 -0
- package/lib/dirname.js +0 -5
- package/lib/helper/Expect.js +0 -425
package/lib/translation.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import importSync from 'import-sync';
|
|
5
|
-
import * as translations from '../translations/index.js';
|
|
1
|
+
const merge = require('lodash.merge');
|
|
2
|
+
const path = require('path');
|
|
6
3
|
|
|
7
4
|
const defaultVocabulary = {
|
|
8
5
|
I: 'I',
|
|
9
6
|
actions: {},
|
|
10
7
|
};
|
|
11
8
|
|
|
12
|
-
|
|
9
|
+
class Translation {
|
|
13
10
|
constructor(vocabulary, loaded) {
|
|
14
11
|
this.vocabulary = vocabulary;
|
|
15
12
|
this.loaded = loaded !== false;
|
|
@@ -20,7 +17,7 @@ export default class Translation {
|
|
|
20
17
|
const filePath = path.join(global.codecept_dir, vocabularyFile);
|
|
21
18
|
|
|
22
19
|
try {
|
|
23
|
-
const vocabulary =
|
|
20
|
+
const vocabulary = require(filePath);
|
|
24
21
|
this.vocabulary = merge(this.vocabulary, vocabulary);
|
|
25
22
|
} catch (err) {
|
|
26
23
|
throw new Error(`Can't load vocabulary from ${filePath}; ${err}`);
|
|
@@ -43,7 +40,7 @@ export default class Translation {
|
|
|
43
40
|
}
|
|
44
41
|
|
|
45
42
|
static get langs() {
|
|
46
|
-
return translations;
|
|
43
|
+
return require('../translations');
|
|
47
44
|
}
|
|
48
45
|
|
|
49
46
|
static createDefault() {
|
|
@@ -54,3 +51,5 @@ export default class Translation {
|
|
|
54
51
|
return new Translation(defaultVocabulary, false);
|
|
55
52
|
}
|
|
56
53
|
}
|
|
54
|
+
|
|
55
|
+
module.exports = Translation;
|
package/lib/ui.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
const escapeRe = require('escape-string-regexp');
|
|
2
|
+
const Suite = require('mocha/lib/suite');
|
|
3
|
+
const Test = require('mocha/lib/test');
|
|
4
|
+
|
|
5
|
+
const scenario = require('./scenario');
|
|
6
|
+
const ScenarioConfig = require('./interfaces/scenarioConfig');
|
|
7
|
+
const FeatureConfig = require('./interfaces/featureConfig');
|
|
8
|
+
const addDataContext = require('./data/context');
|
|
9
|
+
const container = require('./container');
|
|
10
10
|
|
|
11
11
|
const setContextTranslation = (context) => {
|
|
12
12
|
const contexts = container.translation().value('contexts');
|
|
@@ -34,7 +34,7 @@ const setContextTranslation = (context) => {
|
|
|
34
34
|
* @param {Mocha.Suite} suite Root suite.
|
|
35
35
|
* @ignore
|
|
36
36
|
*/
|
|
37
|
-
|
|
37
|
+
module.exports = function (suite) {
|
|
38
38
|
const suites = [suite];
|
|
39
39
|
suite.timeout(0);
|
|
40
40
|
let afterAllHooks;
|
|
@@ -43,7 +43,7 @@ export function suite(suite) {
|
|
|
43
43
|
let afterEachHooksAreLoaded;
|
|
44
44
|
|
|
45
45
|
suite.on('pre-require', (context, file, mocha) => {
|
|
46
|
-
const common =
|
|
46
|
+
const common = require('mocha/lib/interfaces/common')(suites, context, mocha);
|
|
47
47
|
|
|
48
48
|
const addScenario = function (title, opts = {}, fn) {
|
|
49
49
|
const suite = suites[0];
|
|
@@ -233,6 +233,4 @@ export function suite(suite) {
|
|
|
233
233
|
afterAllHooksAreLoaded = true;
|
|
234
234
|
}
|
|
235
235
|
});
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
export default suite;
|
|
236
|
+
};
|
package/lib/utils.js
CHANGED
|
@@ -1,45 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import { convertColorToRGBA, isColorProperty } from './colorUtils.js';
|
|
11
|
-
|
|
12
|
-
const __dirname = path.resolve();
|
|
13
|
-
|
|
14
|
-
export function deepMerge(target, source) {
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const os = require('os');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const getFunctionArguments = require('fn-args');
|
|
5
|
+
const deepClone = require('lodash.clonedeep');
|
|
6
|
+
const { convertColorToRGBA, isColorProperty } = require('./colorUtils');
|
|
7
|
+
|
|
8
|
+
function deepMerge(target, source) {
|
|
9
|
+
const merge = require('lodash.merge');
|
|
15
10
|
return merge(target, source);
|
|
16
11
|
}
|
|
17
12
|
|
|
18
|
-
|
|
19
|
-
return createHash('sha256').update(test.fullTitle()).digest('base64')
|
|
13
|
+
module.exports.genTestId = (test) => {
|
|
14
|
+
return require('crypto').createHash('sha256').update(test.fullTitle()).digest('base64')
|
|
20
15
|
.slice(0, -2);
|
|
21
16
|
};
|
|
22
17
|
|
|
23
|
-
|
|
18
|
+
module.exports.deepMerge = deepMerge;
|
|
24
19
|
|
|
25
|
-
|
|
20
|
+
module.exports.deepClone = deepClone;
|
|
21
|
+
|
|
22
|
+
module.exports.isGenerator = function (fn) {
|
|
26
23
|
return fn.constructor.name === 'GeneratorFunction';
|
|
27
24
|
};
|
|
28
25
|
|
|
29
|
-
|
|
26
|
+
const isFunction = module.exports.isFunction = function (fn) {
|
|
30
27
|
return typeof fn === 'function';
|
|
31
28
|
};
|
|
32
29
|
|
|
33
|
-
|
|
30
|
+
const isAsyncFunction = module.exports.isAsyncFunction = function (fn) {
|
|
34
31
|
if (!fn) return false;
|
|
35
32
|
return fn[Symbol.toStringTag] === 'AsyncFunction';
|
|
36
|
-
}
|
|
33
|
+
};
|
|
37
34
|
|
|
38
|
-
|
|
35
|
+
module.exports.fileExists = function (filePath) {
|
|
39
36
|
return fs.existsSync(filePath);
|
|
40
37
|
};
|
|
41
38
|
|
|
42
|
-
|
|
39
|
+
module.exports.isFile = function (filePath) {
|
|
43
40
|
let filestat;
|
|
44
41
|
try {
|
|
45
42
|
filestat = fs.statSync(filePath);
|
|
@@ -50,16 +47,16 @@ export const isFile = function (filePath) {
|
|
|
50
47
|
return filestat.isFile();
|
|
51
48
|
};
|
|
52
49
|
|
|
53
|
-
|
|
50
|
+
module.exports.getParamNames = function (fn) {
|
|
54
51
|
if (fn.isSinonProxy) return [];
|
|
55
52
|
return getFunctionArguments(fn);
|
|
56
53
|
};
|
|
57
54
|
|
|
58
|
-
|
|
55
|
+
module.exports.installedLocally = function () {
|
|
59
56
|
return path.resolve(`${__dirname}/../`).indexOf(process.cwd()) === 0;
|
|
60
57
|
};
|
|
61
58
|
|
|
62
|
-
|
|
59
|
+
module.exports.methodsOfObject = function (obj, className) {
|
|
63
60
|
const methods = [];
|
|
64
61
|
|
|
65
62
|
const standard = [
|
|
@@ -95,7 +92,7 @@ export const methodsOfObject = function (obj, className) {
|
|
|
95
92
|
return methods;
|
|
96
93
|
};
|
|
97
94
|
|
|
98
|
-
|
|
95
|
+
module.exports.template = function (template, data) {
|
|
99
96
|
return template.replace(/{{([^{}]*)}}/g, (a, b) => {
|
|
100
97
|
const r = data[b];
|
|
101
98
|
if (r === undefined) return '';
|
|
@@ -108,7 +105,7 @@ export const template = function (template, data) {
|
|
|
108
105
|
* @param {string} str
|
|
109
106
|
* @returns {string}
|
|
110
107
|
*/
|
|
111
|
-
|
|
108
|
+
module.exports.ucfirst = function (str) {
|
|
112
109
|
return str.charAt(0).toUpperCase() + str.substr(1);
|
|
113
110
|
};
|
|
114
111
|
|
|
@@ -117,11 +114,11 @@ export const ucfirst = function (str) {
|
|
|
117
114
|
* @param {string} str
|
|
118
115
|
* @returns {string}
|
|
119
116
|
*/
|
|
120
|
-
|
|
117
|
+
module.exports.lcfirst = function (str) {
|
|
121
118
|
return str.charAt(0).toLowerCase() + str.substr(1);
|
|
122
119
|
};
|
|
123
120
|
|
|
124
|
-
|
|
121
|
+
module.exports.chunkArray = function (arr, chunk) {
|
|
125
122
|
let i;
|
|
126
123
|
let j;
|
|
127
124
|
const tmp = [];
|
|
@@ -131,7 +128,7 @@ export const chunkArray = function (arr, chunk) {
|
|
|
131
128
|
return tmp;
|
|
132
129
|
};
|
|
133
130
|
|
|
134
|
-
|
|
131
|
+
module.exports.clearString = function (str) {
|
|
135
132
|
if (!str) return '';
|
|
136
133
|
/* Replace forbidden symbols in string
|
|
137
134
|
*/
|
|
@@ -152,13 +149,13 @@ export const clearString = function (str) {
|
|
|
152
149
|
.replace(/'/g, '');
|
|
153
150
|
};
|
|
154
151
|
|
|
155
|
-
|
|
152
|
+
module.exports.decodeUrl = function (url) {
|
|
156
153
|
/* Replace forbidden symbols in string
|
|
157
154
|
*/
|
|
158
155
|
return decodeURIComponent(decodeURIComponent(decodeURIComponent(url)));
|
|
159
156
|
};
|
|
160
157
|
|
|
161
|
-
|
|
158
|
+
module.exports.xpathLocator = {
|
|
162
159
|
/**
|
|
163
160
|
* @param {string} string
|
|
164
161
|
* @returns {string}
|
|
@@ -179,7 +176,25 @@ export const xpathLocator = {
|
|
|
179
176
|
combine: locators => locators.join(' | '),
|
|
180
177
|
};
|
|
181
178
|
|
|
182
|
-
|
|
179
|
+
module.exports.test = {
|
|
180
|
+
|
|
181
|
+
grepLines(array, startString, endString) {
|
|
182
|
+
let startIndex = 0;
|
|
183
|
+
let endIndex;
|
|
184
|
+
array.every((elem, index) => {
|
|
185
|
+
if (elem === startString) {
|
|
186
|
+
startIndex = index;
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
if (elem === endString) {
|
|
190
|
+
endIndex = index;
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
return true;
|
|
194
|
+
});
|
|
195
|
+
return array.slice(startIndex + 1, endIndex);
|
|
196
|
+
},
|
|
197
|
+
|
|
183
198
|
submittedData(dataFile) {
|
|
184
199
|
return function (key) {
|
|
185
200
|
if (!fs.existsSync(dataFile)) {
|
|
@@ -199,23 +214,6 @@ export default {
|
|
|
199
214
|
|
|
200
215
|
};
|
|
201
216
|
|
|
202
|
-
export function grepLines(array, startString, endString) {
|
|
203
|
-
let startIndex = 0;
|
|
204
|
-
let endIndex;
|
|
205
|
-
array.every((elem, index) => {
|
|
206
|
-
if (elem === startString) {
|
|
207
|
-
startIndex = index;
|
|
208
|
-
return true;
|
|
209
|
-
}
|
|
210
|
-
if (elem === endString) {
|
|
211
|
-
endIndex = index;
|
|
212
|
-
return false;
|
|
213
|
-
}
|
|
214
|
-
return true;
|
|
215
|
-
});
|
|
216
|
-
return array.slice(startIndex + 1, endIndex);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
217
|
function toCamelCase(name) {
|
|
220
218
|
if (typeof name !== 'string') {
|
|
221
219
|
return name;
|
|
@@ -224,7 +222,7 @@ function toCamelCase(name) {
|
|
|
224
222
|
return letter.toUpperCase();
|
|
225
223
|
});
|
|
226
224
|
}
|
|
227
|
-
|
|
225
|
+
module.exports.toCamelCase = toCamelCase;
|
|
228
226
|
|
|
229
227
|
function convertFontWeightToNumber(name) {
|
|
230
228
|
const fontWeightPatterns = [
|
|
@@ -255,7 +253,7 @@ function isFontWeightProperty(prop) {
|
|
|
255
253
|
return prop === 'fontWeight';
|
|
256
254
|
}
|
|
257
255
|
|
|
258
|
-
|
|
256
|
+
module.exports.convertCssPropertiesToCamelCase = function (props) {
|
|
259
257
|
const output = {};
|
|
260
258
|
Object.keys(props).forEach((key) => {
|
|
261
259
|
const keyCamel = toCamelCase(key);
|
|
@@ -271,7 +269,7 @@ export const convertCssPropertiesToCamelCase = function (props) {
|
|
|
271
269
|
return output;
|
|
272
270
|
};
|
|
273
271
|
|
|
274
|
-
|
|
272
|
+
module.exports.deleteDir = function (dir_path) {
|
|
275
273
|
if (fs.existsSync(dir_path)) {
|
|
276
274
|
fs.readdirSync(dir_path).forEach(function (entry) {
|
|
277
275
|
const entry_path = path.join(dir_path, entry);
|
|
@@ -289,7 +287,7 @@ export const deleteDir = function (dir_path) {
|
|
|
289
287
|
* Returns absolute filename to save screenshot.
|
|
290
288
|
* @param fileName {string} - filename.
|
|
291
289
|
*/
|
|
292
|
-
|
|
290
|
+
module.exports.screenshotOutputFolder = function (fileName) {
|
|
293
291
|
const fileSep = path.sep;
|
|
294
292
|
|
|
295
293
|
if (!fileName.includes(fileSep) || fileName.includes('record_')) {
|
|
@@ -298,7 +296,8 @@ export const screenshotOutputFolder = function (fileName) {
|
|
|
298
296
|
return path.resolve(global.codecept_dir, fileName);
|
|
299
297
|
};
|
|
300
298
|
|
|
301
|
-
|
|
299
|
+
module.exports.beautify = function (code) {
|
|
300
|
+
const format = require('js-beautify').js;
|
|
302
301
|
return format(code, { indent_size: 2, space_in_empty_paren: true });
|
|
303
302
|
};
|
|
304
303
|
|
|
@@ -318,7 +317,7 @@ function joinUrl(baseUrl, url) {
|
|
|
318
317
|
return shouldAppendBaseUrl(url) ? `${baseUrl}/${trimUrl(url)}` : url;
|
|
319
318
|
}
|
|
320
319
|
|
|
321
|
-
|
|
320
|
+
module.exports.appendBaseUrl = function (baseUrl = '', oneOrMoreUrls) {
|
|
322
321
|
if (typeof baseUrl !== 'string') {
|
|
323
322
|
throw new Error(`Invalid value for baseUrl: ${baseUrl}`);
|
|
324
323
|
}
|
|
@@ -344,7 +343,7 @@ export const appendBaseUrl = function (baseUrl = '', oneOrMoreUrls) {
|
|
|
344
343
|
* @param {string} key key to search
|
|
345
344
|
* @param {*} value value to set for key
|
|
346
345
|
*/
|
|
347
|
-
|
|
346
|
+
module.exports.replaceValueDeep = function replaceValueDeep(obj, key, value) {
|
|
348
347
|
if (!obj) return;
|
|
349
348
|
|
|
350
349
|
if (obj instanceof Array) {
|
|
@@ -366,7 +365,7 @@ export const replaceValueDeep = function replaceValueDeep(obj, key, value) {
|
|
|
366
365
|
return obj;
|
|
367
366
|
};
|
|
368
367
|
|
|
369
|
-
|
|
368
|
+
module.exports.ansiRegExp = function ({ onlyFirst = false } = {}) {
|
|
370
369
|
const pattern = [
|
|
371
370
|
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
|
|
372
371
|
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))',
|
|
@@ -375,7 +374,7 @@ export const ansiRegExp = function ({ onlyFirst = false } = {}) {
|
|
|
375
374
|
return new RegExp(pattern, onlyFirst ? undefined : 'g');
|
|
376
375
|
};
|
|
377
376
|
|
|
378
|
-
|
|
377
|
+
module.exports.tryOrDefault = function (fn, defaultValue) {
|
|
379
378
|
try {
|
|
380
379
|
return fn();
|
|
381
380
|
} catch (_) {
|
|
@@ -402,7 +401,7 @@ function normalizeKeyReplacer(match, prefix, key, suffix, offset, string) {
|
|
|
402
401
|
* @param {string} key
|
|
403
402
|
* @returns {string}
|
|
404
403
|
*/
|
|
405
|
-
|
|
404
|
+
module.exports.getNormalizedKeyAttributeValue = function (key) {
|
|
406
405
|
// Use operation modifier key based on operating system
|
|
407
406
|
key = key.replace(/(Ctrl|Control|Cmd|Command)[ _]?Or[ _]?(Ctrl|Control|Cmd|Command)/i, os.platform() === 'darwin' ? 'Meta' : 'Control');
|
|
408
407
|
// Selection of keys (https://www.w3.org/TR/uievents-key/#named-key-attribute-values)
|
|
@@ -426,16 +425,15 @@ const modifierKeys = [
|
|
|
426
425
|
'Shift', 'ShiftLeft', 'ShiftRight',
|
|
427
426
|
];
|
|
428
427
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
export const isModifierKey = function (key) {
|
|
428
|
+
module.exports.modifierKeys = modifierKeys;
|
|
429
|
+
module.exports.isModifierKey = function (key) {
|
|
432
430
|
return modifierKeys.includes(key);
|
|
433
431
|
};
|
|
434
432
|
|
|
435
|
-
|
|
433
|
+
module.exports.requireWithFallback = function (...packages) {
|
|
436
434
|
const exists = function (pkg) {
|
|
437
435
|
try {
|
|
438
|
-
|
|
436
|
+
require.resolve(pkg);
|
|
439
437
|
} catch (e) {
|
|
440
438
|
return false;
|
|
441
439
|
}
|
|
@@ -445,24 +443,24 @@ export const requireWithFallback = function (...packages) {
|
|
|
445
443
|
|
|
446
444
|
for (const pkg of packages) {
|
|
447
445
|
if (exists(pkg)) {
|
|
448
|
-
return
|
|
446
|
+
return require(pkg);
|
|
449
447
|
}
|
|
450
448
|
}
|
|
451
449
|
|
|
452
450
|
throw new Error(`Cannot find modules ${packages.join(',')}`);
|
|
453
451
|
};
|
|
454
452
|
|
|
455
|
-
|
|
453
|
+
module.exports.isNotSet = function (obj) {
|
|
456
454
|
if (obj === null) return true;
|
|
457
455
|
if (obj === undefined) return true;
|
|
458
456
|
return false;
|
|
459
457
|
};
|
|
460
458
|
|
|
461
|
-
|
|
462
|
-
|
|
459
|
+
module.exports.emptyFolder = async (directoryPath) => {
|
|
460
|
+
require('child_process').execSync(`rm -rf ${directoryPath}/*`);
|
|
463
461
|
};
|
|
464
462
|
|
|
465
|
-
|
|
463
|
+
module.exports.printObjectProperties = (obj) => {
|
|
466
464
|
if (typeof obj !== 'object' || obj === null) {
|
|
467
465
|
return obj;
|
|
468
466
|
}
|
|
@@ -475,6 +473,6 @@ export const printObjectProperties = (obj) => {
|
|
|
475
473
|
return `{${result}}`;
|
|
476
474
|
};
|
|
477
475
|
|
|
478
|
-
|
|
476
|
+
module.exports.normalizeSpacesInString = (string) => {
|
|
479
477
|
return string.replace(/\s+/g, ' ');
|
|
480
478
|
};
|
package/lib/within.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
const output = require('./output');
|
|
2
|
+
const store = require('./store');
|
|
3
|
+
const recorder = require('./recorder');
|
|
4
|
+
const container = require('./container');
|
|
5
|
+
const event = require('./event');
|
|
6
|
+
const Step = require('./step');
|
|
7
|
+
const { isAsyncFunction } = require('./utils');
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @param {CodeceptJS.LocatorOrString} context
|
|
@@ -29,7 +29,7 @@ function within(context, fn) {
|
|
|
29
29
|
const finalize = () => {
|
|
30
30
|
event.dispatcher.removeListener(event.step.before, defineMetaStep);
|
|
31
31
|
recorder.add('Finalize session within session', () => {
|
|
32
|
-
output.
|
|
32
|
+
output.stepShift = 1;
|
|
33
33
|
recorder.session.restore('within');
|
|
34
34
|
});
|
|
35
35
|
};
|
|
@@ -58,7 +58,7 @@ function within(context, fn) {
|
|
|
58
58
|
} finally {
|
|
59
59
|
finishHelpers();
|
|
60
60
|
recorder.catch((err) => {
|
|
61
|
-
output.
|
|
61
|
+
output.stepShift = 1;
|
|
62
62
|
throw err;
|
|
63
63
|
});
|
|
64
64
|
}
|
|
@@ -67,4 +67,4 @@ function within(context, fn) {
|
|
|
67
67
|
}, false, false);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
module.exports = within;
|
package/lib/workerStorage.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
const { isMainThread, parentPort } = require('worker_threads');
|
|
2
2
|
|
|
3
3
|
const workerObjects = {};
|
|
4
4
|
const shareEvent = 'share';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const invokeWorkerListeners = (workerObj) => {
|
|
7
7
|
const { threadId } = workerObj;
|
|
8
8
|
workerObj.on('message', (messageData) => {
|
|
9
9
|
if (messageData.event === shareEvent) {
|
|
@@ -15,30 +15,32 @@ export const invokeWorkerListeners = (workerObj) => {
|
|
|
15
15
|
});
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
18
|
+
class WorkerStorage {
|
|
19
|
+
/**
|
|
20
|
+
* Add worker object
|
|
21
|
+
*
|
|
22
|
+
* @api
|
|
23
|
+
* @param {Worker} workerObj
|
|
24
|
+
*/
|
|
25
|
+
static addWorker(workerObj) {
|
|
26
|
+
workerObjects[workerObj.threadId] = workerObj;
|
|
27
|
+
invokeWorkerListeners(workerObj);
|
|
28
|
+
}
|
|
29
29
|
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Share data across workers
|
|
32
|
+
*
|
|
33
|
+
* @param {*} data
|
|
34
|
+
*/
|
|
35
|
+
static share(data) {
|
|
36
|
+
if (isMainThread) {
|
|
37
|
+
for (const workerObj of Object.values(workerObjects)) {
|
|
38
|
+
workerObj.postMessage({ data });
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
parentPort.postMessage({ data, event: shareEvent });
|
|
39
42
|
}
|
|
40
|
-
} else {
|
|
41
|
-
// @ts-ignore
|
|
42
|
-
parentPort.postMessage({ data, event: shareEvent });
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
+
|
|
46
|
+
module.exports = WorkerStorage;
|
package/lib/workers.js
CHANGED
|
@@ -1,27 +1,24 @@
|
|
|
1
1
|
/* eslint-disable max-classes-per-file */
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
import collection from './command/run-multiple/collection.js';
|
|
23
|
-
|
|
24
|
-
const __dirname = path.resolve('.', 'lib');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const mkdirp = require('mkdirp');
|
|
4
|
+
const { Worker } = require('worker_threads');
|
|
5
|
+
const { Suite, Test, reporters: { Base } } = require('mocha');
|
|
6
|
+
const { EventEmitter } = require('events');
|
|
7
|
+
const ms = require('ms');
|
|
8
|
+
const Codecept = require('./codecept');
|
|
9
|
+
const MochaFactory = require('./mochaFactory');
|
|
10
|
+
const Container = require('./container');
|
|
11
|
+
const { getTestRoot } = require('./command/utils');
|
|
12
|
+
const { isFunction, fileExists } = require('./utils');
|
|
13
|
+
const { replaceValueDeep, deepClone } = require('./utils');
|
|
14
|
+
const mainConfig = require('./config');
|
|
15
|
+
const output = require('./output');
|
|
16
|
+
const event = require('./event');
|
|
17
|
+
const recorder = require('./recorder');
|
|
18
|
+
const runHook = require('./hooks');
|
|
19
|
+
const WorkerStorage = require('./workerStorage');
|
|
20
|
+
const collection = require('./command/run-multiple/collection');
|
|
21
|
+
|
|
25
22
|
const pathToWorker = path.join(__dirname, 'command', 'workers', 'runTests.js');
|
|
26
23
|
|
|
27
24
|
const initializeCodecept = (configPath, options = {}) => {
|
|
@@ -43,14 +40,14 @@ const createOutputDir = (configPath) => {
|
|
|
43
40
|
}
|
|
44
41
|
};
|
|
45
42
|
|
|
46
|
-
|
|
43
|
+
const populateGroups = (numberOfWorkers) => {
|
|
47
44
|
const groups = [];
|
|
48
45
|
for (let i = 0; i < numberOfWorkers; i++) {
|
|
49
46
|
groups[i] = [];
|
|
50
47
|
}
|
|
51
48
|
|
|
52
49
|
return groups;
|
|
53
|
-
}
|
|
50
|
+
};
|
|
54
51
|
|
|
55
52
|
const createWorker = (workerObject) => {
|
|
56
53
|
const worker = new Worker(pathToWorker, {
|
|
@@ -61,9 +58,8 @@ const createWorker = (workerObject) => {
|
|
|
61
58
|
workerIndex: workerObject.workerIndex + 1,
|
|
62
59
|
},
|
|
63
60
|
});
|
|
64
|
-
worker.on('error', err => output.
|
|
61
|
+
worker.on('error', err => output.error(`Worker Error: ${err.stack}`));
|
|
65
62
|
|
|
66
|
-
// @ts-ignore
|
|
67
63
|
WorkerStorage.addWorker(worker);
|
|
68
64
|
return worker;
|
|
69
65
|
};
|
|
@@ -228,7 +224,7 @@ class WorkerObject {
|
|
|
228
224
|
}
|
|
229
225
|
}
|
|
230
226
|
|
|
231
|
-
|
|
227
|
+
class Workers extends EventEmitter {
|
|
232
228
|
/**
|
|
233
229
|
* @param {Number} numberOfWorkers
|
|
234
230
|
* @param {Object} config
|
|
@@ -392,7 +388,7 @@ export class Workers extends EventEmitter {
|
|
|
392
388
|
|
|
393
389
|
_listenWorkerEvents(worker) {
|
|
394
390
|
worker.on('message', (message) => {
|
|
395
|
-
output.
|
|
391
|
+
output.process(message.workerIndex);
|
|
396
392
|
|
|
397
393
|
// deal with events that are not test cycle related
|
|
398
394
|
if (!message.event) {
|
|
@@ -467,7 +463,7 @@ export class Workers extends EventEmitter {
|
|
|
467
463
|
process.exitCode = 0;
|
|
468
464
|
}
|
|
469
465
|
// removed this.finishedTests because in all /lib only first argument (!this.isFailed()) is used)
|
|
470
|
-
this.emit(event.all.result,
|
|
466
|
+
this.emit(event.all.result, !this.isFailed());
|
|
471
467
|
this.emit('end'); // internal event
|
|
472
468
|
}
|
|
473
469
|
|
|
@@ -484,7 +480,7 @@ export class Workers extends EventEmitter {
|
|
|
484
480
|
this.stats.duration = this.stats.end - this.stats.start;
|
|
485
481
|
|
|
486
482
|
// Reset process for logs in main thread
|
|
487
|
-
output.
|
|
483
|
+
output.process(null);
|
|
488
484
|
output.print();
|
|
489
485
|
|
|
490
486
|
this.failuresLog = this.failuresLog
|
|
@@ -499,7 +495,8 @@ export class Workers extends EventEmitter {
|
|
|
499
495
|
}
|
|
500
496
|
|
|
501
497
|
output.result(this.stats.passes, this.stats.failures, this.stats.pending, ms(this.stats.duration), this.stats.failedHooks);
|
|
502
|
-
output.result(cts.passes, this.stats.failures, this.stats.pending, ms(this.stats.duration));
|
|
503
498
|
process.env.RUNS_WITH_WORKERS = 'false';
|
|
504
499
|
}
|
|
505
500
|
}
|
|
501
|
+
|
|
502
|
+
module.exports = Workers;
|