codeceptjs 4.0.0-beta.1 → 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 +133 -120
- package/bin/codecept.js +107 -96
- package/bin/test-server.js +64 -0
- package/docs/webapi/clearCookie.mustache +1 -1
- package/docs/webapi/click.mustache +5 -1
- package/lib/actor.js +71 -103
- package/lib/ai.js +159 -188
- package/lib/assert/empty.js +22 -24
- package/lib/assert/equal.js +30 -37
- package/lib/assert/error.js +14 -14
- package/lib/assert/include.js +43 -48
- package/lib/assert/throws.js +11 -11
- package/lib/assert/truth.js +22 -22
- package/lib/assert.js +20 -18
- package/lib/codecept.js +238 -162
- package/lib/colorUtils.js +50 -52
- package/lib/command/check.js +206 -0
- package/lib/command/configMigrate.js +56 -51
- package/lib/command/definitions.js +96 -109
- package/lib/command/dryRun.js +77 -79
- package/lib/command/generate.js +234 -194
- package/lib/command/gherkin/init.js +42 -33
- package/lib/command/gherkin/snippets.js +76 -74
- package/lib/command/gherkin/steps.js +20 -17
- package/lib/command/info.js +74 -38
- package/lib/command/init.js +300 -290
- package/lib/command/interactive.js +41 -32
- package/lib/command/list.js +28 -27
- package/lib/command/run-multiple/chunk.js +51 -48
- package/lib/command/run-multiple/collection.js +5 -5
- package/lib/command/run-multiple/run.js +5 -1
- package/lib/command/run-multiple.js +97 -97
- package/lib/command/run-rerun.js +19 -25
- package/lib/command/run-workers.js +68 -92
- package/lib/command/run.js +39 -27
- package/lib/command/utils.js +80 -64
- package/lib/command/workers/runTests.js +388 -226
- package/lib/config.js +124 -50
- package/lib/container.js +751 -260
- package/lib/data/context.js +60 -61
- package/lib/data/dataScenarioConfig.js +47 -47
- package/lib/data/dataTableArgument.js +32 -32
- package/lib/data/table.js +22 -22
- package/lib/effects.js +307 -0
- package/lib/element/WebElement.js +327 -0
- package/lib/els.js +160 -0
- package/lib/event.js +173 -163
- package/lib/globals.js +141 -0
- package/lib/heal.js +89 -85
- package/lib/helper/AI.js +131 -41
- package/lib/helper/ApiDataFactory.js +107 -75
- package/lib/helper/Appium.js +542 -404
- package/lib/helper/FileSystem.js +100 -79
- package/lib/helper/GraphQL.js +44 -43
- package/lib/helper/GraphQLDataFactory.js +52 -52
- package/lib/helper/JSONResponse.js +126 -88
- package/lib/helper/Mochawesome.js +54 -29
- package/lib/helper/Playwright.js +2547 -1316
- package/lib/helper/Puppeteer.js +1578 -1181
- package/lib/helper/REST.js +209 -68
- package/lib/helper/WebDriver.js +1482 -1342
- 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 +17 -8
- package/lib/helper/extras/PlaywrightRestartOpts.js +25 -11
- package/lib/helper/extras/Popup.js +22 -22
- package/lib/helper/extras/React.js +27 -28
- package/lib/helper/network/actions.js +36 -42
- package/lib/helper/network/utils.js +78 -84
- package/lib/helper/scripts/blurElement.js +5 -5
- package/lib/helper/scripts/focusElement.js +5 -5
- package/lib/helper/scripts/highlightElement.js +8 -8
- package/lib/helper/scripts/isElementClickable.js +34 -34
- package/lib/helper.js +2 -3
- package/lib/history.js +23 -19
- package/lib/hooks.js +8 -8
- package/lib/html.js +94 -104
- package/lib/index.js +38 -27
- package/lib/listener/config.js +30 -23
- package/lib/listener/emptyRun.js +54 -0
- package/lib/listener/enhancedGlobalRetry.js +110 -0
- package/lib/listener/exit.js +16 -18
- package/lib/listener/globalRetry.js +70 -0
- package/lib/listener/globalTimeout.js +181 -0
- package/lib/listener/helpers.js +76 -51
- package/lib/listener/mocha.js +10 -11
- package/lib/listener/result.js +11 -0
- package/lib/listener/retryEnhancer.js +85 -0
- package/lib/listener/steps.js +71 -59
- package/lib/listener/store.js +20 -0
- package/lib/locator.js +214 -197
- package/lib/mocha/asyncWrapper.js +274 -0
- package/lib/mocha/bdd.js +167 -0
- package/lib/mocha/cli.js +341 -0
- package/lib/mocha/factory.js +163 -0
- package/lib/mocha/featureConfig.js +89 -0
- package/lib/mocha/gherkin.js +231 -0
- package/lib/mocha/hooks.js +121 -0
- package/lib/mocha/index.js +21 -0
- package/lib/mocha/inject.js +46 -0
- package/lib/{interfaces → mocha}/scenarioConfig.js +58 -34
- package/lib/mocha/suite.js +89 -0
- package/lib/mocha/test.js +184 -0
- package/lib/mocha/types.d.ts +42 -0
- package/lib/mocha/ui.js +242 -0
- package/lib/output.js +141 -71
- package/lib/parser.js +47 -44
- package/lib/pause.js +173 -145
- package/lib/plugin/analyze.js +403 -0
- package/lib/plugin/{autoLogin.js → auth.js} +178 -79
- package/lib/plugin/autoDelay.js +36 -40
- package/lib/plugin/coverage.js +131 -78
- package/lib/plugin/customLocator.js +22 -21
- package/lib/plugin/customReporter.js +53 -0
- package/lib/plugin/enhancedRetryFailedStep.js +99 -0
- package/lib/plugin/heal.js +101 -110
- package/lib/plugin/htmlReporter.js +3648 -0
- package/lib/plugin/pageInfo.js +140 -0
- package/lib/plugin/pauseOnFail.js +12 -11
- package/lib/plugin/retryFailedStep.js +82 -47
- package/lib/plugin/screenshotOnFail.js +111 -92
- package/lib/plugin/stepByStepReport.js +159 -101
- package/lib/plugin/stepTimeout.js +20 -25
- package/lib/plugin/subtitles.js +38 -38
- package/lib/recorder.js +193 -130
- package/lib/rerun.js +94 -49
- package/lib/result.js +238 -0
- package/lib/retryCoordinator.js +207 -0
- package/lib/secret.js +20 -18
- package/lib/session.js +95 -89
- package/lib/step/base.js +239 -0
- package/lib/step/comment.js +10 -0
- package/lib/step/config.js +50 -0
- package/lib/step/func.js +46 -0
- package/lib/step/helper.js +50 -0
- package/lib/step/meta.js +99 -0
- package/lib/step/record.js +74 -0
- package/lib/step/retry.js +11 -0
- package/lib/step/section.js +55 -0
- package/lib/step.js +18 -329
- package/lib/steps.js +54 -0
- package/lib/store.js +38 -7
- package/lib/template/heal.js +3 -12
- 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 +334 -0
- package/lib/timeout.js +60 -0
- package/lib/transform.js +8 -8
- package/lib/translation.js +34 -21
- package/lib/utils/mask_data.js +47 -0
- package/lib/utils.js +411 -228
- package/lib/workerStorage.js +37 -34
- package/lib/workers.js +532 -296
- package/package.json +115 -95
- package/translations/de-DE.js +5 -3
- package/translations/fr-FR.js +5 -4
- package/translations/index.js +22 -12
- package/translations/it-IT.js +4 -3
- package/translations/ja-JP.js +4 -3
- package/translations/nl-NL.js +76 -0
- package/translations/pl-PL.js +4 -3
- package/translations/pt-BR.js +4 -3
- package/translations/ru-RU.js +4 -3
- package/translations/utils.js +10 -0
- package/translations/zh-CN.js +4 -3
- package/translations/zh-TW.js +4 -3
- package/typings/index.d.ts +546 -185
- package/typings/promiseBasedTypes.d.ts +150 -879
- package/typings/types.d.ts +547 -996
- package/lib/cli.js +0 -249
- package/lib/dirname.js +0 -5
- package/lib/helper/Expect.js +0 -425
- package/lib/helper/ExpectHelper.js +0 -399
- package/lib/helper/MockServer.js +0 -223
- package/lib/helper/Nightmare.js +0 -1411
- package/lib/helper/Protractor.js +0 -1835
- package/lib/helper/SoftExpectHelper.js +0 -381
- package/lib/helper/TestCafe.js +0 -1410
- package/lib/helper/clientscripts/nightmare.js +0 -213
- package/lib/helper/testcafe/testControllerHolder.js +0 -42
- package/lib/helper/testcafe/testcafe-utils.js +0 -63
- package/lib/interfaces/bdd.js +0 -98
- package/lib/interfaces/featureConfig.js +0 -69
- package/lib/interfaces/gherkin.js +0 -195
- package/lib/listener/artifacts.js +0 -19
- package/lib/listener/retry.js +0 -68
- package/lib/listener/timeout.js +0 -109
- package/lib/mochaFactory.js +0 -110
- package/lib/plugin/allure.js +0 -15
- package/lib/plugin/commentStep.js +0 -136
- package/lib/plugin/debugErrors.js +0 -67
- package/lib/plugin/eachElement.js +0 -127
- package/lib/plugin/fakerTransform.js +0 -49
- package/lib/plugin/retryTo.js +0 -121
- package/lib/plugin/selenoid.js +0 -371
- package/lib/plugin/standardActingHelpers.js +0 -9
- package/lib/plugin/tryTo.js +0 -105
- package/lib/plugin/wdio.js +0 -246
- package/lib/scenario.js +0 -222
- package/lib/ui.js +0 -238
- package/lib/within.js +0 -70
package/lib/command/init.js
CHANGED
|
@@ -1,38 +1,46 @@
|
|
|
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
|
|
10
|
-
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
const isLocal = installedLocally()
|
|
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()
|
|
16
16
|
|
|
17
17
|
const defaultConfig = {
|
|
18
18
|
tests: './*_test.js',
|
|
19
19
|
output: '',
|
|
20
20
|
helpers: {},
|
|
21
21
|
include: {},
|
|
22
|
-
|
|
22
|
+
plugins: {
|
|
23
|
+
htmlReporter: {
|
|
24
|
+
enabled: true,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
}
|
|
23
28
|
|
|
24
|
-
const helpers = ['Playwright', 'WebDriver', 'Puppeteer', 'REST', 'GraphQL', 'Appium'
|
|
25
|
-
const
|
|
29
|
+
const helpers = ['Playwright', 'WebDriver', 'Puppeteer', 'REST', 'GraphQL', 'Appium']
|
|
30
|
+
const noTranslation = 'English (no localization)'
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
translations.
|
|
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
|
+
}
|
|
29
38
|
|
|
30
|
-
const packages = []
|
|
31
|
-
let isTypeScript = false
|
|
32
|
-
let extension = 'js'
|
|
39
|
+
const packages = []
|
|
40
|
+
let isTypeScript = false
|
|
41
|
+
let extension = 'js'
|
|
33
42
|
|
|
34
|
-
const
|
|
35
|
-
const importCodeceptConfigure = "import { setHeadlessWhen, setCommonPlugins } from '@codeceptjs/configure';";
|
|
43
|
+
const importCodeceptConfigure = "import { setHeadlessWhen, setCommonPlugins } from '@codeceptjs/configure';"
|
|
36
44
|
|
|
37
45
|
const configHeader = `
|
|
38
46
|
// turn on headless mode when running with HEADLESS=true environment variable
|
|
@@ -42,11 +50,11 @@ setHeadlessWhen(process.env.HEADLESS);
|
|
|
42
50
|
// enable all common plugins https://github.com/codeceptjs/configure#setcommonplugins
|
|
43
51
|
setCommonPlugins();
|
|
44
52
|
|
|
45
|
-
|
|
53
|
+
`
|
|
46
54
|
|
|
47
55
|
const defaultActor = `// in this file you can append custom step methods to 'I' object
|
|
48
56
|
|
|
49
|
-
|
|
57
|
+
export default function() {
|
|
50
58
|
return actor({
|
|
51
59
|
|
|
52
60
|
// Define custom steps here, use 'this' to access default methods of I.
|
|
@@ -54,7 +62,7 @@ module.exports = function() {
|
|
|
54
62
|
|
|
55
63
|
});
|
|
56
64
|
}
|
|
57
|
-
|
|
65
|
+
`
|
|
58
66
|
|
|
59
67
|
const defaultActorTs = `// in this file you can append custom step methods to 'I' object
|
|
60
68
|
|
|
@@ -66,354 +74,356 @@ export = function() {
|
|
|
66
74
|
|
|
67
75
|
});
|
|
68
76
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
export default function (initPath) {
|
|
72
|
-
const testsPath = getTestRoot(initPath)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
print(
|
|
76
|
-
print(
|
|
77
|
-
print()
|
|
78
|
-
print(
|
|
79
|
-
print()
|
|
80
|
-
print(
|
|
81
|
-
print(' 👉 How to
|
|
82
|
-
print(' 👉
|
|
83
|
-
print()
|
|
77
|
+
`
|
|
78
|
+
|
|
79
|
+
export default async function (initPath) {
|
|
80
|
+
const testsPath = getTestRoot(initPath)
|
|
81
|
+
const translations = await getTranslations()
|
|
82
|
+
|
|
83
|
+
print()
|
|
84
|
+
print(` Welcome to ${colors.magenta.bold('CodeceptJS')} initialization tool`)
|
|
85
|
+
print(' It will prepare and configure a test environment for you')
|
|
86
|
+
print()
|
|
87
|
+
print(' Useful links:')
|
|
88
|
+
print()
|
|
89
|
+
print(' 👉 How to start testing ASAP: https://codecept.io/quickstart/#init')
|
|
90
|
+
print(' 👉 How to select helper: https://codecept.io/basics/#architecture')
|
|
91
|
+
print(' 👉 TypeScript setup: https://codecept.io/typescript/#getting-started')
|
|
92
|
+
print()
|
|
84
93
|
|
|
85
94
|
if (!path) {
|
|
86
|
-
print('No test root specified.')
|
|
87
|
-
print(`Test root is assumed to be ${colors.yellow.bold(testsPath)}`)
|
|
88
|
-
print('----------------------------------')
|
|
95
|
+
print('No test root specified.')
|
|
96
|
+
print(`Test root is assumed to be ${colors.yellow.bold(testsPath)}`)
|
|
97
|
+
print('----------------------------------')
|
|
89
98
|
} else {
|
|
90
|
-
print(`Installing to ${colors.bold(testsPath)}`)
|
|
99
|
+
print(`Installing to ${colors.bold(testsPath)}`)
|
|
91
100
|
}
|
|
92
101
|
|
|
93
102
|
if (!fileExists(testsPath)) {
|
|
94
|
-
print(`Directory ${testsPath} does not exist, creating...`)
|
|
95
|
-
mkdirp.sync(testsPath)
|
|
103
|
+
print(`Directory ${testsPath} does not exist, creating...`)
|
|
104
|
+
mkdirp.sync(testsPath)
|
|
96
105
|
}
|
|
97
106
|
|
|
98
|
-
const configFile = path.join(testsPath, 'codecept.conf.js')
|
|
107
|
+
const configFile = path.join(testsPath, 'codecept.conf.js')
|
|
99
108
|
if (fileExists(configFile)) {
|
|
100
|
-
error(`Config is already created at ${configFile}`)
|
|
101
|
-
return
|
|
109
|
+
error(`Config is already created at ${configFile}`)
|
|
110
|
+
return
|
|
102
111
|
}
|
|
103
112
|
|
|
104
|
-
const typeScriptconfigFile = path.join(testsPath, 'codecept.conf.ts')
|
|
113
|
+
const typeScriptconfigFile = path.join(testsPath, 'codecept.conf.ts')
|
|
105
114
|
if (fileExists(typeScriptconfigFile)) {
|
|
106
|
-
error(`Config is already created at ${typeScriptconfigFile}`)
|
|
107
|
-
return
|
|
115
|
+
error(`Config is already created at ${typeScriptconfigFile}`)
|
|
116
|
+
return
|
|
108
117
|
}
|
|
109
118
|
|
|
110
|
-
inquirer
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
config.name = testsPath.split(path.sep).pop();
|
|
159
|
-
config.output = result.output;
|
|
160
|
-
|
|
161
|
-
config.tests = result.tests;
|
|
162
|
-
if (isTypeScript) {
|
|
163
|
-
config.tests = `${config.tests.replace(/\.js$/, `.${extension}`)}`;
|
|
164
|
-
}
|
|
119
|
+
inquirer
|
|
120
|
+
.prompt([
|
|
121
|
+
{
|
|
122
|
+
name: 'typescript',
|
|
123
|
+
type: 'confirm',
|
|
124
|
+
default: false,
|
|
125
|
+
message: 'Do you plan to write tests in TypeScript?',
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
name: 'tests',
|
|
129
|
+
type: 'input',
|
|
130
|
+
default: answers => `./*_test.${answers.typescript ? 'ts' : 'js'}`,
|
|
131
|
+
message: 'Where are your tests located?',
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: 'helper',
|
|
135
|
+
type: 'list',
|
|
136
|
+
choices: helpers,
|
|
137
|
+
default: 'Playwright',
|
|
138
|
+
message: 'What helpers do you want to use?',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: 'jsonResponse',
|
|
142
|
+
type: 'confirm',
|
|
143
|
+
default: true,
|
|
144
|
+
message: 'Do you want to use JSONResponse helper for assertions on JSON responses? http://bit.ly/3ASVPy9',
|
|
145
|
+
when: answers => ['GraphQL', 'REST'].includes(answers.helper) === true,
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: 'output',
|
|
149
|
+
default: './output',
|
|
150
|
+
message: 'Where should logs, screenshots, and reports to be stored?',
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: 'translation',
|
|
154
|
+
type: 'list',
|
|
155
|
+
message: 'Do you want to enable localization for tests? http://bit.ly/3GNUBbh',
|
|
156
|
+
choices: translations,
|
|
157
|
+
},
|
|
158
|
+
])
|
|
159
|
+
.then(async result => {
|
|
160
|
+
if (result.typescript === true) {
|
|
161
|
+
isTypeScript = true
|
|
162
|
+
extension = isTypeScript === true ? 'ts' : 'js'
|
|
163
|
+
packages.push('typescript')
|
|
164
|
+
packages.push('ts-node')
|
|
165
|
+
packages.push('@types/node')
|
|
166
|
+
}
|
|
165
167
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
mkdirp.sync(path.join(testsPath, matchResults[0]));
|
|
170
|
-
}
|
|
168
|
+
const config = defaultConfig
|
|
169
|
+
config.name = testsPath.split(path.sep).pop()
|
|
170
|
+
config.output = result.output
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
config.tests = result.tests
|
|
173
|
+
if (isTypeScript) {
|
|
174
|
+
config.tests = `${config.tests.replace(/\.js$/, `.${extension}`)}`
|
|
175
|
+
}
|
|
173
176
|
|
|
174
|
-
|
|
175
|
-
|
|
177
|
+
// create a directory tests if it is included in tests path
|
|
178
|
+
const matchResults = config.tests.match(/[^*.]+/)
|
|
179
|
+
if (matchResults) {
|
|
180
|
+
mkdirp.sync(path.join(testsPath, matchResults[0]))
|
|
181
|
+
}
|
|
176
182
|
|
|
177
|
-
|
|
178
|
-
config.helpers.JSONResponse = {};
|
|
179
|
-
}
|
|
183
|
+
if (result.translation !== noTranslation) config.translation = result.translation
|
|
180
184
|
|
|
181
|
-
|
|
185
|
+
const helperName = result.helper
|
|
186
|
+
config.helpers[helperName] = {}
|
|
182
187
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if (Helper._checkRequirements) {
|
|
186
|
-
packages.concat(Helper._checkRequirements());
|
|
188
|
+
if (result.jsonResponse === true) {
|
|
189
|
+
config.helpers.JSONResponse = {}
|
|
187
190
|
}
|
|
188
191
|
|
|
189
|
-
|
|
190
|
-
helperConfigs = helperConfigs.concat(Helper._config().map((config) => {
|
|
191
|
-
config.message = `[${helperName}] ${config.message}`;
|
|
192
|
-
config.name = `${helperName}_${config.name}`;
|
|
193
|
-
config.type = config.type || 'input';
|
|
194
|
-
return config;
|
|
195
|
-
}));
|
|
196
|
-
} catch (err) {
|
|
197
|
-
error(err);
|
|
198
|
-
}
|
|
192
|
+
let helperConfigs = []
|
|
199
193
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
194
|
+
try {
|
|
195
|
+
const HelperModule = await import(`../helper/${helperName}.js`)
|
|
196
|
+
const Helper = HelperModule.default || HelperModule
|
|
197
|
+
if (Helper._checkRequirements) {
|
|
198
|
+
packages.concat(Helper._checkRequirements())
|
|
199
|
+
}
|
|
205
200
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
201
|
+
if (!Helper._config()) return
|
|
202
|
+
helperConfigs = helperConfigs.concat(
|
|
203
|
+
Helper._config().map(config => {
|
|
204
|
+
config.message = `[${helperName}] ${config.message}`
|
|
205
|
+
config.name = `${helperName}_${config.name}`
|
|
206
|
+
config.type = config.type || 'input'
|
|
207
|
+
return config
|
|
208
|
+
}),
|
|
209
|
+
)
|
|
210
|
+
} catch (err) {
|
|
211
|
+
error(err)
|
|
210
212
|
}
|
|
211
213
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
214
|
+
const finish = async () => {
|
|
215
|
+
// create steps file by default
|
|
216
|
+
// no extra step file for typescript (as it doesn't match TS conventions)
|
|
217
|
+
const stepFile = `./steps_file.${extension}`
|
|
218
|
+
fs.writeFileSync(path.join(testsPath, stepFile), extension === 'ts' ? defaultActorTs : defaultActor)
|
|
216
219
|
|
|
217
|
-
|
|
218
|
-
|
|
220
|
+
if (isTypeScript) {
|
|
221
|
+
config.include = await _actorTranslation('./steps_file', config.translation, translations)
|
|
222
|
+
} else {
|
|
223
|
+
config.include = await _actorTranslation(stepFile, config.translation, translations)
|
|
224
|
+
}
|
|
219
225
|
|
|
220
|
-
|
|
226
|
+
print(`Steps file created at ${stepFile}`)
|
|
221
227
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
} else {
|
|
225
|
-
configSource = beautify(`/** @type {CodeceptJS.MainConfig} */\nexports.config = ${inspect(config, false, 4, false)}`);
|
|
228
|
+
let configSource
|
|
229
|
+
const hasConfigure = isLocal && !initPath
|
|
226
230
|
|
|
227
|
-
if (
|
|
231
|
+
if (isTypeScript) {
|
|
232
|
+
configSource = beautify(`export const config : CodeceptJS.MainConfig = ${inspect(config, false, 4, false)}`)
|
|
228
233
|
|
|
229
|
-
|
|
230
|
-
print(`Config created at ${configFile}`);
|
|
231
|
-
}
|
|
234
|
+
if (hasConfigure) configSource = importCodeceptConfigure + configHeader + configSource
|
|
232
235
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
mkdirp.sync(path.join(testsPath, config.output));
|
|
236
|
-
print(`Directory for temporary output files created at '${config.output}'`);
|
|
236
|
+
fs.writeFileSync(typeScriptconfigFile, configSource, 'utf-8')
|
|
237
|
+
print(`Config created at ${typeScriptconfigFile}`)
|
|
237
238
|
} else {
|
|
238
|
-
|
|
239
|
+
configSource = beautify(`/** @type {CodeceptJS.MainConfig} */\nexport const config = ${inspect(config, false, 4, false)}`)
|
|
240
|
+
|
|
241
|
+
if (hasConfigure) configSource = importCodeceptConfigure + configHeader + configSource
|
|
242
|
+
|
|
243
|
+
fs.writeFileSync(configFile, configSource, 'utf-8')
|
|
244
|
+
print(`Config created at ${configFile}`)
|
|
239
245
|
}
|
|
240
|
-
}
|
|
241
246
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
files: true,
|
|
251
|
-
},
|
|
252
|
-
compilerOptions: {
|
|
253
|
-
target: 'es2018',
|
|
254
|
-
lib: ['es2018', 'DOM'],
|
|
255
|
-
esModuleInterop: true,
|
|
256
|
-
module: 'commonjs',
|
|
257
|
-
strictNullChecks: false,
|
|
258
|
-
types: ['codeceptjs', 'node'],
|
|
259
|
-
declaration: true,
|
|
260
|
-
skipLibCheck: true,
|
|
261
|
-
},
|
|
262
|
-
exclude: ['node_modules'],
|
|
263
|
-
};
|
|
247
|
+
if (config.output) {
|
|
248
|
+
if (!fileExists(config.output)) {
|
|
249
|
+
mkdirp.sync(path.join(testsPath, config.output))
|
|
250
|
+
print(`Directory for temporary output files created at '${config.output}'`)
|
|
251
|
+
} else {
|
|
252
|
+
print(`Directory for temporary output files is already created at '${config.output}'`)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
264
255
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
256
|
+
const jsconfig = {
|
|
257
|
+
compilerOptions: {
|
|
258
|
+
allowJs: true,
|
|
259
|
+
},
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const tsconfig = {
|
|
263
|
+
'ts-node': {
|
|
264
|
+
files: true,
|
|
265
|
+
},
|
|
266
|
+
compilerOptions: {
|
|
267
|
+
target: 'es2018',
|
|
268
|
+
lib: ['es2018', 'DOM'],
|
|
269
|
+
esModuleInterop: true,
|
|
270
|
+
module: 'commonjs',
|
|
271
|
+
strictNullChecks: false,
|
|
272
|
+
types: ['codeceptjs', 'node'],
|
|
273
|
+
declaration: true,
|
|
274
|
+
skipLibCheck: true,
|
|
275
|
+
},
|
|
276
|
+
exclude: ['node_modules'],
|
|
272
277
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
+
|
|
279
|
+
if (isTypeScript) {
|
|
280
|
+
const tsconfigJson = beautify(JSON.stringify(tsconfig))
|
|
281
|
+
const tsconfigFile = path.join(testsPath, 'tsconfig.json')
|
|
282
|
+
if (fileExists(tsconfigFile)) {
|
|
283
|
+
print(`tsconfig.json already exists at ${tsconfigFile}`)
|
|
284
|
+
} else {
|
|
285
|
+
fs.writeFileSync(tsconfigFile, tsconfigJson)
|
|
286
|
+
}
|
|
278
287
|
} else {
|
|
279
|
-
|
|
280
|
-
|
|
288
|
+
const jsconfigJson = beautify(JSON.stringify(jsconfig))
|
|
289
|
+
const jsconfigFile = path.join(testsPath, 'jsconfig.json')
|
|
290
|
+
if (fileExists(jsconfigFile)) {
|
|
291
|
+
print(`jsconfig.json already exists at ${jsconfigFile}`)
|
|
292
|
+
} else {
|
|
293
|
+
fs.writeFileSync(jsconfigFile, jsconfigJson)
|
|
294
|
+
print(`Intellisense enabled in ${jsconfigFile}`)
|
|
295
|
+
}
|
|
281
296
|
}
|
|
282
|
-
}
|
|
283
297
|
|
|
284
|
-
|
|
298
|
+
const generateDefinitionsManually = colors.bold(`To get auto-completion support, please generate type definitions: ${colors.green('npx codeceptjs def')}`)
|
|
299
|
+
|
|
300
|
+
if (packages) {
|
|
301
|
+
try {
|
|
302
|
+
install(packages)
|
|
303
|
+
} catch (err) {
|
|
304
|
+
print(colors.bold.red(err.toString()))
|
|
305
|
+
print()
|
|
306
|
+
print(colors.bold.red('Please install next packages manually:'))
|
|
307
|
+
print(`npm i ${packages.join(' ')} --save-dev`)
|
|
308
|
+
print()
|
|
309
|
+
print('Things to do after missing packages installed:')
|
|
310
|
+
print('☑', generateDefinitionsManually)
|
|
311
|
+
print('☑ Create first test:', colors.green('npx codeceptjs gt'))
|
|
312
|
+
print(colors.bold.magenta('Find more information at https://codecept.io'))
|
|
313
|
+
return
|
|
314
|
+
}
|
|
315
|
+
}
|
|
285
316
|
|
|
286
|
-
if (packages) {
|
|
287
317
|
try {
|
|
288
|
-
|
|
318
|
+
generateDefinitions(testsPath, {})
|
|
289
319
|
} catch (err) {
|
|
290
|
-
print(colors.bold.red(
|
|
291
|
-
print()
|
|
292
|
-
print(
|
|
293
|
-
print(
|
|
294
|
-
print();
|
|
295
|
-
print('Things to do after missing packages installed:');
|
|
296
|
-
print('☑', generateDefinitionsManually);
|
|
297
|
-
print('☑ Create first test:', colors.green('npx codeceptjs gt'));
|
|
298
|
-
print(colors.bold.magenta('Find more information at https://codecept.io'));
|
|
299
|
-
return;
|
|
320
|
+
print(colors.bold.red("Couldn't generate type definitions"))
|
|
321
|
+
print(colors.red(err.toString()))
|
|
322
|
+
print('Skipping type definitions...')
|
|
323
|
+
print(generateDefinitionsManually)
|
|
300
324
|
}
|
|
301
|
-
}
|
|
302
325
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
326
|
+
print('')
|
|
327
|
+
success(' Almost ready... Next step:')
|
|
328
|
+
|
|
329
|
+
const generatedTest = generateTest(testsPath)
|
|
330
|
+
if (!generatedTest) return
|
|
331
|
+
generatedTest.then(() => {
|
|
332
|
+
print('\n--')
|
|
333
|
+
print(colors.bold.green('CodeceptJS Installed! Enjoy supercharged testing! 🤩'))
|
|
334
|
+
print(colors.bold.magenta('Find more information at https://codecept.io'))
|
|
335
|
+
print()
|
|
336
|
+
})
|
|
310
337
|
}
|
|
311
338
|
|
|
312
|
-
print('')
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
generatedTest.then(() => {
|
|
318
|
-
print('\n--');
|
|
319
|
-
print(colors.bold.green('CodeceptJS Installed! Enjoy supercharged testing! 🤩'));
|
|
320
|
-
print(colors.bold.magenta('Find more information at https://codecept.io'));
|
|
321
|
-
print();
|
|
322
|
-
});
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
print('Configure helpers...');
|
|
326
|
-
inquirer.prompt(helperConfigs).then(async (helperResult) => {
|
|
327
|
-
if (helperResult.Playwright_browser === 'electron') {
|
|
328
|
-
delete helperResult.Playwright_url;
|
|
329
|
-
delete helperResult.Playwright_show;
|
|
330
|
-
|
|
331
|
-
helperResult.Playwright_electron = {
|
|
332
|
-
executablePath: '// require("electron") or require("electron-forge")',
|
|
333
|
-
args: ['path/to/your/main.js'],
|
|
334
|
-
};
|
|
335
|
-
}
|
|
339
|
+
print('Configure helpers...')
|
|
340
|
+
inquirer.prompt(helperConfigs).then(async helperResult => {
|
|
341
|
+
if (helperResult.Playwright_browser === 'electron') {
|
|
342
|
+
delete helperResult.Playwright_url
|
|
343
|
+
delete helperResult.Playwright_show
|
|
336
344
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
345
|
+
helperResult.Playwright_electron = {
|
|
346
|
+
executablePath: '// require("electron") or require("electron-forge")',
|
|
347
|
+
args: ['path/to/your/main.js'],
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
Object.keys(helperResult).forEach(key => {
|
|
352
|
+
const parts = key.split('_')
|
|
353
|
+
const helperName = parts[0]
|
|
354
|
+
const configName = parts[1]
|
|
355
|
+
if (!configName) return
|
|
356
|
+
config.helpers[helperName][configName] = helperResult[key]
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
print('')
|
|
360
|
+
await finish()
|
|
361
|
+
})
|
|
362
|
+
})
|
|
349
363
|
}
|
|
350
364
|
|
|
351
365
|
function install(dependencies) {
|
|
352
|
-
let command
|
|
353
|
-
let args
|
|
366
|
+
let command
|
|
367
|
+
let args
|
|
354
368
|
|
|
355
369
|
if (!fs.existsSync(path.join(process.cwd(), 'package.json'))) {
|
|
356
|
-
dependencies.push('codeceptjs')
|
|
357
|
-
throw new Error("Error: 'package.json' file not found. Generate it with 'npm init -y' command.")
|
|
370
|
+
dependencies.push('codeceptjs')
|
|
371
|
+
throw new Error("Error: 'package.json' file not found. Generate it with 'npm init -y' command.")
|
|
358
372
|
}
|
|
359
373
|
|
|
360
374
|
if (!installedLocally()) {
|
|
361
|
-
console.log('CodeceptJS should be installed locally')
|
|
362
|
-
dependencies.push('codeceptjs')
|
|
375
|
+
console.log('CodeceptJS should be installed locally')
|
|
376
|
+
dependencies.push('codeceptjs')
|
|
363
377
|
}
|
|
364
378
|
|
|
365
|
-
console.log('Installing packages: ', colors.green(dependencies.join(', ')))
|
|
379
|
+
console.log('Installing packages: ', colors.green(dependencies.join(', ')))
|
|
366
380
|
|
|
367
381
|
if (fileExists('yarn.lock')) {
|
|
368
|
-
command = 'yarnpkg'
|
|
369
|
-
args = ['add', '-D', '--exact']
|
|
370
|
-
[].push.apply(args, dependencies)
|
|
382
|
+
command = 'yarnpkg'
|
|
383
|
+
args = ['add', '-D', '--exact']
|
|
384
|
+
;[].push.apply(args, dependencies)
|
|
371
385
|
|
|
372
|
-
args.push('--cwd')
|
|
373
|
-
args.push(process.cwd())
|
|
386
|
+
args.push('--cwd')
|
|
387
|
+
args.push(process.cwd())
|
|
374
388
|
} else {
|
|
375
|
-
command = 'npm'
|
|
376
|
-
args = [
|
|
377
|
-
'install',
|
|
378
|
-
'--save-dev',
|
|
379
|
-
'--loglevel',
|
|
380
|
-
'error',
|
|
381
|
-
].concat(dependencies);
|
|
389
|
+
command = 'npm'
|
|
390
|
+
args = ['install', '--save-dev', '--loglevel', 'error'].concat(dependencies)
|
|
382
391
|
}
|
|
383
392
|
|
|
384
393
|
if (process.env._INIT_DRY_RUN_INSTALL) {
|
|
385
|
-
args.push('--dry-run')
|
|
394
|
+
args.push('--dry-run')
|
|
386
395
|
}
|
|
387
396
|
|
|
388
|
-
const { status } = spawn.sync(command, args, { stdio: 'inherit' })
|
|
397
|
+
const { status } = spawn.sync(command, args, { stdio: 'inherit' })
|
|
389
398
|
if (status !== 0) {
|
|
390
|
-
throw new Error(`${command} ${args.join(' ')} failed`)
|
|
399
|
+
throw new Error(`${command} ${args.join(' ')} failed`)
|
|
391
400
|
}
|
|
392
|
-
return true
|
|
401
|
+
return true
|
|
393
402
|
}
|
|
394
403
|
|
|
395
|
-
function _actorTranslation(stepFile, translationSelected) {
|
|
396
|
-
let actor
|
|
404
|
+
async function _actorTranslation(stepFile, translationSelected, translations) {
|
|
405
|
+
let actor
|
|
397
406
|
|
|
398
407
|
for (const translationAvailable of translations) {
|
|
399
408
|
if (actor) {
|
|
400
|
-
break
|
|
409
|
+
break
|
|
401
410
|
}
|
|
402
411
|
|
|
403
412
|
if (translationSelected === translationAvailable) {
|
|
404
|
-
const
|
|
413
|
+
const translationsModule = await import('../../translations/index.js')
|
|
414
|
+
const nameOfActor = (translationsModule.default || translationsModule)[translationAvailable].I
|
|
405
415
|
|
|
406
416
|
actor = {
|
|
407
417
|
[nameOfActor]: stepFile,
|
|
408
|
-
}
|
|
418
|
+
}
|
|
409
419
|
}
|
|
410
420
|
}
|
|
411
421
|
|
|
412
422
|
if (!actor) {
|
|
413
423
|
actor = {
|
|
414
424
|
I: stepFile,
|
|
415
|
-
}
|
|
425
|
+
}
|
|
416
426
|
}
|
|
417
427
|
|
|
418
|
-
return actor
|
|
428
|
+
return actor
|
|
419
429
|
}
|