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