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.
Files changed (209) hide show
  1. package/README.md +133 -120
  2. package/bin/codecept.js +107 -96
  3. package/bin/test-server.js +64 -0
  4. package/docs/webapi/clearCookie.mustache +1 -1
  5. package/docs/webapi/click.mustache +5 -1
  6. package/lib/actor.js +71 -103
  7. package/lib/ai.js +159 -188
  8. package/lib/assert/empty.js +22 -24
  9. package/lib/assert/equal.js +30 -37
  10. package/lib/assert/error.js +14 -14
  11. package/lib/assert/include.js +43 -48
  12. package/lib/assert/throws.js +11 -11
  13. package/lib/assert/truth.js +22 -22
  14. package/lib/assert.js +20 -18
  15. package/lib/codecept.js +262 -162
  16. package/lib/colorUtils.js +50 -52
  17. package/lib/command/check.js +206 -0
  18. package/lib/command/configMigrate.js +56 -51
  19. package/lib/command/definitions.js +96 -109
  20. package/lib/command/dryRun.js +77 -79
  21. package/lib/command/generate.js +234 -194
  22. package/lib/command/gherkin/init.js +42 -33
  23. package/lib/command/gherkin/snippets.js +76 -74
  24. package/lib/command/gherkin/steps.js +20 -17
  25. package/lib/command/info.js +74 -38
  26. package/lib/command/init.js +301 -290
  27. package/lib/command/interactive.js +41 -32
  28. package/lib/command/list.js +28 -27
  29. package/lib/command/run-multiple/chunk.js +51 -48
  30. package/lib/command/run-multiple/collection.js +5 -5
  31. package/lib/command/run-multiple/run.js +5 -1
  32. package/lib/command/run-multiple.js +97 -97
  33. package/lib/command/run-rerun.js +19 -25
  34. package/lib/command/run-workers.js +68 -92
  35. package/lib/command/run.js +39 -27
  36. package/lib/command/utils.js +80 -64
  37. package/lib/command/workers/runTests.js +388 -226
  38. package/lib/config.js +109 -50
  39. package/lib/container.js +641 -261
  40. package/lib/data/context.js +60 -61
  41. package/lib/data/dataScenarioConfig.js +47 -47
  42. package/lib/data/dataTableArgument.js +32 -32
  43. package/lib/data/table.js +22 -22
  44. package/lib/effects.js +307 -0
  45. package/lib/element/WebElement.js +327 -0
  46. package/lib/els.js +160 -0
  47. package/lib/event.js +173 -163
  48. package/lib/globals.js +141 -0
  49. package/lib/heal.js +89 -85
  50. package/lib/helper/AI.js +131 -41
  51. package/lib/helper/ApiDataFactory.js +107 -75
  52. package/lib/helper/Appium.js +542 -404
  53. package/lib/helper/FileSystem.js +100 -79
  54. package/lib/helper/GraphQL.js +44 -43
  55. package/lib/helper/GraphQLDataFactory.js +52 -52
  56. package/lib/helper/JSONResponse.js +126 -88
  57. package/lib/helper/Mochawesome.js +54 -29
  58. package/lib/helper/Playwright.js +2547 -1316
  59. package/lib/helper/Puppeteer.js +1578 -1181
  60. package/lib/helper/REST.js +209 -68
  61. package/lib/helper/WebDriver.js +1482 -1342
  62. package/lib/helper/errors/ConnectionRefused.js +6 -6
  63. package/lib/helper/errors/ElementAssertion.js +11 -16
  64. package/lib/helper/errors/ElementNotFound.js +5 -9
  65. package/lib/helper/errors/RemoteBrowserConnectionRefused.js +5 -5
  66. package/lib/helper/extras/Console.js +11 -11
  67. package/lib/helper/extras/PlaywrightLocator.js +110 -0
  68. package/lib/helper/extras/PlaywrightPropEngine.js +18 -18
  69. package/lib/helper/extras/PlaywrightReactVueLocator.js +17 -8
  70. package/lib/helper/extras/PlaywrightRestartOpts.js +25 -11
  71. package/lib/helper/extras/Popup.js +22 -22
  72. package/lib/helper/extras/React.js +27 -28
  73. package/lib/helper/network/actions.js +36 -42
  74. package/lib/helper/network/utils.js +78 -84
  75. package/lib/helper/scripts/blurElement.js +5 -5
  76. package/lib/helper/scripts/focusElement.js +5 -5
  77. package/lib/helper/scripts/highlightElement.js +8 -8
  78. package/lib/helper/scripts/isElementClickable.js +34 -34
  79. package/lib/helper.js +2 -3
  80. package/lib/history.js +23 -19
  81. package/lib/hooks.js +8 -8
  82. package/lib/html.js +94 -104
  83. package/lib/index.js +38 -27
  84. package/lib/listener/config.js +30 -23
  85. package/lib/listener/emptyRun.js +54 -0
  86. package/lib/listener/enhancedGlobalRetry.js +110 -0
  87. package/lib/listener/exit.js +16 -18
  88. package/lib/listener/globalRetry.js +70 -0
  89. package/lib/listener/globalTimeout.js +181 -0
  90. package/lib/listener/helpers.js +76 -51
  91. package/lib/listener/mocha.js +10 -11
  92. package/lib/listener/result.js +11 -0
  93. package/lib/listener/retryEnhancer.js +85 -0
  94. package/lib/listener/steps.js +71 -59
  95. package/lib/listener/store.js +20 -0
  96. package/lib/locator.js +214 -197
  97. package/lib/mocha/asyncWrapper.js +274 -0
  98. package/lib/mocha/bdd.js +167 -0
  99. package/lib/mocha/cli.js +341 -0
  100. package/lib/mocha/factory.js +163 -0
  101. package/lib/mocha/featureConfig.js +89 -0
  102. package/lib/mocha/gherkin.js +231 -0
  103. package/lib/mocha/hooks.js +121 -0
  104. package/lib/mocha/index.js +21 -0
  105. package/lib/mocha/inject.js +46 -0
  106. package/lib/{interfaces → mocha}/scenarioConfig.js +58 -34
  107. package/lib/mocha/suite.js +89 -0
  108. package/lib/mocha/test.js +184 -0
  109. package/lib/mocha/types.d.ts +42 -0
  110. package/lib/mocha/ui.js +242 -0
  111. package/lib/output.js +141 -71
  112. package/lib/parser.js +47 -44
  113. package/lib/pause.js +173 -145
  114. package/lib/plugin/analyze.js +403 -0
  115. package/lib/plugin/{autoLogin.js → auth.js} +178 -79
  116. package/lib/plugin/autoDelay.js +36 -40
  117. package/lib/plugin/coverage.js +131 -78
  118. package/lib/plugin/customLocator.js +22 -21
  119. package/lib/plugin/customReporter.js +53 -0
  120. package/lib/plugin/enhancedRetryFailedStep.js +99 -0
  121. package/lib/plugin/heal.js +101 -110
  122. package/lib/plugin/htmlReporter.js +3648 -0
  123. package/lib/plugin/pageInfo.js +140 -0
  124. package/lib/plugin/pauseOnFail.js +12 -11
  125. package/lib/plugin/retryFailedStep.js +82 -47
  126. package/lib/plugin/screenshotOnFail.js +111 -92
  127. package/lib/plugin/stepByStepReport.js +159 -101
  128. package/lib/plugin/stepTimeout.js +20 -25
  129. package/lib/plugin/subtitles.js +38 -38
  130. package/lib/recorder.js +193 -130
  131. package/lib/rerun.js +94 -49
  132. package/lib/result.js +238 -0
  133. package/lib/retryCoordinator.js +207 -0
  134. package/lib/secret.js +20 -18
  135. package/lib/session.js +95 -89
  136. package/lib/step/base.js +239 -0
  137. package/lib/step/comment.js +10 -0
  138. package/lib/step/config.js +50 -0
  139. package/lib/step/func.js +46 -0
  140. package/lib/step/helper.js +50 -0
  141. package/lib/step/meta.js +99 -0
  142. package/lib/step/record.js +74 -0
  143. package/lib/step/retry.js +11 -0
  144. package/lib/step/section.js +55 -0
  145. package/lib/step.js +18 -329
  146. package/lib/steps.js +54 -0
  147. package/lib/store.js +38 -7
  148. package/lib/template/heal.js +3 -12
  149. package/lib/template/prompts/generatePageObject.js +31 -0
  150. package/lib/template/prompts/healStep.js +13 -0
  151. package/lib/template/prompts/writeStep.js +9 -0
  152. package/lib/test-server.js +334 -0
  153. package/lib/timeout.js +60 -0
  154. package/lib/transform.js +8 -8
  155. package/lib/translation.js +34 -21
  156. package/lib/utils/loaderCheck.js +124 -0
  157. package/lib/utils/mask_data.js +47 -0
  158. package/lib/utils/typescript.js +237 -0
  159. package/lib/utils.js +411 -228
  160. package/lib/workerStorage.js +37 -34
  161. package/lib/workers.js +532 -296
  162. package/package.json +124 -95
  163. package/translations/de-DE.js +5 -3
  164. package/translations/fr-FR.js +5 -4
  165. package/translations/index.js +22 -12
  166. package/translations/it-IT.js +4 -3
  167. package/translations/ja-JP.js +4 -3
  168. package/translations/nl-NL.js +76 -0
  169. package/translations/pl-PL.js +4 -3
  170. package/translations/pt-BR.js +4 -3
  171. package/translations/ru-RU.js +4 -3
  172. package/translations/utils.js +10 -0
  173. package/translations/zh-CN.js +4 -3
  174. package/translations/zh-TW.js +4 -3
  175. package/typings/index.d.ts +546 -185
  176. package/typings/promiseBasedTypes.d.ts +150 -875
  177. package/typings/types.d.ts +547 -992
  178. package/lib/cli.js +0 -249
  179. package/lib/dirname.js +0 -5
  180. package/lib/helper/Expect.js +0 -425
  181. package/lib/helper/ExpectHelper.js +0 -399
  182. package/lib/helper/MockServer.js +0 -223
  183. package/lib/helper/Nightmare.js +0 -1411
  184. package/lib/helper/Protractor.js +0 -1835
  185. package/lib/helper/SoftExpectHelper.js +0 -381
  186. package/lib/helper/TestCafe.js +0 -1410
  187. package/lib/helper/clientscripts/nightmare.js +0 -213
  188. package/lib/helper/testcafe/testControllerHolder.js +0 -42
  189. package/lib/helper/testcafe/testcafe-utils.js +0 -63
  190. package/lib/interfaces/bdd.js +0 -98
  191. package/lib/interfaces/featureConfig.js +0 -69
  192. package/lib/interfaces/gherkin.js +0 -195
  193. package/lib/listener/artifacts.js +0 -19
  194. package/lib/listener/retry.js +0 -68
  195. package/lib/listener/timeout.js +0 -109
  196. package/lib/mochaFactory.js +0 -110
  197. package/lib/plugin/allure.js +0 -15
  198. package/lib/plugin/commentStep.js +0 -136
  199. package/lib/plugin/debugErrors.js +0 -67
  200. package/lib/plugin/eachElement.js +0 -127
  201. package/lib/plugin/fakerTransform.js +0 -49
  202. package/lib/plugin/retryTo.js +0 -121
  203. package/lib/plugin/selenoid.js +0 -371
  204. package/lib/plugin/standardActingHelpers.js +0 -9
  205. package/lib/plugin/tryTo.js +0 -105
  206. package/lib/plugin/wdio.js +0 -246
  207. package/lib/scenario.js +0 -222
  208. package/lib/ui.js +0 -238
  209. package/lib/within.js +0 -70
@@ -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
- import * as output from '../output.js';
9
- import { fileExists, beautify, installedLocally } from '../utils.js';
10
- import { getTestRoot } from './utils.js';
11
- import generateDefinitions from './definitions.js';
12
- import { test as generateTest } from './generate.js';
13
- import * as translations0 from '../../translations/index.js';
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', 'TestCafe'];
25
- const translations = Object.keys(translations0);
29
+ const helpers = ['Playwright', 'WebDriver', 'Puppeteer', 'REST', 'GraphQL', 'Appium']
30
+ const noTranslation = 'English (no localization)'
26
31
 
27
- const noTranslation = 'English (no localization)';
28
- translations.unshift(noTranslation);
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 requireCodeceptConfigure = "const { setHeadlessWhen, setCommonPlugins } = require('@codeceptjs/configure');";
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
- module.exports = function() {
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
- 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();
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.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
- ]).then((result) => {
149
- if (result.typescript === true) {
150
- isTypeScript = true;
151
- extension = isTypeScript === true ? 'ts' : 'js';
152
- packages.push('typescript');
153
- packages.push('ts-node');
154
- packages.push('@types/node');
155
- }
156
-
157
- const config = defaultConfig;
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
- // create a directory tests if it is included in tests path
167
- const matchResults = config.tests.match(/[^*.]+/);
168
- if (matchResults) {
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
- if (result.translation !== noTranslation) config.translation = result.translation;
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
- const helperName = result.helper;
175
- config.helpers[helperName] = {};
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
- if (result.jsonResponse === true) {
178
- config.helpers.JSONResponse = {};
179
- }
184
+ if (result.translation !== noTranslation) config.translation = result.translation
180
185
 
181
- let helperConfigs = [];
186
+ const helperName = result.helper
187
+ config.helpers[helperName] = {}
182
188
 
183
- try {
184
- const Helper = require(`../helper/${helperName}`);
185
- if (Helper._checkRequirements) {
186
- packages.concat(Helper._checkRequirements());
189
+ if (result.jsonResponse === true) {
190
+ config.helpers.JSONResponse = {}
187
191
  }
188
192
 
189
- if (!Helper._config()) return;
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
- const finish = async () => {
201
- // create steps file by default
202
- // no extra step file for typescript (as it doesn't match TS conventions)
203
- const stepFile = `./steps_file.${extension}`;
204
- fs.writeFileSync(path.join(testsPath, stepFile), extension === 'ts' ? defaultActorTs : defaultActor);
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
- if (isTypeScript) {
207
- config.include = _actorTranslation('./steps_file', config.translation);
208
- } else {
209
- config.include = _actorTranslation(stepFile, config.translation);
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
- print(`Steps file created at ${stepFile}`);
213
-
214
- let configSource;
215
- const hasConfigure = isLocal && !initPath;
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
- if (isTypeScript) {
218
- configSource = beautify(`export const config : CodeceptJS.MainConfig = ${inspect(config, false, 4, false)}`);
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
- if (hasConfigure) configSource = importCodeceptConfigure + configHeader + configSource;
227
+ print(`Steps file created at ${stepFile}`)
221
228
 
222
- fs.writeFileSync(typeScriptconfigFile, configSource, 'utf-8');
223
- print(`Config created at ${typeScriptconfigFile}`);
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 (hasConfigure) configSource = requireCodeceptConfigure + configHeader + configSource;
232
+ if (isTypeScript) {
233
+ configSource = beautify(`export const config : CodeceptJS.MainConfig = ${inspect(config, false, 4, false)}`)
228
234
 
229
- fs.writeFileSync(configFile, configSource, 'utf-8');
230
- print(`Config created at ${configFile}`);
231
- }
235
+ if (hasConfigure) configSource = importCodeceptConfigure + configHeader + configSource
232
236
 
233
- if (config.output) {
234
- if (!fileExists(config.output)) {
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
- print(`Directory for temporary output files is already created at '${config.output}'`);
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
- const jsconfig = {
243
- compilerOptions: {
244
- allowJs: true,
245
- },
246
- };
247
-
248
- const tsconfig = {
249
- 'ts-node': {
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
- if (isTypeScript) {
266
- const tsconfigJson = beautify(JSON.stringify(tsconfig));
267
- const tsconfigFile = path.join(testsPath, 'tsconfig.json');
268
- if (fileExists(tsconfigFile)) {
269
- print(`tsconfig.json already exists at ${tsconfigFile}`);
270
- } else {
271
- fs.writeFileSync(tsconfigFile, tsconfigJson);
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
- } else {
274
- const jsconfigJson = beautify(JSON.stringify(jsconfig));
275
- const jsconfigFile = path.join(testsPath, 'jsconfig.json');
276
- if (fileExists(jsconfigFile)) {
277
- print(`jsconfig.json already exists at ${jsconfigFile}`);
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
- fs.writeFileSync(jsconfigFile, jsconfigJson);
280
- print(`Intellisense enabled in ${jsconfigFile}`);
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
- const generateDefinitionsManually = colors.bold(`To get auto-completion support, please generate type definitions: ${colors.green('npx codeceptjs def')}`);
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
- install(packages);
319
+ generateDefinitions(testsPath, {})
289
320
  } catch (err) {
290
- print(colors.bold.red(err.toString()));
291
- print();
292
- print(colors.bold.red('Please install next packages manually:'));
293
- print(`npm i ${packages.join(' ')} --save-dev`);
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
- try {
304
- generateDefinitions(testsPath, {});
305
- } catch (err) {
306
- print(colors.bold.red('Couldn\'t generate type definitions'));
307
- print(colors.red(err.toString()));
308
- print('Skipping type definitions...');
309
- print(generateDefinitionsManually);
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
- success(' Almost ready... Next step:');
314
-
315
- const generatedTest = generateTest(testsPath);
316
- if (!generatedTest) return;
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
- Object.keys(helperResult).forEach((key) => {
338
- const parts = key.split('_');
339
- const helperName = parts[0];
340
- const configName = parts[1];
341
- if (!configName) return;
342
- config.helpers[helperName][configName] = helperResult[key];
343
- });
344
-
345
- print('');
346
- await finish();
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 nameOfActor = require('../../translations')[translationAvailable].I;
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
  }