codeceptjs 3.7.6-beta.4 → 4.0.0-beta.10.esm-aria
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 +1 -3
- package/bin/codecept.js +51 -53
- package/bin/test-server.js +14 -3
- package/docs/webapi/click.mustache +5 -1
- package/lib/actor.js +15 -11
- package/lib/ai.js +72 -107
- package/lib/assert/empty.js +9 -8
- package/lib/assert/equal.js +15 -17
- package/lib/assert/error.js +2 -2
- package/lib/assert/include.js +9 -11
- package/lib/assert/throws.js +1 -1
- package/lib/assert/truth.js +8 -5
- package/lib/assert.js +18 -18
- package/lib/codecept.js +102 -75
- package/lib/colorUtils.js +48 -50
- package/lib/command/check.js +32 -27
- package/lib/command/configMigrate.js +11 -10
- package/lib/command/definitions.js +16 -10
- package/lib/command/dryRun.js +16 -16
- package/lib/command/generate.js +62 -27
- package/lib/command/gherkin/init.js +36 -38
- package/lib/command/gherkin/snippets.js +14 -14
- package/lib/command/gherkin/steps.js +21 -18
- package/lib/command/info.js +8 -8
- package/lib/command/init.js +36 -29
- package/lib/command/interactive.js +11 -10
- package/lib/command/list.js +10 -9
- package/lib/command/run-multiple/chunk.js +5 -5
- package/lib/command/run-multiple/collection.js +5 -5
- package/lib/command/run-multiple/run.js +3 -3
- package/lib/command/run-multiple.js +16 -13
- package/lib/command/run-rerun.js +6 -7
- package/lib/command/run-workers.js +24 -9
- package/lib/command/run.js +23 -8
- package/lib/command/utils.js +20 -18
- package/lib/command/workers/runTests.js +197 -114
- package/lib/config.js +124 -51
- package/lib/container.js +438 -87
- package/lib/data/context.js +6 -5
- package/lib/data/dataScenarioConfig.js +1 -1
- package/lib/data/dataTableArgument.js +1 -1
- package/lib/data/table.js +1 -1
- package/lib/effects.js +94 -10
- package/lib/element/WebElement.js +2 -2
- package/lib/els.js +11 -9
- package/lib/event.js +11 -10
- package/lib/globals.js +141 -0
- package/lib/heal.js +12 -12
- package/lib/helper/AI.js +11 -11
- package/lib/helper/ApiDataFactory.js +50 -19
- package/lib/helper/Appium.js +19 -27
- package/lib/helper/FileSystem.js +32 -12
- package/lib/helper/GraphQL.js +3 -3
- package/lib/helper/GraphQLDataFactory.js +4 -4
- package/lib/helper/JSONResponse.js +25 -29
- package/lib/helper/Mochawesome.js +7 -4
- package/lib/helper/Playwright.js +902 -164
- package/lib/helper/Puppeteer.js +383 -76
- package/lib/helper/REST.js +29 -12
- package/lib/helper/WebDriver.js +268 -61
- package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
- package/lib/helper/errors/ConnectionRefused.js +6 -6
- package/lib/helper/errors/ElementAssertion.js +11 -16
- package/lib/helper/errors/ElementNotFound.js +5 -9
- package/lib/helper/errors/RemoteBrowserConnectionRefused.js +5 -5
- package/lib/helper/extras/Console.js +11 -11
- package/lib/helper/extras/PlaywrightLocator.js +110 -0
- package/lib/helper/extras/PlaywrightPropEngine.js +18 -18
- package/lib/helper/extras/PlaywrightReactVueLocator.js +18 -9
- package/lib/helper/extras/PlaywrightRestartOpts.js +34 -23
- package/lib/helper/extras/Popup.js +1 -1
- package/lib/helper/extras/React.js +29 -30
- package/lib/helper/network/actions.js +29 -44
- package/lib/helper/network/utils.js +76 -83
- package/lib/helper/scripts/blurElement.js +6 -6
- package/lib/helper/scripts/focusElement.js +6 -6
- package/lib/helper/scripts/highlightElement.js +9 -9
- package/lib/helper/scripts/isElementClickable.js +34 -34
- package/lib/helper.js +2 -1
- package/lib/history.js +23 -20
- package/lib/hooks.js +10 -10
- package/lib/html.js +90 -100
- package/lib/index.js +48 -21
- package/lib/listener/config.js +19 -12
- package/lib/listener/emptyRun.js +6 -7
- package/lib/listener/enhancedGlobalRetry.js +6 -6
- package/lib/listener/exit.js +4 -3
- package/lib/listener/globalRetry.js +5 -5
- package/lib/listener/globalTimeout.js +30 -14
- package/lib/listener/helpers.js +39 -14
- package/lib/listener/mocha.js +3 -4
- package/lib/listener/result.js +4 -5
- package/lib/listener/retryEnhancer.js +3 -3
- package/lib/listener/steps.js +8 -7
- package/lib/listener/store.js +3 -3
- package/lib/locator.js +213 -192
- package/lib/mocha/asyncWrapper.js +105 -62
- package/lib/mocha/bdd.js +99 -13
- package/lib/mocha/cli.js +59 -26
- package/lib/mocha/factory.js +78 -19
- package/lib/mocha/featureConfig.js +1 -1
- package/lib/mocha/gherkin.js +56 -24
- package/lib/mocha/hooks.js +12 -3
- package/lib/mocha/index.js +13 -4
- package/lib/mocha/inject.js +22 -5
- package/lib/mocha/scenarioConfig.js +2 -2
- package/lib/mocha/suite.js +9 -2
- package/lib/mocha/test.js +10 -7
- package/lib/mocha/ui.js +28 -18
- package/lib/output.js +10 -8
- package/lib/parser.js +44 -44
- package/lib/pause.js +15 -16
- package/lib/plugin/analyze.js +19 -12
- package/lib/plugin/auth.js +20 -21
- package/lib/plugin/autoDelay.js +12 -8
- package/lib/plugin/coverage.js +28 -11
- package/lib/plugin/customLocator.js +3 -3
- package/lib/plugin/customReporter.js +3 -2
- package/lib/plugin/enhancedRetryFailedStep.js +6 -6
- package/lib/plugin/heal.js +14 -9
- package/lib/plugin/htmlReporter.js +724 -99
- package/lib/plugin/pageInfo.js +10 -10
- package/lib/plugin/pauseOnFail.js +4 -3
- package/lib/plugin/retryFailedStep.js +48 -5
- package/lib/plugin/screenshotOnFail.js +75 -37
- package/lib/plugin/stepByStepReport.js +14 -14
- package/lib/plugin/stepTimeout.js +4 -3
- package/lib/plugin/subtitles.js +6 -5
- package/lib/recorder.js +33 -14
- package/lib/rerun.js +69 -26
- package/lib/result.js +4 -4
- package/lib/retryCoordinator.js +2 -2
- package/lib/secret.js +18 -17
- package/lib/session.js +95 -89
- package/lib/step/base.js +7 -7
- package/lib/step/comment.js +2 -2
- package/lib/step/config.js +1 -1
- package/lib/step/func.js +3 -3
- package/lib/step/helper.js +3 -3
- package/lib/step/meta.js +5 -5
- package/lib/step/record.js +11 -11
- package/lib/step/retry.js +3 -3
- package/lib/step/section.js +3 -3
- package/lib/step.js +7 -10
- package/lib/steps.js +9 -5
- package/lib/store.js +1 -1
- package/lib/template/heal.js +1 -1
- package/lib/template/prompts/generatePageObject.js +31 -0
- package/lib/template/prompts/healStep.js +13 -0
- package/lib/template/prompts/writeStep.js +9 -0
- package/lib/test-server.js +17 -6
- package/lib/timeout.js +1 -7
- package/lib/transform.js +8 -8
- package/lib/translation.js +32 -18
- package/lib/utils/mask_data.js +4 -10
- package/lib/utils.js +66 -64
- package/lib/workerStorage.js +17 -17
- package/lib/workers.js +214 -84
- package/package.json +41 -37
- package/translations/de-DE.js +2 -2
- package/translations/fr-FR.js +2 -2
- package/translations/index.js +23 -10
- package/translations/it-IT.js +2 -2
- package/translations/ja-JP.js +2 -2
- package/translations/nl-NL.js +2 -2
- package/translations/pl-PL.js +2 -2
- package/translations/pt-BR.js +2 -2
- package/translations/ru-RU.js +2 -2
- package/translations/utils.js +4 -3
- package/translations/zh-CN.js +2 -2
- package/translations/zh-TW.js +2 -2
- package/typings/index.d.ts +5 -3
- package/typings/promiseBasedTypes.d.ts +4 -0
- package/typings/types.d.ts +4 -0
- package/lib/helper/Nightmare.js +0 -1486
- package/lib/helper/Protractor.js +0 -1840
- package/lib/helper/TestCafe.js +0 -1391
- package/lib/helper/clientscripts/nightmare.js +0 -213
- package/lib/helper/testcafe/testControllerHolder.js +0 -42
- package/lib/helper/testcafe/testcafe-utils.js +0 -61
- package/lib/plugin/allure.js +0 -15
- package/lib/plugin/autoLogin.js +0 -5
- package/lib/plugin/commentStep.js +0 -141
- package/lib/plugin/eachElement.js +0 -127
- package/lib/plugin/fakerTransform.js +0 -49
- package/lib/plugin/retryTo.js +0 -16
- package/lib/plugin/selenoid.js +0 -364
- package/lib/plugin/standardActingHelpers.js +0 -6
- package/lib/plugin/tryTo.js +0 -16
- package/lib/plugin/wdio.js +0 -247
- package/lib/within.js +0 -90
package/lib/command/info.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import envinfo from 'envinfo'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import { getConfig, getTestRoot } from './utils.js'
|
|
4
|
+
import Codecept from '../codecept.js'
|
|
5
|
+
import output from '../output.js'
|
|
6
|
+
import { execSync } from 'child_process'
|
|
7
7
|
|
|
8
8
|
async function getPlaywrightBrowsers() {
|
|
9
9
|
try {
|
|
@@ -40,9 +40,9 @@ async function getOsBrowsers() {
|
|
|
40
40
|
].join(', ')
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
export default async function (path) {
|
|
44
44
|
const testsPath = getTestRoot(path)
|
|
45
|
-
const config = getConfig(testsPath)
|
|
45
|
+
const config = await getConfig(testsPath)
|
|
46
46
|
const codecept = new Codecept(config, {})
|
|
47
47
|
codecept.init(testsPath)
|
|
48
48
|
|
|
@@ -73,7 +73,7 @@ module.exports = async function (path) {
|
|
|
73
73
|
output.print('***************************************')
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
export const getMachineInfo = async () => {
|
|
77
77
|
const info = {
|
|
78
78
|
nodeInfo: await envinfo.helpers.getNodeInfo(),
|
|
79
79
|
osInfo: await envinfo.helpers.getOSInfo(),
|
package/lib/command/init.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import colors from 'chalk'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import inquirer from 'inquirer'
|
|
4
|
+
import { mkdirp } from 'mkdirp'
|
|
5
|
+
import path from 'path'
|
|
6
|
+
import { inspect } from 'util'
|
|
7
|
+
import spawn from 'cross-spawn'
|
|
8
|
+
|
|
9
|
+
import output from '../output.js'
|
|
10
|
+
const { print, success, error } = output
|
|
11
|
+
import { fileExists, beautify, installedLocally } from '../utils.js'
|
|
12
|
+
import { getTestRoot } from './utils.js'
|
|
13
|
+
import generateDefinitions from './definitions.js'
|
|
14
|
+
import { test as generateTest } from './generate.js'
|
|
15
|
+
const isLocal = installedLocally()
|
|
15
16
|
|
|
16
17
|
const defaultConfig = {
|
|
17
18
|
tests: './*_test.js',
|
|
@@ -25,17 +26,20 @@ const defaultConfig = {
|
|
|
25
26
|
},
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
const helpers = ['Playwright', 'WebDriver', 'Puppeteer', 'REST', 'GraphQL', 'Appium'
|
|
29
|
-
const translations = Object.keys(require('../../translations'))
|
|
30
|
-
|
|
29
|
+
const helpers = ['Playwright', 'WebDriver', 'Puppeteer', 'REST', 'GraphQL', 'Appium']
|
|
31
30
|
const noTranslation = 'English (no localization)'
|
|
32
|
-
|
|
31
|
+
|
|
32
|
+
async function getTranslations() {
|
|
33
|
+
const translationsModule = await import('../../translations/index.js')
|
|
34
|
+
const translations = Object.keys(translationsModule.default || translationsModule)
|
|
35
|
+
translations.unshift(noTranslation)
|
|
36
|
+
return translations
|
|
37
|
+
}
|
|
33
38
|
|
|
34
39
|
const packages = []
|
|
35
40
|
let isTypeScript = false
|
|
36
41
|
let extension = 'js'
|
|
37
42
|
|
|
38
|
-
const requireCodeceptConfigure = "const { setHeadlessWhen, setCommonPlugins } = require('@codeceptjs/configure');"
|
|
39
43
|
const importCodeceptConfigure = "import { setHeadlessWhen, setCommonPlugins } from '@codeceptjs/configure';"
|
|
40
44
|
|
|
41
45
|
const configHeader = `
|
|
@@ -50,7 +54,7 @@ setCommonPlugins();
|
|
|
50
54
|
|
|
51
55
|
const defaultActor = `// in this file you can append custom step methods to 'I' object
|
|
52
56
|
|
|
53
|
-
|
|
57
|
+
export default function() {
|
|
54
58
|
return actor({
|
|
55
59
|
|
|
56
60
|
// Define custom steps here, use 'this' to access default methods of I.
|
|
@@ -72,8 +76,9 @@ export = function() {
|
|
|
72
76
|
}
|
|
73
77
|
`
|
|
74
78
|
|
|
75
|
-
|
|
79
|
+
export default async function (initPath) {
|
|
76
80
|
const testsPath = getTestRoot(initPath)
|
|
81
|
+
const translations = await getTranslations()
|
|
77
82
|
|
|
78
83
|
print()
|
|
79
84
|
print(` Welcome to ${colors.magenta.bold('CodeceptJS')} initialization tool`)
|
|
@@ -151,7 +156,7 @@ module.exports = function (initPath) {
|
|
|
151
156
|
choices: translations,
|
|
152
157
|
},
|
|
153
158
|
])
|
|
154
|
-
.then(result => {
|
|
159
|
+
.then(async result => {
|
|
155
160
|
if (result.typescript === true) {
|
|
156
161
|
isTypeScript = true
|
|
157
162
|
extension = isTypeScript === true ? 'ts' : 'js'
|
|
@@ -187,7 +192,8 @@ module.exports = function (initPath) {
|
|
|
187
192
|
let helperConfigs = []
|
|
188
193
|
|
|
189
194
|
try {
|
|
190
|
-
const
|
|
195
|
+
const HelperModule = await import(`../helper/${helperName}.js`)
|
|
196
|
+
const Helper = HelperModule.default || HelperModule
|
|
191
197
|
if (Helper._checkRequirements) {
|
|
192
198
|
packages.concat(Helper._checkRequirements())
|
|
193
199
|
}
|
|
@@ -212,9 +218,9 @@ module.exports = function (initPath) {
|
|
|
212
218
|
fs.writeFileSync(path.join(testsPath, stepFile), extension === 'ts' ? defaultActorTs : defaultActor)
|
|
213
219
|
|
|
214
220
|
if (isTypeScript) {
|
|
215
|
-
config.include = _actorTranslation('./steps_file', config.translation)
|
|
221
|
+
config.include = await _actorTranslation('./steps_file', config.translation, translations)
|
|
216
222
|
} else {
|
|
217
|
-
config.include = _actorTranslation(stepFile, config.translation)
|
|
223
|
+
config.include = await _actorTranslation(stepFile, config.translation, translations)
|
|
218
224
|
}
|
|
219
225
|
|
|
220
226
|
print(`Steps file created at ${stepFile}`)
|
|
@@ -230,9 +236,9 @@ module.exports = function (initPath) {
|
|
|
230
236
|
fs.writeFileSync(typeScriptconfigFile, configSource, 'utf-8')
|
|
231
237
|
print(`Config created at ${typeScriptconfigFile}`)
|
|
232
238
|
} else {
|
|
233
|
-
configSource = beautify(`/** @type {CodeceptJS.MainConfig} */\
|
|
239
|
+
configSource = beautify(`/** @type {CodeceptJS.MainConfig} */\nexport const config = ${inspect(config, false, 4, false)}`)
|
|
234
240
|
|
|
235
|
-
if (hasConfigure) configSource =
|
|
241
|
+
if (hasConfigure) configSource = importCodeceptConfigure + configHeader + configSource
|
|
236
242
|
|
|
237
243
|
fs.writeFileSync(configFile, configSource, 'utf-8')
|
|
238
244
|
print(`Config created at ${configFile}`)
|
|
@@ -395,7 +401,7 @@ function install(dependencies) {
|
|
|
395
401
|
return true
|
|
396
402
|
}
|
|
397
403
|
|
|
398
|
-
function _actorTranslation(stepFile, translationSelected) {
|
|
404
|
+
async function _actorTranslation(stepFile, translationSelected, translations) {
|
|
399
405
|
let actor
|
|
400
406
|
|
|
401
407
|
for (const translationAvailable of translations) {
|
|
@@ -404,7 +410,8 @@ function _actorTranslation(stepFile, translationSelected) {
|
|
|
404
410
|
}
|
|
405
411
|
|
|
406
412
|
if (translationSelected === translationAvailable) {
|
|
407
|
-
const
|
|
413
|
+
const translationsModule = await import('../../translations/index.js')
|
|
414
|
+
const nameOfActor = (translationsModule.default || translationsModule)[translationAvailable].I
|
|
408
415
|
|
|
409
416
|
actor = {
|
|
410
417
|
[nameOfActor]: stepFile,
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { getConfig, getTestRoot } from './utils.js'
|
|
2
|
+
import recorder from '../recorder.js'
|
|
3
|
+
import Codecept from '../codecept.js'
|
|
4
|
+
import Container from '../container.js'
|
|
5
|
+
import event from '../event.js'
|
|
6
|
+
import pause from '../pause.js'
|
|
7
|
+
import output from '../output.js'
|
|
7
8
|
const webHelpers = Container.STANDARD_ACTING_HELPERS
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
export default async function (path, options) {
|
|
10
11
|
// Backward compatibility for --profile
|
|
11
12
|
process.profile = options.profile
|
|
12
13
|
process.env.profile = options.profile
|
|
13
14
|
const configFile = options.config
|
|
14
15
|
|
|
15
|
-
const config = getConfig(configFile)
|
|
16
|
+
const config = await getConfig(configFile)
|
|
16
17
|
const testsPath = getTestRoot(configFile)
|
|
17
18
|
|
|
18
19
|
const codecept = new Codecept(config, options)
|
|
@@ -20,6 +21,7 @@ module.exports = async function (path, options) {
|
|
|
20
21
|
|
|
21
22
|
try {
|
|
22
23
|
await codecept.bootstrap()
|
|
24
|
+
await Container.started()
|
|
23
25
|
|
|
24
26
|
if (options.verbose) output.level(3)
|
|
25
27
|
|
|
@@ -51,8 +53,7 @@ module.exports = async function (path, options) {
|
|
|
51
53
|
break
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
|
-
|
|
55
|
-
// recorder.catchWithoutStop((err) => console.log(err.stack));
|
|
56
|
+
pause()
|
|
56
57
|
recorder.add(() => event.emit(event.test.after, {}))
|
|
57
58
|
recorder.add(() => event.emit(event.suite.after, {}))
|
|
58
59
|
recorder.add(() => event.emit(event.all.result, {}))
|
package/lib/command/list.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { getConfig, getTestRoot } from './utils.js'
|
|
2
|
+
import Codecept from '../codecept.js'
|
|
3
|
+
import container from '../container.js'
|
|
4
|
+
import { getParamsToString } from '../parser.js'
|
|
5
|
+
import { methodsOfObject } from '../utils.js'
|
|
6
|
+
import output from '../output.js'
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
export default async function (path) {
|
|
9
9
|
const testsPath = getTestRoot(path)
|
|
10
|
-
const config = getConfig(testsPath)
|
|
10
|
+
const config = await getConfig(testsPath)
|
|
11
11
|
const codecept = new Codecept(config, {})
|
|
12
|
-
codecept.init(testsPath)
|
|
12
|
+
await codecept.init(testsPath)
|
|
13
|
+
await container.started()
|
|
13
14
|
|
|
14
15
|
output.print('List of test actions: -- ')
|
|
15
16
|
const helpers = container.helpers()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { globSync } from 'glob'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import fs from 'fs'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Splits a list to (n) parts, defined via the size argument.
|
|
@@ -89,6 +89,6 @@ const createChunks = (config, patterns = []) => {
|
|
|
89
89
|
})
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
createChunks
|
|
92
|
+
export {
|
|
93
|
+
createChunks
|
|
94
94
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { createChunks } from './chunk.js'
|
|
2
|
+
import { createRun } from './run.js'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Bootstraps a collection of runs, it combines user defined selection of runs
|
|
@@ -190,6 +190,6 @@ function guessBrowser(config) {
|
|
|
190
190
|
return [config.helpers[firstHelper].browser];
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
|
|
194
|
-
createRuns
|
|
195
|
-
}
|
|
193
|
+
export {
|
|
194
|
+
createRuns
|
|
195
|
+
}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { fork } from 'child_process'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import crypto from 'crypto'
|
|
4
|
+
import { fileURLToPath } from 'url'
|
|
5
|
+
|
|
6
|
+
import runHook from '../hooks.js'
|
|
7
|
+
import event from '../event.js'
|
|
8
|
+
import { createRuns } from './run-multiple/collection.js'
|
|
9
|
+
import { clearString, replaceValueDeep } from '../utils.js'
|
|
10
|
+
import { getConfig, getTestRoot, fail } from './utils.js'
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
13
|
+
const __dirname = path.dirname(__filename)
|
|
11
14
|
const runner = path.join(__dirname, '/../../bin/codecept')
|
|
12
15
|
let config
|
|
13
16
|
const childOpts = {}
|
|
@@ -24,7 +27,7 @@ let subprocessCount = 0
|
|
|
24
27
|
let totalSubprocessCount = 0
|
|
25
28
|
let processesDone
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
export default async function (selectedRuns, options) {
|
|
28
31
|
// registering options globally to use in config
|
|
29
32
|
if (options.profile) {
|
|
30
33
|
process.env.profile = options.profile
|
|
@@ -49,7 +52,7 @@ module.exports = async function (selectedRuns, options) {
|
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
config = {
|
|
52
|
-
...getConfig(configFile),
|
|
55
|
+
...(await getConfig(configFile)),
|
|
53
56
|
...overrides,
|
|
54
57
|
}
|
|
55
58
|
|
|
@@ -88,7 +91,7 @@ module.exports = async function (selectedRuns, options) {
|
|
|
88
91
|
})
|
|
89
92
|
|
|
90
93
|
const runsToExecute = []
|
|
91
|
-
|
|
94
|
+
createRuns(selectedRuns, config).forEach(run => {
|
|
92
95
|
const runName = run.getOriginalName() || run.getName()
|
|
93
96
|
const runConfig = run.getConfig()
|
|
94
97
|
runsToExecute.push(executeRun(runName, runConfig))
|
package/lib/command/run-rerun.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const Codecept = require('../rerun')
|
|
1
|
+
import { getConfig, getTestRoot, printError, createOutputDir } from './utils.js'
|
|
2
|
+
import Config from '../config.js'
|
|
3
|
+
import Codecept from '../rerun.js'
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
export default async function (test, options) {
|
|
7
6
|
// registering options globally to use in config
|
|
8
7
|
// Backward compatibility for --profile
|
|
9
8
|
process.profile = options.profile
|
|
10
9
|
process.env.profile = options.profile
|
|
11
10
|
const configFile = options.config
|
|
12
11
|
|
|
13
|
-
let config = getConfig(configFile)
|
|
12
|
+
let config = await getConfig(configFile)
|
|
14
13
|
if (options.override) {
|
|
15
14
|
config = Config.append(JSON.parse(options.override))
|
|
16
15
|
}
|
|
@@ -20,7 +19,7 @@ module.exports = async function (test, options) {
|
|
|
20
19
|
const codecept = new Codecept(config, options)
|
|
21
20
|
|
|
22
21
|
try {
|
|
23
|
-
codecept.init(testRoot)
|
|
22
|
+
await codecept.init(testRoot)
|
|
24
23
|
|
|
25
24
|
await codecept.bootstrap()
|
|
26
25
|
codecept.loadTests(test)
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// For Node version >=10.5.0, have to use experimental flag
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { tryOrDefault } from '../utils.js'
|
|
3
|
+
import output from '../output.js'
|
|
4
|
+
import store from '../store.js'
|
|
5
|
+
import event from '../event.js'
|
|
6
|
+
import Workers from '../workers.js'
|
|
7
|
+
import Codecept from '../codecept.js'
|
|
8
|
+
import { getMachineInfo } from './info.js'
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
export default async function (workerCount, selectedRuns, options) {
|
|
9
11
|
process.env.profile = options.profile
|
|
10
12
|
|
|
11
13
|
const { config: testConfig, override = '' } = options
|
|
@@ -36,7 +38,7 @@ module.exports = async function (workerCount, selectedRuns, options) {
|
|
|
36
38
|
|
|
37
39
|
const numberOfWorkers = parseInt(workerCount, 10)
|
|
38
40
|
|
|
39
|
-
output.print(`CodeceptJS v${
|
|
41
|
+
output.print(`CodeceptJS v${Codecept.version()} ${output.standWithUkraine()}`)
|
|
40
42
|
output.print(`Running tests in ${output.styles.bold(numberOfWorkers)} workers...`)
|
|
41
43
|
output.print()
|
|
42
44
|
store.hasWorkers = true
|
|
@@ -64,15 +66,28 @@ module.exports = async function (workerCount, selectedRuns, options) {
|
|
|
64
66
|
if (options.verbose || options.debug) store.debugMode = true
|
|
65
67
|
|
|
66
68
|
if (options.verbose) {
|
|
67
|
-
const { getMachineInfo } = require('./info')
|
|
68
69
|
await getMachineInfo()
|
|
69
70
|
}
|
|
70
71
|
await workers.bootstrapAll()
|
|
71
72
|
await workers.run()
|
|
72
73
|
} catch (err) {
|
|
73
74
|
output.error(err)
|
|
74
|
-
process.
|
|
75
|
+
process.exitCode = 1
|
|
75
76
|
} finally {
|
|
76
77
|
await workers.teardownAll()
|
|
78
|
+
|
|
79
|
+
// Force exit if event loop doesn't clear naturally
|
|
80
|
+
// This is needed because worker threads may leave handles open
|
|
81
|
+
// even after proper cleanup, preventing natural process termination
|
|
82
|
+
if (!options.noExit) {
|
|
83
|
+
// Use beforeExit to ensure we run after all other exit handlers
|
|
84
|
+
// have set the correct exit code
|
|
85
|
+
process.once('beforeExit', (code) => {
|
|
86
|
+
// Give cleanup a moment to complete, then force exit with the correct code
|
|
87
|
+
setTimeout(() => {
|
|
88
|
+
process.exit(code || process.exitCode || 0)
|
|
89
|
+
}, 100)
|
|
90
|
+
})
|
|
91
|
+
}
|
|
77
92
|
}
|
|
78
93
|
}
|
package/lib/command/run.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { getConfig, printError, getTestRoot, createOutputDir } from './utils.js'
|
|
2
|
+
import Config from '../config.js'
|
|
3
|
+
import store from '../store.js'
|
|
4
|
+
import Codecept from '../codecept.js'
|
|
5
|
+
import container from '../container.js'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
export default async function (test, options) {
|
|
7
8
|
// registering options globally to use in config
|
|
8
9
|
// Backward compatibility for --profile
|
|
9
10
|
// TODO: remove in CodeceptJS 4
|
|
@@ -16,7 +17,7 @@ module.exports = async function (test, options) {
|
|
|
16
17
|
|
|
17
18
|
const configFile = options.config
|
|
18
19
|
|
|
19
|
-
let config = getConfig(configFile)
|
|
20
|
+
let config = await getConfig(configFile)
|
|
20
21
|
if (options.override) {
|
|
21
22
|
config = Config.append(JSON.parse(options.override))
|
|
22
23
|
}
|
|
@@ -26,13 +27,13 @@ module.exports = async function (test, options) {
|
|
|
26
27
|
const codecept = new Codecept(config, options)
|
|
27
28
|
|
|
28
29
|
try {
|
|
29
|
-
codecept.init(testRoot)
|
|
30
|
+
await codecept.init(testRoot)
|
|
30
31
|
await codecept.bootstrap()
|
|
31
32
|
codecept.loadTests(test)
|
|
32
33
|
|
|
33
34
|
if (options.verbose) {
|
|
34
35
|
global.debugMode = true
|
|
35
|
-
const { getMachineInfo } =
|
|
36
|
+
const { getMachineInfo } = await import('./info.js')
|
|
36
37
|
await getMachineInfo()
|
|
37
38
|
}
|
|
38
39
|
|
|
@@ -42,5 +43,19 @@ module.exports = async function (test, options) {
|
|
|
42
43
|
process.exitCode = 1
|
|
43
44
|
} finally {
|
|
44
45
|
await codecept.teardown()
|
|
46
|
+
|
|
47
|
+
// Schedule a delayed exit to prevent process hanging due to browser helper event loops
|
|
48
|
+
// Only needed for Playwright/Puppeteer which keep the event loop alive
|
|
49
|
+
// Wait 1 second to allow final cleanup and output to complete
|
|
50
|
+
if (!process.env.CODECEPT_DISABLE_AUTO_EXIT) {
|
|
51
|
+
const helpers = container.helpers()
|
|
52
|
+
const hasBrowserHelper = helpers && (helpers.Playwright || helpers.Puppeteer || helpers.WebDriver)
|
|
53
|
+
|
|
54
|
+
if (hasBrowserHelper) {
|
|
55
|
+
setTimeout(() => {
|
|
56
|
+
process.exit(process.exitCode || 0)
|
|
57
|
+
}, 1000).unref()
|
|
58
|
+
}
|
|
59
|
+
}
|
|
45
60
|
}
|
|
46
61
|
}
|
package/lib/command/utils.js
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import util from 'util'
|
|
4
|
+
import { mkdirp } from 'mkdirp'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import output from '../output.js'
|
|
7
|
+
import { fileExists, beautify, deepMerge } from '../utils.js'
|
|
8
8
|
|
|
9
9
|
// alias to deep merge
|
|
10
|
-
|
|
10
|
+
export { deepMerge }
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
export async function getConfig(configFile) {
|
|
13
13
|
try {
|
|
14
|
-
|
|
14
|
+
const configModule = await import('../config.js')
|
|
15
|
+
const config = configModule.default || configModule
|
|
16
|
+
return await config.load(configFile)
|
|
15
17
|
} catch (err) {
|
|
16
18
|
fail(err.stack)
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
export function readConfig(configFile) {
|
|
21
23
|
try {
|
|
22
24
|
const data = fs.readFileSync(configFile, 'utf8')
|
|
23
25
|
return data
|
|
@@ -32,14 +34,14 @@ function getTestRoot(currentPath) {
|
|
|
32
34
|
currentPath = fs.lstatSync(currentPath).isDirectory() || !path.extname(currentPath) ? currentPath : path.dirname(currentPath)
|
|
33
35
|
return currentPath
|
|
34
36
|
}
|
|
35
|
-
|
|
37
|
+
export { getTestRoot }
|
|
36
38
|
|
|
37
39
|
function fail(msg) {
|
|
38
40
|
output.error(msg)
|
|
39
41
|
process.exit(1)
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
export { fail }
|
|
43
45
|
|
|
44
46
|
function updateConfig(testsPath, config, extension) {
|
|
45
47
|
const configFile = path.join(testsPath, `codecept.conf.${extension}`)
|
|
@@ -57,7 +59,7 @@ function updateConfig(testsPath, config, extension) {
|
|
|
57
59
|
return fs.writeFileSync(configFile, beautify(`exports.config = ${util.inspect(config, false, 4, false)}`), 'utf-8')
|
|
58
60
|
}
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
export { updateConfig }
|
|
61
63
|
|
|
62
64
|
function safeFileWrite(file, contents) {
|
|
63
65
|
if (fileExists(file)) {
|
|
@@ -68,9 +70,9 @@ function safeFileWrite(file, contents) {
|
|
|
68
70
|
return true
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
|
|
73
|
+
export { safeFileWrite }
|
|
72
74
|
|
|
73
|
-
|
|
75
|
+
export const captureStream = stream => {
|
|
74
76
|
let oldStream
|
|
75
77
|
let buffer = ''
|
|
76
78
|
|
|
@@ -87,14 +89,14 @@ module.exports.captureStream = stream => {
|
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
91
|
|
|
90
|
-
|
|
92
|
+
export const printError = err => {
|
|
91
93
|
output.print('')
|
|
92
94
|
output.error(err.message)
|
|
93
95
|
output.print('')
|
|
94
96
|
output.print(output.colors.grey(err.stack.replace(err.message, '')))
|
|
95
97
|
}
|
|
96
98
|
|
|
97
|
-
|
|
99
|
+
export const createOutputDir = (config, testRoot) => {
|
|
98
100
|
let outputDir
|
|
99
101
|
if (path.isAbsolute(config.output)) outputDir = config.output
|
|
100
102
|
else outputDir = path.join(testRoot, config.output)
|
|
@@ -105,7 +107,7 @@ module.exports.createOutputDir = (config, testRoot) => {
|
|
|
105
107
|
}
|
|
106
108
|
}
|
|
107
109
|
|
|
108
|
-
|
|
110
|
+
export const findConfigFile = testsPath => {
|
|
109
111
|
const extensions = ['js', 'ts']
|
|
110
112
|
for (const ext of extensions) {
|
|
111
113
|
const configFile = path.join(testsPath, `codecept.conf.${ext}`)
|