codeceptjs 4.0.0-rc.8 → 4.0.0

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 (314) hide show
  1. package/README.md +9 -10
  2. package/bin/codecept.js +15 -2
  3. package/bin/codeceptq.js +49 -0
  4. package/bin/mcp-server.js +751 -172
  5. package/docs/advanced.md +201 -0
  6. package/docs/agents.md +181 -0
  7. package/docs/ai.md +489 -0
  8. package/docs/aitrace.md +266 -0
  9. package/docs/api.md +332 -0
  10. package/docs/architecture.md +235 -0
  11. package/docs/assertions.md +415 -0
  12. package/docs/auth.md +318 -0
  13. package/docs/basics.md +424 -0
  14. package/docs/bdd.md +539 -0
  15. package/docs/best.md +240 -0
  16. package/docs/bootstrap.md +132 -0
  17. package/docs/commands.md +352 -0
  18. package/docs/community-helpers.md +63 -0
  19. package/docs/configuration.md +185 -0
  20. package/docs/continuous-integration.md +431 -0
  21. package/docs/custom-helpers.md +297 -0
  22. package/docs/data.md +448 -0
  23. package/docs/debugging.md +332 -0
  24. package/docs/detox.md +235 -0
  25. package/docs/docker.md +107 -0
  26. package/docs/effects.md +179 -0
  27. package/docs/element-based-testing.md +295 -0
  28. package/docs/element-selection.md +125 -0
  29. package/docs/els.md +328 -0
  30. package/docs/environment-variables.md +131 -0
  31. package/docs/examples.md +160 -0
  32. package/docs/heal.md +213 -0
  33. package/docs/helpers/ApiDataFactory.md +267 -0
  34. package/docs/helpers/Appium.md +1419 -0
  35. package/docs/helpers/Detox.md +665 -0
  36. package/docs/helpers/ExpectHelper.md +275 -0
  37. package/docs/helpers/FileSystem.md +152 -0
  38. package/docs/helpers/GraphQL.md +152 -0
  39. package/docs/helpers/GraphQLDataFactory.md +226 -0
  40. package/docs/helpers/JSONResponse.md +255 -0
  41. package/docs/helpers/MockRequest.md +377 -0
  42. package/docs/helpers/Playwright.md +2970 -0
  43. package/docs/helpers/Puppeteer-firefox.md +86 -0
  44. package/docs/helpers/Puppeteer.md +2583 -0
  45. package/docs/helpers/REST.md +289 -0
  46. package/docs/helpers/WebDriver.md +2639 -0
  47. package/docs/hooks.md +148 -0
  48. package/docs/index.md +111 -0
  49. package/docs/installation.md +121 -0
  50. package/docs/internal-test-server.md +89 -0
  51. package/docs/locators.md +355 -0
  52. package/docs/mcp.md +485 -0
  53. package/docs/migrate-from-cypress.md +98 -0
  54. package/docs/migrate-from-java.md +108 -0
  55. package/docs/migrate-from-protractor.md +101 -0
  56. package/docs/migrate-from-testcafe.md +99 -0
  57. package/docs/migration-4.md +743 -0
  58. package/docs/mobile.md +338 -0
  59. package/docs/pageobjects.md +399 -0
  60. package/docs/parallel.md +187 -0
  61. package/docs/playwright.md +714 -0
  62. package/docs/plugins/aiTrace.md +49 -0
  63. package/docs/plugins/analyze.md +66 -0
  64. package/docs/plugins/auth.md +241 -0
  65. package/docs/plugins/autoDelay.md +48 -0
  66. package/docs/plugins/browser.md +41 -0
  67. package/docs/plugins/coverage.md +39 -0
  68. package/docs/plugins/customLocator.md +119 -0
  69. package/docs/plugins/customReporter.md +16 -0
  70. package/docs/plugins/expose.md +75 -0
  71. package/docs/plugins/heal.md +44 -0
  72. package/docs/plugins/junitReporter.md +51 -0
  73. package/docs/plugins/pageInfo.md +34 -0
  74. package/docs/plugins/pause.md +43 -0
  75. package/docs/plugins/pauseOnFail.md +18 -0
  76. package/docs/plugins/retryFailedStep.md +75 -0
  77. package/docs/plugins/screencast.md +55 -0
  78. package/docs/plugins/screenshot.md +58 -0
  79. package/docs/plugins/screenshotOnFail.md +18 -0
  80. package/docs/plugins/stepTimeout.md +65 -0
  81. package/docs/plugins.md +87 -0
  82. package/docs/puppeteer.md +314 -0
  83. package/docs/quickstart.md +120 -0
  84. package/docs/reports.md +198 -0
  85. package/docs/retry.md +311 -0
  86. package/docs/secrets.md +150 -0
  87. package/docs/sessions.md +80 -0
  88. package/docs/shadow.md +68 -0
  89. package/docs/store.md +94 -0
  90. package/docs/test-structure.md +275 -0
  91. package/docs/timeouts.md +183 -0
  92. package/docs/translation.md +247 -0
  93. package/docs/tutorial.md +323 -0
  94. package/docs/typescript.md +159 -0
  95. package/docs/web-element.md +251 -0
  96. package/docs/webdriver.md +641 -0
  97. package/docs/within.md +55 -0
  98. package/lib/actor.js +1 -36
  99. package/lib/ai.js +3 -2
  100. package/lib/aria.js +260 -0
  101. package/lib/assertions.js +18 -0
  102. package/lib/codecept.js +7 -7
  103. package/lib/command/check.js +2 -1
  104. package/lib/command/dryRun.js +24 -5
  105. package/lib/command/generate.js +2 -0
  106. package/lib/command/gherkin/snippets.js +5 -4
  107. package/lib/command/init.js +248 -266
  108. package/lib/command/list.js +150 -10
  109. package/lib/command/query.js +218 -0
  110. package/lib/command/run-multiple.js +3 -2
  111. package/lib/command/run-workers.js +1 -14
  112. package/lib/command/run.js +3 -17
  113. package/lib/command/utils.js +14 -0
  114. package/lib/command/workers/runTests.js +11 -15
  115. package/lib/config.js +77 -4
  116. package/lib/container.js +97 -15
  117. package/lib/effects.js +17 -0
  118. package/lib/element/WebElement.js +195 -3
  119. package/lib/els.js +12 -6
  120. package/lib/globals.js +32 -19
  121. package/lib/heal.js +7 -4
  122. package/lib/helper/ApiDataFactory.js +2 -1
  123. package/lib/helper/FileSystem.js +3 -2
  124. package/lib/helper/GraphQLDataFactory.js +2 -1
  125. package/lib/helper/Playwright.js +96 -115
  126. package/lib/helper/Puppeteer.js +43 -131
  127. package/lib/helper/WebDriver.js +42 -52
  128. package/lib/helper/errors/NonFocusedType.js +8 -0
  129. package/lib/helper/extras/Download.js +45 -0
  130. package/lib/helper/extras/PlaywrightLocator.js +10 -0
  131. package/lib/helper/extras/elementSelection.js +58 -0
  132. package/lib/helper/extras/focusCheck.js +43 -0
  133. package/lib/helper/extras/richTextEditor.js +178 -0
  134. package/lib/history.js +3 -2
  135. package/lib/html.js +90 -16
  136. package/lib/index.js +9 -1
  137. package/lib/listener/config.js +6 -4
  138. package/lib/listener/emptyRun.js +2 -1
  139. package/lib/listener/helpers.js +4 -1
  140. package/lib/listener/mocha.js +2 -1
  141. package/lib/listener/pageobjects.js +43 -0
  142. package/lib/listener/result.js +3 -2
  143. package/lib/locator.js +126 -16
  144. package/lib/mocha/cli.js +4 -2
  145. package/lib/mocha/factory.js +7 -2
  146. package/lib/mocha/inject.js +1 -1
  147. package/lib/mocha/scenarioConfig.js +2 -1
  148. package/lib/mocha/ui.js +5 -6
  149. package/lib/parser.js +2 -2
  150. package/lib/pause.js +38 -4
  151. package/lib/plugin/aiTrace.js +96 -103
  152. package/lib/plugin/analyze.js +9 -9
  153. package/lib/plugin/auth.js +3 -3
  154. package/lib/plugin/browser.js +77 -0
  155. package/lib/plugin/expose.js +159 -0
  156. package/lib/plugin/heal.js +47 -3
  157. package/lib/plugin/junitReporter.js +303 -0
  158. package/lib/plugin/pageInfo.js +54 -52
  159. package/lib/plugin/pause.js +131 -0
  160. package/lib/plugin/pauseOnFail.js +11 -33
  161. package/lib/plugin/retryFailedStep.js +15 -13
  162. package/lib/plugin/screencast.js +289 -0
  163. package/lib/plugin/screenshot.js +558 -0
  164. package/lib/plugin/screenshotOnFail.js +9 -170
  165. package/lib/plugin/stepTimeout.js +3 -2
  166. package/lib/recorder.js +1 -1
  167. package/lib/rerun.js +2 -1
  168. package/lib/result.js +2 -1
  169. package/lib/step/base.js +10 -9
  170. package/lib/step/comment.js +2 -2
  171. package/lib/step/config.js +15 -2
  172. package/lib/step/helper.js +4 -4
  173. package/lib/step/meta.js +3 -3
  174. package/lib/step/record.js +5 -5
  175. package/lib/store.js +72 -3
  176. package/lib/translation.js +2 -1
  177. package/lib/utils/mask_data.js +2 -1
  178. package/lib/utils/pluginParser.js +151 -0
  179. package/lib/utils/trace.js +297 -0
  180. package/lib/utils.js +29 -3
  181. package/lib/workers.js +14 -22
  182. package/package.json +17 -14
  183. package/typings/index.d.ts +19 -5
  184. package/docs/webapi/amOnPage.mustache +0 -11
  185. package/docs/webapi/appendField.mustache +0 -16
  186. package/docs/webapi/attachFile.mustache +0 -24
  187. package/docs/webapi/blur.mustache +0 -18
  188. package/docs/webapi/checkOption.mustache +0 -13
  189. package/docs/webapi/clearCookie.mustache +0 -9
  190. package/docs/webapi/clearField.mustache +0 -14
  191. package/docs/webapi/click.mustache +0 -29
  192. package/docs/webapi/clickLink.mustache +0 -8
  193. package/docs/webapi/closeCurrentTab.mustache +0 -7
  194. package/docs/webapi/closeOtherTabs.mustache +0 -8
  195. package/docs/webapi/dontSee.mustache +0 -11
  196. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
  197. package/docs/webapi/dontSeeCookie.mustache +0 -8
  198. package/docs/webapi/dontSeeCurrentPathEquals.mustache +0 -10
  199. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
  200. package/docs/webapi/dontSeeElement.mustache +0 -12
  201. package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
  202. package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
  203. package/docs/webapi/dontSeeInField.mustache +0 -16
  204. package/docs/webapi/dontSeeInSource.mustache +0 -8
  205. package/docs/webapi/dontSeeInTitle.mustache +0 -8
  206. package/docs/webapi/dontSeeTraffic.mustache +0 -13
  207. package/docs/webapi/doubleClick.mustache +0 -13
  208. package/docs/webapi/downloadFile.mustache +0 -12
  209. package/docs/webapi/dragAndDrop.mustache +0 -9
  210. package/docs/webapi/dragSlider.mustache +0 -11
  211. package/docs/webapi/executeAsyncScript.mustache +0 -24
  212. package/docs/webapi/executeScript.mustache +0 -26
  213. package/docs/webapi/fillField.mustache +0 -21
  214. package/docs/webapi/flushNetworkTraffics.mustache +0 -5
  215. package/docs/webapi/focus.mustache +0 -13
  216. package/docs/webapi/forceClick.mustache +0 -28
  217. package/docs/webapi/forceRightClick.mustache +0 -18
  218. package/docs/webapi/grabAllWindowHandles.mustache +0 -7
  219. package/docs/webapi/grabAttributeFrom.mustache +0 -10
  220. package/docs/webapi/grabAttributeFromAll.mustache +0 -9
  221. package/docs/webapi/grabBrowserLogs.mustache +0 -9
  222. package/docs/webapi/grabCookie.mustache +0 -11
  223. package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
  224. package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
  225. package/docs/webapi/grabCurrentUrl.mustache +0 -9
  226. package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
  227. package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
  228. package/docs/webapi/grabElementBoundingRect.mustache +0 -20
  229. package/docs/webapi/grabGeoLocation.mustache +0 -8
  230. package/docs/webapi/grabHTMLFrom.mustache +0 -10
  231. package/docs/webapi/grabHTMLFromAll.mustache +0 -9
  232. package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
  233. package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
  234. package/docs/webapi/grabPageScrollPosition.mustache +0 -8
  235. package/docs/webapi/grabPopupText.mustache +0 -5
  236. package/docs/webapi/grabRecordedNetworkTraffics.mustache +0 -10
  237. package/docs/webapi/grabSource.mustache +0 -8
  238. package/docs/webapi/grabTextFrom.mustache +0 -10
  239. package/docs/webapi/grabTextFromAll.mustache +0 -9
  240. package/docs/webapi/grabTitle.mustache +0 -8
  241. package/docs/webapi/grabValueFrom.mustache +0 -9
  242. package/docs/webapi/grabValueFromAll.mustache +0 -8
  243. package/docs/webapi/grabWebElement.mustache +0 -9
  244. package/docs/webapi/grabWebElements.mustache +0 -9
  245. package/docs/webapi/moveCursorTo.mustache +0 -16
  246. package/docs/webapi/openNewTab.mustache +0 -7
  247. package/docs/webapi/pressKey.mustache +0 -12
  248. package/docs/webapi/pressKeyDown.mustache +0 -12
  249. package/docs/webapi/pressKeyUp.mustache +0 -12
  250. package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
  251. package/docs/webapi/refreshPage.mustache +0 -6
  252. package/docs/webapi/resizeWindow.mustache +0 -6
  253. package/docs/webapi/rightClick.mustache +0 -14
  254. package/docs/webapi/saveElementScreenshot.mustache +0 -10
  255. package/docs/webapi/saveScreenshot.mustache +0 -12
  256. package/docs/webapi/say.mustache +0 -10
  257. package/docs/webapi/scrollIntoView.mustache +0 -11
  258. package/docs/webapi/scrollPageToBottom.mustache +0 -6
  259. package/docs/webapi/scrollPageToTop.mustache +0 -6
  260. package/docs/webapi/scrollTo.mustache +0 -12
  261. package/docs/webapi/see.mustache +0 -11
  262. package/docs/webapi/seeAttributesOnElements.mustache +0 -9
  263. package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
  264. package/docs/webapi/seeCookie.mustache +0 -8
  265. package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
  266. package/docs/webapi/seeCurrentPathEquals.mustache +0 -10
  267. package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
  268. package/docs/webapi/seeElement.mustache +0 -12
  269. package/docs/webapi/seeElementInDOM.mustache +0 -8
  270. package/docs/webapi/seeInCurrentUrl.mustache +0 -8
  271. package/docs/webapi/seeInField.mustache +0 -17
  272. package/docs/webapi/seeInPopup.mustache +0 -8
  273. package/docs/webapi/seeInSource.mustache +0 -7
  274. package/docs/webapi/seeInTitle.mustache +0 -8
  275. package/docs/webapi/seeNumberOfElements.mustache +0 -11
  276. package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
  277. package/docs/webapi/seeTextEquals.mustache +0 -9
  278. package/docs/webapi/seeTitleEquals.mustache +0 -8
  279. package/docs/webapi/seeTraffic.mustache +0 -36
  280. package/docs/webapi/selectOption.mustache +0 -26
  281. package/docs/webapi/setCookie.mustache +0 -16
  282. package/docs/webapi/setGeoLocation.mustache +0 -12
  283. package/docs/webapi/startRecordingTraffic.mustache +0 -8
  284. package/docs/webapi/startRecordingWebSocketMessages.mustache +0 -8
  285. package/docs/webapi/stopRecordingTraffic.mustache +0 -5
  286. package/docs/webapi/stopRecordingWebSocketMessages.mustache +0 -7
  287. package/docs/webapi/switchTo.mustache +0 -9
  288. package/docs/webapi/switchToNextTab.mustache +0 -10
  289. package/docs/webapi/switchToPreviousTab.mustache +0 -10
  290. package/docs/webapi/type.mustache +0 -21
  291. package/docs/webapi/uncheckOption.mustache +0 -13
  292. package/docs/webapi/wait.mustache +0 -8
  293. package/docs/webapi/waitForClickable.mustache +0 -11
  294. package/docs/webapi/waitForCookie.mustache +0 -9
  295. package/docs/webapi/waitForDetached.mustache +0 -10
  296. package/docs/webapi/waitForDisabled.mustache +0 -6
  297. package/docs/webapi/waitForElement.mustache +0 -11
  298. package/docs/webapi/waitForEnabled.mustache +0 -6
  299. package/docs/webapi/waitForFunction.mustache +0 -17
  300. package/docs/webapi/waitForInvisible.mustache +0 -10
  301. package/docs/webapi/waitForNumberOfTabs.mustache +0 -9
  302. package/docs/webapi/waitForText.mustache +0 -13
  303. package/docs/webapi/waitForValue.mustache +0 -10
  304. package/docs/webapi/waitForVisible.mustache +0 -10
  305. package/docs/webapi/waitInUrl.mustache +0 -9
  306. package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
  307. package/docs/webapi/waitToHide.mustache +0 -10
  308. package/docs/webapi/waitUrlEquals.mustache +0 -10
  309. package/lib/helper/AI.js +0 -214
  310. package/lib/helper/Mochawesome.js +0 -96
  311. package/lib/helper/extras/PlaywrightReactVueLocator.js +0 -52
  312. package/lib/helper/extras/React.js +0 -65
  313. package/lib/plugin/stepByStepReport.js +0 -431
  314. package/lib/plugin/subtitles.js +0 -89
@@ -15,23 +15,16 @@ import { test as generateTest } from './generate.js'
15
15
  const isLocal = installedLocally()
16
16
 
17
17
  const defaultConfig = {
18
- tests: './*_test.js',
18
+ tests: './tests/*_test.js',
19
19
  output: '',
20
20
  helpers: {},
21
21
  include: {},
22
+ noGlobals: true,
22
23
  plugins: {
23
24
  },
24
25
  }
25
26
 
26
27
  const helpers = ['Playwright', 'WebDriver', 'Puppeteer', 'REST', 'GraphQL', 'Appium']
27
- const noTranslation = 'English (no localization)'
28
-
29
- async function getTranslations() {
30
- const translationsModule = await import('../../translations/index.js')
31
- const translations = Object.keys(translationsModule.default || translationsModule)
32
- translations.unshift(noTranslation)
33
- return translations
34
- }
35
28
 
36
29
  const packages = []
37
30
  let isTypeScript = false
@@ -50,6 +43,7 @@ setCommonPlugins();
50
43
  `
51
44
 
52
45
  const defaultActor = `// in this file you can append custom step methods to 'I' object
46
+ import { actor } from 'codeceptjs';
53
47
 
54
48
  export default function() {
55
49
  return actor({
@@ -62,6 +56,7 @@ export default function() {
62
56
  `
63
57
 
64
58
  const defaultActorTs = `// in this file you can append custom step methods to 'I' object
59
+ import { actor } from 'codeceptjs';
65
60
 
66
61
  export = function() {
67
62
  return actor({
@@ -73,9 +68,9 @@ export = function() {
73
68
  }
74
69
  `
75
70
 
76
- export default async function (initPath) {
71
+ export default async function (initPath, options = {}) {
77
72
  const testsPath = getTestRoot(initPath)
78
- const translations = await getTranslations()
73
+ const skipPrompts = !!options.yes
79
74
 
80
75
  print()
81
76
  print(` Welcome to ${colors.magenta.bold('CodeceptJS')} initialization tool`)
@@ -113,251 +108,265 @@ export default async function (initPath) {
113
108
  return
114
109
  }
115
110
 
116
- inquirer
117
- .prompt([
118
- {
119
- name: 'typescript',
120
- type: 'confirm',
121
- default: false,
122
- message: 'Do you plan to write tests in TypeScript?',
123
- },
124
- {
125
- name: 'tests',
126
- type: 'input',
127
- default: answers => `./*_test.${answers.typescript ? 'ts' : 'js'}`,
128
- message: 'Where are your tests located?',
129
- },
130
- {
131
- name: 'helper',
132
- type: 'list',
133
- choices: helpers,
134
- default: 'Playwright',
135
- message: 'What helpers do you want to use?',
136
- },
137
- {
138
- name: 'jsonResponse',
139
- type: 'confirm',
140
- default: true,
141
- message: 'Do you want to use JSONResponse helper for assertions on JSON responses? http://bit.ly/3ASVPy9',
142
- when: answers => ['GraphQL', 'REST'].includes(answers.helper) === true,
143
- },
144
- {
145
- name: 'output',
146
- default: './output',
147
- message: 'Where should logs, screenshots, and reports to be stored?',
148
- },
149
- {
150
- name: 'translation',
151
- type: 'list',
152
- message: 'Do you want to enable localization for tests? http://bit.ly/3GNUBbh',
153
- choices: translations,
154
- },
155
- ])
156
- .then(async result => {
157
- if (result.typescript === true) {
158
- isTypeScript = true
159
- extension = isTypeScript === true ? 'ts' : 'js'
160
- packages.push('typescript')
161
- packages.push('tsx') // Add tsx for TypeScript support
162
- packages.push('@types/node')
111
+ const result = skipPrompts
112
+ ? {
113
+ typescript: false,
114
+ tests: './tests/*_test.js',
115
+ helper: 'Playwright',
116
+ jsonResponse: false,
117
+ output: './output',
163
118
  }
119
+ : await inquirer.prompt([
120
+ {
121
+ name: 'typescript',
122
+ type: 'confirm',
123
+ default: false,
124
+ message: 'Do you plan to write tests in TypeScript?',
125
+ },
126
+ {
127
+ name: 'tests',
128
+ type: 'input',
129
+ default: answers => `./tests/*_test.${answers.typescript ? 'ts' : 'js'}`,
130
+ message: 'Where are your tests located?',
131
+ },
132
+ {
133
+ name: 'helper',
134
+ type: 'list',
135
+ choices: helpers,
136
+ default: 'Playwright',
137
+ message: 'What helpers do you want to use?',
138
+ },
139
+ {
140
+ name: 'jsonResponse',
141
+ type: 'confirm',
142
+ default: true,
143
+ message: 'Do you want to use JSONResponse helper for assertions on JSON responses? http://bit.ly/3ASVPy9',
144
+ when: answers => ['GraphQL', 'REST'].includes(answers.helper) === true,
145
+ },
146
+ {
147
+ name: 'output',
148
+ default: './output',
149
+ message: 'Where should logs, screenshots, and reports to be stored?',
150
+ },
151
+ ])
152
+
153
+ if (result.typescript === true) {
154
+ isTypeScript = true
155
+ extension = isTypeScript === true ? 'ts' : 'js'
156
+ packages.push('typescript')
157
+ packages.push('tsx')
158
+ packages.push('@types/node')
159
+ }
164
160
 
165
- const config = defaultConfig
166
- config.name = testsPath.split(path.sep).pop()
167
- config.output = result.output
161
+ const config = defaultConfig
162
+ config.name = testsPath.split(path.sep).pop()
163
+ config.output = result.output
168
164
 
169
- config.tests = result.tests
170
- if (isTypeScript) {
171
- config.tests = `${config.tests.replace(/\.js$/, `.${extension}`)}`
172
- config.require = ['tsx/cjs'] // Add tsx/cjs loader for TypeScript tests
173
- }
165
+ config.tests = result.tests
166
+ if (isTypeScript) {
167
+ config.tests = `${config.tests.replace(/\.js$/, `.${extension}`)}`
168
+ config.require = ['tsx/cjs']
169
+ }
170
+
171
+ const matchResults = config.tests.match(/[^*.]+/)
172
+ if (matchResults) {
173
+ mkdirp.sync(path.join(testsPath, matchResults[0]))
174
+ }
175
+
176
+ const helperName = result.helper
177
+ config.helpers[helperName] = {}
174
178
 
175
- // create a directory tests if it is included in tests path
176
- const matchResults = config.tests.match(/[^*.]+/)
177
- if (matchResults) {
178
- mkdirp.sync(path.join(testsPath, matchResults[0]))
179
+ if (result.jsonResponse === true) {
180
+ config.helpers.JSONResponse = {}
181
+ }
182
+
183
+ let helperConfigs = []
184
+
185
+ try {
186
+ const HelperModule = await import(`../helper/${helperName}.js`)
187
+ const Helper = HelperModule.default || HelperModule
188
+ if (Helper._checkRequirements) {
189
+ packages.concat(Helper._checkRequirements())
190
+ }
191
+
192
+ if (!Helper._config()) return
193
+ helperConfigs = helperConfigs.concat(
194
+ Helper._config().map(config => {
195
+ config.message = `[${helperName}] ${config.message}`
196
+ config.name = `${helperName}_${config.name}`
197
+ config.type = config.type || 'input'
198
+ return config
199
+ }),
200
+ )
201
+ } catch (err) {
202
+ error(err)
203
+ }
204
+
205
+ const finish = async () => {
206
+ const stepFile = `./steps_file.${extension}`
207
+ fs.writeFileSync(path.join(testsPath, stepFile), extension === 'ts' ? defaultActorTs : defaultActor)
208
+
209
+ config.include = { I: isTypeScript ? './steps_file' : stepFile }
210
+
211
+ print(`Steps file created at ${stepFile}`)
212
+
213
+ let configSource
214
+ const hasConfigure = isLocal && !initPath
215
+
216
+ if (isTypeScript) {
217
+ configSource = beautify(`export const config : CodeceptJS.MainConfig = ${inspect(config, false, 4, false)}`)
218
+
219
+ if (hasConfigure) configSource = importCodeceptConfigure + configHeader + configSource
220
+
221
+ fs.writeFileSync(typeScriptconfigFile, configSource, 'utf-8')
222
+ print(`Config created at ${typeScriptconfigFile}`)
223
+ } else {
224
+ configSource = beautify(`/** @type {CodeceptJS.MainConfig} */\nexport const config = ${inspect(config, false, 4, false)}`)
225
+
226
+ if (hasConfigure) configSource = importCodeceptConfigure + configHeader + configSource
227
+
228
+ fs.writeFileSync(configFile, configSource, 'utf-8')
229
+ print(`Config created at ${configFile}`)
230
+ }
231
+
232
+ if (config.output) {
233
+ if (!fileExists(config.output)) {
234
+ mkdirp.sync(path.join(testsPath, config.output))
235
+ print(`Directory for temporary output files created at '${config.output}'`)
236
+ } else {
237
+ print(`Directory for temporary output files is already created at '${config.output}'`)
179
238
  }
239
+ }
180
240
 
181
- if (result.translation !== noTranslation) config.translation = result.translation
241
+ const jsconfig = {
242
+ compilerOptions: {
243
+ allowJs: true,
244
+ },
245
+ }
182
246
 
183
- const helperName = result.helper
184
- config.helpers[helperName] = {}
247
+ const tsconfig = {
248
+ 'ts-node': {
249
+ files: true,
250
+ },
251
+ compilerOptions: {
252
+ target: 'es2018',
253
+ lib: ['es2018', 'DOM'],
254
+ esModuleInterop: true,
255
+ module: 'commonjs',
256
+ strictNullChecks: false,
257
+ types: ['codeceptjs', 'node'],
258
+ declaration: true,
259
+ skipLibCheck: true,
260
+ },
261
+ exclude: ['node_modules'],
262
+ }
185
263
 
186
- if (result.jsonResponse === true) {
187
- config.helpers.JSONResponse = {}
264
+ if (isTypeScript) {
265
+ const tsconfigJson = beautify(JSON.stringify(tsconfig))
266
+ const tsconfigFile = path.join(testsPath, 'tsconfig.json')
267
+ if (fileExists(tsconfigFile)) {
268
+ print(`tsconfig.json already exists at ${tsconfigFile}`)
269
+ } else {
270
+ fs.writeFileSync(tsconfigFile, tsconfigJson)
271
+ }
272
+ } else {
273
+ const jsconfigJson = beautify(JSON.stringify(jsconfig))
274
+ const jsconfigFile = path.join(testsPath, 'jsconfig.json')
275
+ if (fileExists(jsconfigFile)) {
276
+ print(`jsconfig.json already exists at ${jsconfigFile}`)
277
+ } else {
278
+ fs.writeFileSync(jsconfigFile, jsconfigJson)
279
+ print(`Intellisense enabled in ${jsconfigFile}`)
188
280
  }
281
+ }
189
282
 
190
- let helperConfigs = []
283
+ const generateDefinitionsManually = colors.bold(`To get auto-completion support, please generate type definitions: ${colors.green('npx codeceptjs def')}`)
191
284
 
285
+ if (packages) {
192
286
  try {
193
- const HelperModule = await import(`../helper/${helperName}.js`)
194
- const Helper = HelperModule.default || HelperModule
195
- if (Helper._checkRequirements) {
196
- packages.concat(Helper._checkRequirements())
197
- }
198
-
199
- if (!Helper._config()) return
200
- helperConfigs = helperConfigs.concat(
201
- Helper._config().map(config => {
202
- config.message = `[${helperName}] ${config.message}`
203
- config.name = `${helperName}_${config.name}`
204
- config.type = config.type || 'input'
205
- return config
206
- }),
207
- )
287
+ install(packages)
208
288
  } catch (err) {
209
- error(err)
289
+ print(colors.bold.red(err.toString()))
290
+ print()
291
+ print(colors.bold.red('Please install next packages manually:'))
292
+ print(`npm i ${packages.join(' ')} --save-dev`)
293
+ print()
294
+ print('Things to do after missing packages installed:')
295
+ print('☑', generateDefinitionsManually)
296
+ print('☑ Create first test:', colors.green('npx codeceptjs gt'))
297
+ print(colors.bold.magenta('Find more information at https://codecept.io'))
298
+ return
210
299
  }
300
+ }
211
301
 
212
- const finish = async () => {
213
- // create steps file by default
214
- // no extra step file for typescript (as it doesn't match TS conventions)
215
- const stepFile = `./steps_file.${extension}`
216
- fs.writeFileSync(path.join(testsPath, stepFile), extension === 'ts' ? defaultActorTs : defaultActor)
217
-
218
- if (isTypeScript) {
219
- config.include = await _actorTranslation('./steps_file', config.translation, translations)
220
- } else {
221
- config.include = await _actorTranslation(stepFile, config.translation, translations)
222
- }
223
-
224
- print(`Steps file created at ${stepFile}`)
225
-
226
- let configSource
227
- const hasConfigure = isLocal && !initPath
228
-
229
- if (isTypeScript) {
230
- configSource = beautify(`export const config : CodeceptJS.MainConfig = ${inspect(config, false, 4, false)}`)
231
-
232
- if (hasConfigure) configSource = importCodeceptConfigure + configHeader + configSource
233
-
234
- fs.writeFileSync(typeScriptconfigFile, configSource, 'utf-8')
235
- print(`Config created at ${typeScriptconfigFile}`)
236
- } else {
237
- configSource = beautify(`/** @type {CodeceptJS.MainConfig} */\nexport const config = ${inspect(config, false, 4, false)}`)
238
-
239
- if (hasConfigure) configSource = importCodeceptConfigure + configHeader + configSource
240
-
241
- fs.writeFileSync(configFile, configSource, 'utf-8')
242
- print(`Config created at ${configFile}`)
243
- }
244
-
245
- if (config.output) {
246
- if (!fileExists(config.output)) {
247
- mkdirp.sync(path.join(testsPath, config.output))
248
- print(`Directory for temporary output files created at '${config.output}'`)
249
- } else {
250
- print(`Directory for temporary output files is already created at '${config.output}'`)
251
- }
252
- }
253
-
254
- const jsconfig = {
255
- compilerOptions: {
256
- allowJs: true,
257
- },
258
- }
259
-
260
- const tsconfig = {
261
- 'ts-node': {
262
- files: true,
263
- },
264
- compilerOptions: {
265
- target: 'es2018',
266
- lib: ['es2018', 'DOM'],
267
- esModuleInterop: true,
268
- module: 'commonjs',
269
- strictNullChecks: false,
270
- types: ['codeceptjs', 'node'],
271
- declaration: true,
272
- skipLibCheck: true,
273
- },
274
- exclude: ['node_modules'],
275
- }
276
-
277
- if (isTypeScript) {
278
- const tsconfigJson = beautify(JSON.stringify(tsconfig))
279
- const tsconfigFile = path.join(testsPath, 'tsconfig.json')
280
- if (fileExists(tsconfigFile)) {
281
- print(`tsconfig.json already exists at ${tsconfigFile}`)
282
- } else {
283
- fs.writeFileSync(tsconfigFile, tsconfigJson)
284
- }
285
- } else {
286
- const jsconfigJson = beautify(JSON.stringify(jsconfig))
287
- const jsconfigFile = path.join(testsPath, 'jsconfig.json')
288
- if (fileExists(jsconfigFile)) {
289
- print(`jsconfig.json already exists at ${jsconfigFile}`)
290
- } else {
291
- fs.writeFileSync(jsconfigFile, jsconfigJson)
292
- print(`Intellisense enabled in ${jsconfigFile}`)
293
- }
294
- }
295
-
296
- const generateDefinitionsManually = colors.bold(`To get auto-completion support, please generate type definitions: ${colors.green('npx codeceptjs def')}`)
297
-
298
- if (packages) {
299
- try {
300
- install(packages)
301
- } catch (err) {
302
- print(colors.bold.red(err.toString()))
303
- print()
304
- print(colors.bold.red('Please install next packages manually:'))
305
- print(`npm i ${packages.join(' ')} --save-dev`)
306
- print()
307
- print('Things to do after missing packages installed:')
308
- print('☑', generateDefinitionsManually)
309
- print('☑ Create first test:', colors.green('npx codeceptjs gt'))
310
- print(colors.bold.magenta('Find more information at https://codecept.io'))
311
- return
312
- }
313
- }
314
-
315
- try {
316
- generateDefinitions(testsPath, {})
317
- } catch (err) {
318
- print(colors.bold.red("Couldn't generate type definitions"))
319
- print(colors.red(err.toString()))
320
- print('Skipping type definitions...')
321
- print(generateDefinitionsManually)
322
- }
323
-
324
- print('')
325
- success(' Almost ready... Next step:')
326
-
327
- const generatedTest = generateTest(testsPath)
328
- if (!generatedTest) return
329
- generatedTest.then(() => {
330
- print('\n--')
331
- print(colors.bold.green('CodeceptJS Installed! Enjoy supercharged testing! 🤩'))
332
- print(colors.bold.magenta('Find more information at https://codecept.io'))
333
- print()
334
- })
335
- }
302
+ try {
303
+ generateDefinitions(testsPath, {})
304
+ } catch (err) {
305
+ print(colors.bold.red("Couldn't generate type definitions"))
306
+ print(colors.red(err.toString()))
307
+ print('Skipping type definitions...')
308
+ print(generateDefinitionsManually)
309
+ }
310
+
311
+ print('')
312
+ success(' Almost ready... Next step:')
313
+
314
+ if (skipPrompts) {
315
+ print('\n--')
316
+ print(colors.bold.green('CodeceptJS Installed! Enjoy supercharged testing! 🤩'))
317
+ print(colors.bold.magenta('Find more information at https://codecept.io'))
318
+ print()
319
+ return
320
+ }
336
321
 
337
- print('Configure helpers...')
338
- inquirer.prompt(helperConfigs).then(async helperResult => {
339
- if (helperResult.Playwright_browser === 'electron') {
340
- delete helperResult.Playwright_url
341
- delete helperResult.Playwright_show
342
-
343
- helperResult.Playwright_electron = {
344
- executablePath: '// require("electron") or require("electron-forge")',
345
- args: ['path/to/your/main.js'],
346
- }
347
- }
348
-
349
- Object.keys(helperResult).forEach(key => {
350
- const parts = key.split('_')
351
- const helperName = parts[0]
352
- const configName = parts[1]
353
- if (!configName) return
354
- config.helpers[helperName][configName] = helperResult[key]
355
- })
356
-
357
- print('')
358
- await finish()
359
- })
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()
360
329
  })
330
+ }
331
+
332
+ const helperResult = skipPrompts
333
+ ? defaultHelperAnswers(helperName)
334
+ : await (async () => {
335
+ print('Configure helpers...')
336
+ return inquirer.prompt(helperConfigs)
337
+ })()
338
+
339
+ if (helperResult.Playwright_browser === 'electron') {
340
+ delete helperResult.Playwright_url
341
+ delete helperResult.Playwright_show
342
+
343
+ helperResult.Playwright_electron = {
344
+ executablePath: '// require("electron") or require("electron-forge")',
345
+ args: ['path/to/your/main.js'],
346
+ }
347
+ }
348
+
349
+ Object.keys(helperResult).forEach(key => {
350
+ const parts = key.split('_')
351
+ const hName = parts[0]
352
+ const configName = parts[1]
353
+ if (!configName) return
354
+ config.helpers[hName][configName] = helperResult[key]
355
+ })
356
+
357
+ print('')
358
+ await finish()
359
+ }
360
+
361
+ function defaultHelperAnswers(helperName) {
362
+ if (helperName === 'Playwright') {
363
+ return {
364
+ Playwright_browser: 'chromium',
365
+ Playwright_url: process.env.BASE_URL || 'http://localhost',
366
+ Playwright_show: false,
367
+ }
368
+ }
369
+ return {}
361
370
  }
362
371
 
363
372
  function install(dependencies) {
@@ -398,30 +407,3 @@ function install(dependencies) {
398
407
  }
399
408
  return true
400
409
  }
401
-
402
- async function _actorTranslation(stepFile, translationSelected, translations) {
403
- let actor
404
-
405
- for (const translationAvailable of translations) {
406
- if (actor) {
407
- break
408
- }
409
-
410
- if (translationSelected === translationAvailable) {
411
- const translationsModule = await import('../../translations/index.js')
412
- const nameOfActor = (translationsModule.default || translationsModule)[translationAvailable].I
413
-
414
- actor = {
415
- [nameOfActor]: stepFile,
416
- }
417
- }
418
- }
419
-
420
- if (!actor) {
421
- actor = {
422
- I: stepFile,
423
- }
424
- }
425
-
426
- return actor
427
- }