codeceptjs 4.0.0-beta.2 → 4.0.0-beta.20
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 +262 -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 +301 -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 +109 -50
- package/lib/container.js +641 -261
- 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/loaderCheck.js +124 -0
- package/lib/utils/mask_data.js +47 -0
- package/lib/utils/typescript.js +237 -0
- package/lib/utils.js +411 -228
- package/lib/workerStorage.js +37 -34
- package/lib/workers.js +532 -296
- package/package.json +124 -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 -875
- package/typings/types.d.ts +547 -992
- 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,357 @@ 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('tsx') // Add tsx for TypeScript support
|
|
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
|
+
config.require = ['tsx/cjs'] // Add tsx/cjs loader for TypeScript tests
|
|
176
|
+
}
|
|
173
177
|
|
|
174
|
-
|
|
175
|
-
|
|
178
|
+
// create a directory tests if it is included in tests path
|
|
179
|
+
const matchResults = config.tests.match(/[^*.]+/)
|
|
180
|
+
if (matchResults) {
|
|
181
|
+
mkdirp.sync(path.join(testsPath, matchResults[0]))
|
|
182
|
+
}
|
|
176
183
|
|
|
177
|
-
|
|
178
|
-
config.helpers.JSONResponse = {};
|
|
179
|
-
}
|
|
184
|
+
if (result.translation !== noTranslation) config.translation = result.translation
|
|
180
185
|
|
|
181
|
-
|
|
186
|
+
const helperName = result.helper
|
|
187
|
+
config.helpers[helperName] = {}
|
|
182
188
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if (Helper._checkRequirements) {
|
|
186
|
-
packages.concat(Helper._checkRequirements());
|
|
189
|
+
if (result.jsonResponse === true) {
|
|
190
|
+
config.helpers.JSONResponse = {}
|
|
187
191
|
}
|
|
188
192
|
|
|
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
|
-
}
|
|
193
|
+
let helperConfigs = []
|
|
199
194
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
195
|
+
try {
|
|
196
|
+
const HelperModule = await import(`../helper/${helperName}.js`)
|
|
197
|
+
const Helper = HelperModule.default || HelperModule
|
|
198
|
+
if (Helper._checkRequirements) {
|
|
199
|
+
packages.concat(Helper._checkRequirements())
|
|
200
|
+
}
|
|
205
201
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
202
|
+
if (!Helper._config()) return
|
|
203
|
+
helperConfigs = helperConfigs.concat(
|
|
204
|
+
Helper._config().map(config => {
|
|
205
|
+
config.message = `[${helperName}] ${config.message}`
|
|
206
|
+
config.name = `${helperName}_${config.name}`
|
|
207
|
+
config.type = config.type || 'input'
|
|
208
|
+
return config
|
|
209
|
+
}),
|
|
210
|
+
)
|
|
211
|
+
} catch (err) {
|
|
212
|
+
error(err)
|
|
210
213
|
}
|
|
211
214
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
215
|
+
const finish = async () => {
|
|
216
|
+
// create steps file by default
|
|
217
|
+
// no extra step file for typescript (as it doesn't match TS conventions)
|
|
218
|
+
const stepFile = `./steps_file.${extension}`
|
|
219
|
+
fs.writeFileSync(path.join(testsPath, stepFile), extension === 'ts' ? defaultActorTs : defaultActor)
|
|
216
220
|
|
|
217
|
-
|
|
218
|
-
|
|
221
|
+
if (isTypeScript) {
|
|
222
|
+
config.include = await _actorTranslation('./steps_file', config.translation, translations)
|
|
223
|
+
} else {
|
|
224
|
+
config.include = await _actorTranslation(stepFile, config.translation, translations)
|
|
225
|
+
}
|
|
219
226
|
|
|
220
|
-
|
|
227
|
+
print(`Steps file created at ${stepFile}`)
|
|
221
228
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
} else {
|
|
225
|
-
configSource = beautify(`/** @type {CodeceptJS.MainConfig} */\nexports.config = ${inspect(config, false, 4, false)}`);
|
|
229
|
+
let configSource
|
|
230
|
+
const hasConfigure = isLocal && !initPath
|
|
226
231
|
|
|
227
|
-
if (
|
|
232
|
+
if (isTypeScript) {
|
|
233
|
+
configSource = beautify(`export const config : CodeceptJS.MainConfig = ${inspect(config, false, 4, false)}`)
|
|
228
234
|
|
|
229
|
-
|
|
230
|
-
print(`Config created at ${configFile}`);
|
|
231
|
-
}
|
|
235
|
+
if (hasConfigure) configSource = importCodeceptConfigure + configHeader + configSource
|
|
232
236
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
mkdirp.sync(path.join(testsPath, config.output));
|
|
236
|
-
print(`Directory for temporary output files created at '${config.output}'`);
|
|
237
|
+
fs.writeFileSync(typeScriptconfigFile, configSource, 'utf-8')
|
|
238
|
+
print(`Config created at ${typeScriptconfigFile}`)
|
|
237
239
|
} else {
|
|
238
|
-
|
|
240
|
+
configSource = beautify(`/** @type {CodeceptJS.MainConfig} */\nexport const config = ${inspect(config, false, 4, false)}`)
|
|
241
|
+
|
|
242
|
+
if (hasConfigure) configSource = importCodeceptConfigure + configHeader + configSource
|
|
243
|
+
|
|
244
|
+
fs.writeFileSync(configFile, configSource, 'utf-8')
|
|
245
|
+
print(`Config created at ${configFile}`)
|
|
239
246
|
}
|
|
240
|
-
}
|
|
241
247
|
|
|
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
|
-
};
|
|
248
|
+
if (config.output) {
|
|
249
|
+
if (!fileExists(config.output)) {
|
|
250
|
+
mkdirp.sync(path.join(testsPath, config.output))
|
|
251
|
+
print(`Directory for temporary output files created at '${config.output}'`)
|
|
252
|
+
} else {
|
|
253
|
+
print(`Directory for temporary output files is already created at '${config.output}'`)
|
|
254
|
+
}
|
|
255
|
+
}
|
|
264
256
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
257
|
+
const jsconfig = {
|
|
258
|
+
compilerOptions: {
|
|
259
|
+
allowJs: true,
|
|
260
|
+
},
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const tsconfig = {
|
|
264
|
+
'ts-node': {
|
|
265
|
+
files: true,
|
|
266
|
+
},
|
|
267
|
+
compilerOptions: {
|
|
268
|
+
target: 'es2018',
|
|
269
|
+
lib: ['es2018', 'DOM'],
|
|
270
|
+
esModuleInterop: true,
|
|
271
|
+
module: 'commonjs',
|
|
272
|
+
strictNullChecks: false,
|
|
273
|
+
types: ['codeceptjs', 'node'],
|
|
274
|
+
declaration: true,
|
|
275
|
+
skipLibCheck: true,
|
|
276
|
+
},
|
|
277
|
+
exclude: ['node_modules'],
|
|
272
278
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
279
|
+
|
|
280
|
+
if (isTypeScript) {
|
|
281
|
+
const tsconfigJson = beautify(JSON.stringify(tsconfig))
|
|
282
|
+
const tsconfigFile = path.join(testsPath, 'tsconfig.json')
|
|
283
|
+
if (fileExists(tsconfigFile)) {
|
|
284
|
+
print(`tsconfig.json already exists at ${tsconfigFile}`)
|
|
285
|
+
} else {
|
|
286
|
+
fs.writeFileSync(tsconfigFile, tsconfigJson)
|
|
287
|
+
}
|
|
278
288
|
} else {
|
|
279
|
-
|
|
280
|
-
|
|
289
|
+
const jsconfigJson = beautify(JSON.stringify(jsconfig))
|
|
290
|
+
const jsconfigFile = path.join(testsPath, 'jsconfig.json')
|
|
291
|
+
if (fileExists(jsconfigFile)) {
|
|
292
|
+
print(`jsconfig.json already exists at ${jsconfigFile}`)
|
|
293
|
+
} else {
|
|
294
|
+
fs.writeFileSync(jsconfigFile, jsconfigJson)
|
|
295
|
+
print(`Intellisense enabled in ${jsconfigFile}`)
|
|
296
|
+
}
|
|
281
297
|
}
|
|
282
|
-
}
|
|
283
298
|
|
|
284
|
-
|
|
299
|
+
const generateDefinitionsManually = colors.bold(`To get auto-completion support, please generate type definitions: ${colors.green('npx codeceptjs def')}`)
|
|
300
|
+
|
|
301
|
+
if (packages) {
|
|
302
|
+
try {
|
|
303
|
+
install(packages)
|
|
304
|
+
} catch (err) {
|
|
305
|
+
print(colors.bold.red(err.toString()))
|
|
306
|
+
print()
|
|
307
|
+
print(colors.bold.red('Please install next packages manually:'))
|
|
308
|
+
print(`npm i ${packages.join(' ')} --save-dev`)
|
|
309
|
+
print()
|
|
310
|
+
print('Things to do after missing packages installed:')
|
|
311
|
+
print('☑', generateDefinitionsManually)
|
|
312
|
+
print('☑ Create first test:', colors.green('npx codeceptjs gt'))
|
|
313
|
+
print(colors.bold.magenta('Find more information at https://codecept.io'))
|
|
314
|
+
return
|
|
315
|
+
}
|
|
316
|
+
}
|
|
285
317
|
|
|
286
|
-
if (packages) {
|
|
287
318
|
try {
|
|
288
|
-
|
|
319
|
+
generateDefinitions(testsPath, {})
|
|
289
320
|
} 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;
|
|
321
|
+
print(colors.bold.red("Couldn't generate type definitions"))
|
|
322
|
+
print(colors.red(err.toString()))
|
|
323
|
+
print('Skipping type definitions...')
|
|
324
|
+
print(generateDefinitionsManually)
|
|
300
325
|
}
|
|
301
|
-
}
|
|
302
326
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
327
|
+
print('')
|
|
328
|
+
success(' Almost ready... Next step:')
|
|
329
|
+
|
|
330
|
+
const generatedTest = generateTest(testsPath)
|
|
331
|
+
if (!generatedTest) return
|
|
332
|
+
generatedTest.then(() => {
|
|
333
|
+
print('\n--')
|
|
334
|
+
print(colors.bold.green('CodeceptJS Installed! Enjoy supercharged testing! 🤩'))
|
|
335
|
+
print(colors.bold.magenta('Find more information at https://codecept.io'))
|
|
336
|
+
print()
|
|
337
|
+
})
|
|
310
338
|
}
|
|
311
339
|
|
|
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
|
-
}
|
|
340
|
+
print('Configure helpers...')
|
|
341
|
+
inquirer.prompt(helperConfigs).then(async helperResult => {
|
|
342
|
+
if (helperResult.Playwright_browser === 'electron') {
|
|
343
|
+
delete helperResult.Playwright_url
|
|
344
|
+
delete helperResult.Playwright_show
|
|
336
345
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
346
|
+
helperResult.Playwright_electron = {
|
|
347
|
+
executablePath: '// require("electron") or require("electron-forge")',
|
|
348
|
+
args: ['path/to/your/main.js'],
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
Object.keys(helperResult).forEach(key => {
|
|
353
|
+
const parts = key.split('_')
|
|
354
|
+
const helperName = parts[0]
|
|
355
|
+
const configName = parts[1]
|
|
356
|
+
if (!configName) return
|
|
357
|
+
config.helpers[helperName][configName] = helperResult[key]
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
print('')
|
|
361
|
+
await finish()
|
|
362
|
+
})
|
|
363
|
+
})
|
|
349
364
|
}
|
|
350
365
|
|
|
351
366
|
function install(dependencies) {
|
|
352
|
-
let command
|
|
353
|
-
let args
|
|
367
|
+
let command
|
|
368
|
+
let args
|
|
354
369
|
|
|
355
370
|
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.")
|
|
371
|
+
dependencies.push('codeceptjs')
|
|
372
|
+
throw new Error("Error: 'package.json' file not found. Generate it with 'npm init -y' command.")
|
|
358
373
|
}
|
|
359
374
|
|
|
360
375
|
if (!installedLocally()) {
|
|
361
|
-
console.log('CodeceptJS should be installed locally')
|
|
362
|
-
dependencies.push('codeceptjs')
|
|
376
|
+
console.log('CodeceptJS should be installed locally')
|
|
377
|
+
dependencies.push('codeceptjs')
|
|
363
378
|
}
|
|
364
379
|
|
|
365
|
-
console.log('Installing packages: ', colors.green(dependencies.join(', ')))
|
|
380
|
+
console.log('Installing packages: ', colors.green(dependencies.join(', ')))
|
|
366
381
|
|
|
367
382
|
if (fileExists('yarn.lock')) {
|
|
368
|
-
command = 'yarnpkg'
|
|
369
|
-
args = ['add', '-D', '--exact']
|
|
370
|
-
[].push.apply(args, dependencies)
|
|
383
|
+
command = 'yarnpkg'
|
|
384
|
+
args = ['add', '-D', '--exact']
|
|
385
|
+
;[].push.apply(args, dependencies)
|
|
371
386
|
|
|
372
|
-
args.push('--cwd')
|
|
373
|
-
args.push(process.cwd())
|
|
387
|
+
args.push('--cwd')
|
|
388
|
+
args.push(process.cwd())
|
|
374
389
|
} else {
|
|
375
|
-
command = 'npm'
|
|
376
|
-
args = [
|
|
377
|
-
'install',
|
|
378
|
-
'--save-dev',
|
|
379
|
-
'--loglevel',
|
|
380
|
-
'error',
|
|
381
|
-
].concat(dependencies);
|
|
390
|
+
command = 'npm'
|
|
391
|
+
args = ['install', '--save-dev', '--loglevel', 'error'].concat(dependencies)
|
|
382
392
|
}
|
|
383
393
|
|
|
384
394
|
if (process.env._INIT_DRY_RUN_INSTALL) {
|
|
385
|
-
args.push('--dry-run')
|
|
395
|
+
args.push('--dry-run')
|
|
386
396
|
}
|
|
387
397
|
|
|
388
|
-
const { status } = spawn.sync(command, args, { stdio: 'inherit' })
|
|
398
|
+
const { status } = spawn.sync(command, args, { stdio: 'inherit' })
|
|
389
399
|
if (status !== 0) {
|
|
390
|
-
throw new Error(`${command} ${args.join(' ')} failed`)
|
|
400
|
+
throw new Error(`${command} ${args.join(' ')} failed`)
|
|
391
401
|
}
|
|
392
|
-
return true
|
|
402
|
+
return true
|
|
393
403
|
}
|
|
394
404
|
|
|
395
|
-
function _actorTranslation(stepFile, translationSelected) {
|
|
396
|
-
let actor
|
|
405
|
+
async function _actorTranslation(stepFile, translationSelected, translations) {
|
|
406
|
+
let actor
|
|
397
407
|
|
|
398
408
|
for (const translationAvailable of translations) {
|
|
399
409
|
if (actor) {
|
|
400
|
-
break
|
|
410
|
+
break
|
|
401
411
|
}
|
|
402
412
|
|
|
403
413
|
if (translationSelected === translationAvailable) {
|
|
404
|
-
const
|
|
414
|
+
const translationsModule = await import('../../translations/index.js')
|
|
415
|
+
const nameOfActor = (translationsModule.default || translationsModule)[translationAvailable].I
|
|
405
416
|
|
|
406
417
|
actor = {
|
|
407
418
|
[nameOfActor]: stepFile,
|
|
408
|
-
}
|
|
419
|
+
}
|
|
409
420
|
}
|
|
410
421
|
}
|
|
411
422
|
|
|
412
423
|
if (!actor) {
|
|
413
424
|
actor = {
|
|
414
425
|
I: stepFile,
|
|
415
|
-
}
|
|
426
|
+
}
|
|
416
427
|
}
|
|
417
428
|
|
|
418
|
-
return actor
|
|
429
|
+
return actor
|
|
419
430
|
}
|