codeceptjs 3.7.6-beta.4 → 4.0.0-beta.10.esm-aria

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/README.md +1 -3
  2. package/bin/codecept.js +51 -53
  3. package/bin/test-server.js +14 -3
  4. package/docs/webapi/click.mustache +5 -1
  5. package/lib/actor.js +15 -11
  6. package/lib/ai.js +72 -107
  7. package/lib/assert/empty.js +9 -8
  8. package/lib/assert/equal.js +15 -17
  9. package/lib/assert/error.js +2 -2
  10. package/lib/assert/include.js +9 -11
  11. package/lib/assert/throws.js +1 -1
  12. package/lib/assert/truth.js +8 -5
  13. package/lib/assert.js +18 -18
  14. package/lib/codecept.js +102 -75
  15. package/lib/colorUtils.js +48 -50
  16. package/lib/command/check.js +32 -27
  17. package/lib/command/configMigrate.js +11 -10
  18. package/lib/command/definitions.js +16 -10
  19. package/lib/command/dryRun.js +16 -16
  20. package/lib/command/generate.js +62 -27
  21. package/lib/command/gherkin/init.js +36 -38
  22. package/lib/command/gherkin/snippets.js +14 -14
  23. package/lib/command/gherkin/steps.js +21 -18
  24. package/lib/command/info.js +8 -8
  25. package/lib/command/init.js +36 -29
  26. package/lib/command/interactive.js +11 -10
  27. package/lib/command/list.js +10 -9
  28. package/lib/command/run-multiple/chunk.js +5 -5
  29. package/lib/command/run-multiple/collection.js +5 -5
  30. package/lib/command/run-multiple/run.js +3 -3
  31. package/lib/command/run-multiple.js +16 -13
  32. package/lib/command/run-rerun.js +6 -7
  33. package/lib/command/run-workers.js +24 -9
  34. package/lib/command/run.js +23 -8
  35. package/lib/command/utils.js +20 -18
  36. package/lib/command/workers/runTests.js +197 -114
  37. package/lib/config.js +124 -51
  38. package/lib/container.js +438 -87
  39. package/lib/data/context.js +6 -5
  40. package/lib/data/dataScenarioConfig.js +1 -1
  41. package/lib/data/dataTableArgument.js +1 -1
  42. package/lib/data/table.js +1 -1
  43. package/lib/effects.js +94 -10
  44. package/lib/element/WebElement.js +2 -2
  45. package/lib/els.js +11 -9
  46. package/lib/event.js +11 -10
  47. package/lib/globals.js +141 -0
  48. package/lib/heal.js +12 -12
  49. package/lib/helper/AI.js +11 -11
  50. package/lib/helper/ApiDataFactory.js +50 -19
  51. package/lib/helper/Appium.js +19 -27
  52. package/lib/helper/FileSystem.js +32 -12
  53. package/lib/helper/GraphQL.js +3 -3
  54. package/lib/helper/GraphQLDataFactory.js +4 -4
  55. package/lib/helper/JSONResponse.js +25 -29
  56. package/lib/helper/Mochawesome.js +7 -4
  57. package/lib/helper/Playwright.js +902 -164
  58. package/lib/helper/Puppeteer.js +383 -76
  59. package/lib/helper/REST.js +29 -12
  60. package/lib/helper/WebDriver.js +268 -61
  61. package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
  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 +18 -9
  70. package/lib/helper/extras/PlaywrightRestartOpts.js +34 -23
  71. package/lib/helper/extras/Popup.js +1 -1
  72. package/lib/helper/extras/React.js +29 -30
  73. package/lib/helper/network/actions.js +29 -44
  74. package/lib/helper/network/utils.js +76 -83
  75. package/lib/helper/scripts/blurElement.js +6 -6
  76. package/lib/helper/scripts/focusElement.js +6 -6
  77. package/lib/helper/scripts/highlightElement.js +9 -9
  78. package/lib/helper/scripts/isElementClickable.js +34 -34
  79. package/lib/helper.js +2 -1
  80. package/lib/history.js +23 -20
  81. package/lib/hooks.js +10 -10
  82. package/lib/html.js +90 -100
  83. package/lib/index.js +48 -21
  84. package/lib/listener/config.js +19 -12
  85. package/lib/listener/emptyRun.js +6 -7
  86. package/lib/listener/enhancedGlobalRetry.js +6 -6
  87. package/lib/listener/exit.js +4 -3
  88. package/lib/listener/globalRetry.js +5 -5
  89. package/lib/listener/globalTimeout.js +30 -14
  90. package/lib/listener/helpers.js +39 -14
  91. package/lib/listener/mocha.js +3 -4
  92. package/lib/listener/result.js +4 -5
  93. package/lib/listener/retryEnhancer.js +3 -3
  94. package/lib/listener/steps.js +8 -7
  95. package/lib/listener/store.js +3 -3
  96. package/lib/locator.js +213 -192
  97. package/lib/mocha/asyncWrapper.js +105 -62
  98. package/lib/mocha/bdd.js +99 -13
  99. package/lib/mocha/cli.js +59 -26
  100. package/lib/mocha/factory.js +78 -19
  101. package/lib/mocha/featureConfig.js +1 -1
  102. package/lib/mocha/gherkin.js +56 -24
  103. package/lib/mocha/hooks.js +12 -3
  104. package/lib/mocha/index.js +13 -4
  105. package/lib/mocha/inject.js +22 -5
  106. package/lib/mocha/scenarioConfig.js +2 -2
  107. package/lib/mocha/suite.js +9 -2
  108. package/lib/mocha/test.js +10 -7
  109. package/lib/mocha/ui.js +28 -18
  110. package/lib/output.js +10 -8
  111. package/lib/parser.js +44 -44
  112. package/lib/pause.js +15 -16
  113. package/lib/plugin/analyze.js +19 -12
  114. package/lib/plugin/auth.js +20 -21
  115. package/lib/plugin/autoDelay.js +12 -8
  116. package/lib/plugin/coverage.js +28 -11
  117. package/lib/plugin/customLocator.js +3 -3
  118. package/lib/plugin/customReporter.js +3 -2
  119. package/lib/plugin/enhancedRetryFailedStep.js +6 -6
  120. package/lib/plugin/heal.js +14 -9
  121. package/lib/plugin/htmlReporter.js +724 -99
  122. package/lib/plugin/pageInfo.js +10 -10
  123. package/lib/plugin/pauseOnFail.js +4 -3
  124. package/lib/plugin/retryFailedStep.js +48 -5
  125. package/lib/plugin/screenshotOnFail.js +75 -37
  126. package/lib/plugin/stepByStepReport.js +14 -14
  127. package/lib/plugin/stepTimeout.js +4 -3
  128. package/lib/plugin/subtitles.js +6 -5
  129. package/lib/recorder.js +33 -14
  130. package/lib/rerun.js +69 -26
  131. package/lib/result.js +4 -4
  132. package/lib/retryCoordinator.js +2 -2
  133. package/lib/secret.js +18 -17
  134. package/lib/session.js +95 -89
  135. package/lib/step/base.js +7 -7
  136. package/lib/step/comment.js +2 -2
  137. package/lib/step/config.js +1 -1
  138. package/lib/step/func.js +3 -3
  139. package/lib/step/helper.js +3 -3
  140. package/lib/step/meta.js +5 -5
  141. package/lib/step/record.js +11 -11
  142. package/lib/step/retry.js +3 -3
  143. package/lib/step/section.js +3 -3
  144. package/lib/step.js +7 -10
  145. package/lib/steps.js +9 -5
  146. package/lib/store.js +1 -1
  147. package/lib/template/heal.js +1 -1
  148. package/lib/template/prompts/generatePageObject.js +31 -0
  149. package/lib/template/prompts/healStep.js +13 -0
  150. package/lib/template/prompts/writeStep.js +9 -0
  151. package/lib/test-server.js +17 -6
  152. package/lib/timeout.js +1 -7
  153. package/lib/transform.js +8 -8
  154. package/lib/translation.js +32 -18
  155. package/lib/utils/mask_data.js +4 -10
  156. package/lib/utils.js +66 -64
  157. package/lib/workerStorage.js +17 -17
  158. package/lib/workers.js +214 -84
  159. package/package.json +41 -37
  160. package/translations/de-DE.js +2 -2
  161. package/translations/fr-FR.js +2 -2
  162. package/translations/index.js +23 -10
  163. package/translations/it-IT.js +2 -2
  164. package/translations/ja-JP.js +2 -2
  165. package/translations/nl-NL.js +2 -2
  166. package/translations/pl-PL.js +2 -2
  167. package/translations/pt-BR.js +2 -2
  168. package/translations/ru-RU.js +2 -2
  169. package/translations/utils.js +4 -3
  170. package/translations/zh-CN.js +2 -2
  171. package/translations/zh-TW.js +2 -2
  172. package/typings/index.d.ts +5 -3
  173. package/typings/promiseBasedTypes.d.ts +4 -0
  174. package/typings/types.d.ts +4 -0
  175. package/lib/helper/Nightmare.js +0 -1486
  176. package/lib/helper/Protractor.js +0 -1840
  177. package/lib/helper/TestCafe.js +0 -1391
  178. package/lib/helper/clientscripts/nightmare.js +0 -213
  179. package/lib/helper/testcafe/testControllerHolder.js +0 -42
  180. package/lib/helper/testcafe/testcafe-utils.js +0 -61
  181. package/lib/plugin/allure.js +0 -15
  182. package/lib/plugin/autoLogin.js +0 -5
  183. package/lib/plugin/commentStep.js +0 -141
  184. package/lib/plugin/eachElement.js +0 -127
  185. package/lib/plugin/fakerTransform.js +0 -49
  186. package/lib/plugin/retryTo.js +0 -16
  187. package/lib/plugin/selenoid.js +0 -364
  188. package/lib/plugin/standardActingHelpers.js +0 -6
  189. package/lib/plugin/tryTo.js +0 -16
  190. package/lib/plugin/wdio.js +0 -247
  191. package/lib/within.js +0 -90
@@ -1,15 +1,15 @@
1
- const { getConfig, getTestRoot } = require('./utils')
2
- const Codecept = require('../codecept')
3
- const output = require('../output')
4
- const store = require('../store')
5
- const container = require('../container')
6
- const figures = require('figures')
7
- const chalk = require('chalk')
8
- const { createTest } = require('../mocha/test')
9
- const { getMachineInfo } = require('./info')
10
- const definitions = require('./definitions')
11
-
12
- module.exports = async function (options) {
1
+ import { getConfig, getTestRoot } from './utils.js'
2
+ import Codecept from '../codecept.js'
3
+ import output from '../output.js'
4
+ import store from '../store.js'
5
+ import Container from '../container.js'
6
+ import figures from 'figures'
7
+ import chalk from 'chalk'
8
+ import { createTest } from '../mocha/test.js'
9
+ import { getMachineInfo } from './info.js'
10
+ import definitions from './definitions.js'
11
+
12
+ export default async function (options) {
13
13
  const configFile = options.config
14
14
 
15
15
  setTimeout(() => {
@@ -31,10 +31,10 @@ module.exports = async function (options) {
31
31
  }
32
32
 
33
33
  const testRoot = getTestRoot(configFile)
34
- let config = getConfig(configFile)
34
+ let config = await getConfig(configFile)
35
35
 
36
36
  try {
37
- config = getConfig(configFile)
37
+ config = await getConfig(configFile)
38
38
  checks['config'] = true
39
39
  } catch (err) {
40
40
  checks['config'] = err
@@ -45,14 +45,14 @@ module.exports = async function (options) {
45
45
  let codecept
46
46
  try {
47
47
  codecept = new Codecept(config, options)
48
- codecept.init(testRoot)
49
- await container.started()
48
+ await codecept.init(testRoot)
49
+ await Container.started()
50
50
  checks.container = true
51
51
  } catch (err) {
52
52
  checks.container = err
53
53
  }
54
54
 
55
- const standardActingHelpers = container.STANDARD_ACTING_HELPERS
55
+ const standardActingHelpers = Container.STANDARD_ACTING_HELPERS
56
56
 
57
57
  printCheck('container', checks['container'])
58
58
 
@@ -70,12 +70,17 @@ module.exports = async function (options) {
70
70
  if (codecept) {
71
71
  try {
72
72
  codecept.loadTests()
73
- const mocha = container.mocha()
74
- mocha.files = codecept.testFiles
73
+ const files = codecept.testFiles
74
+ const mocha = Container.mocha()
75
+ mocha.files = files
75
76
  mocha.loadFiles()
76
- mocha.suite.suites.forEach(suite => {
77
- numTests += suite.tests.length
78
- })
77
+
78
+ for (const suite of mocha.suite.suites) {
79
+ if (suite && suite.tests) {
80
+ numTests += suite.tests.length
81
+ }
82
+ }
83
+
79
84
  if (numTests > 0) {
80
85
  checks.tests = true
81
86
  } else {
@@ -97,13 +102,13 @@ module.exports = async function (options) {
97
102
 
98
103
  store.dryRun = true
99
104
 
100
- const helpers = container.helpers()
105
+ const helpers = Container.helpers()
101
106
 
102
107
  try {
103
108
  if (!Object.keys(helpers).length) throw new Error('No helpers found')
104
109
  // load helpers
105
110
  for (const helper of Object.values(helpers)) {
106
- if (helper._init) helper._init()
111
+ if (helper._init) await helper._init()
107
112
  }
108
113
  checks.helpers = true
109
114
  } catch (err) {
@@ -112,7 +117,7 @@ module.exports = async function (options) {
112
117
 
113
118
  printCheck('helpers', checks['helpers'], `${Object.keys(helpers).join(', ')}`)
114
119
 
115
- const pageObjects = container.support()
120
+ const pageObjects = Container.support()
116
121
 
117
122
  try {
118
123
  if (Object.keys(pageObjects).length) {
@@ -127,10 +132,10 @@ module.exports = async function (options) {
127
132
  printCheck('page objects', checks['pageObjects'], `Total: ${Object.keys(pageObjects).length} support objects`)
128
133
 
129
134
  checks.plugins = true // how to check plugins?
130
- printCheck('plugins', checks['plugins'], Object.keys(container.plugins()).join(', '))
135
+ printCheck('plugins', checks['plugins'], Object.keys(Container.plugins()).join(', '))
131
136
 
132
137
  if (Object.keys(helpers).length) {
133
- const suite = container.mocha().suite
138
+ const suite = Container.mocha().suite
134
139
  const test = createTest('test', () => {})
135
140
  checks.setup = true
136
141
  for (const helper of Object.values(helpers)) {
@@ -1,15 +1,16 @@
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 util = require('util')
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 util from 'util'
7
7
 
8
- const { print, success, error } = require('../output')
9
- const { fileExists } = require('../utils')
10
- const { getTestRoot } = require('./utils')
8
+ import output from '../output.js'
9
+ const { print, success, error } = output
10
+ import { fileExists } from '../utils.js'
11
+ import { getTestRoot } from './utils.js'
11
12
 
12
- module.exports = function (initPath) {
13
+ export default function (initPath) {
13
14
  const testsPath = getTestRoot(initPath)
14
15
 
15
16
  print()
@@ -1,10 +1,10 @@
1
- const fs = require('fs')
2
- const path = require('path')
1
+ import fs from 'fs'
2
+ import path from 'path'
3
3
 
4
- const { getConfig, getTestRoot } = require('./utils')
5
- const Codecept = require('../codecept')
6
- const container = require('../container')
7
- const output = require('../output')
4
+ import { getConfig, getTestRoot } from './utils.js'
5
+ import Codecept from '../codecept.js'
6
+ import container from '../container.js'
7
+ import output from '../output.js'
8
8
  const actingHelpers = [...container.STANDARD_ACTING_HELPERS, 'REST']
9
9
 
10
10
  /**
@@ -86,11 +86,11 @@ const helperNames = []
86
86
  /** @type {Array<string>} */
87
87
  const customHelpers = []
88
88
 
89
- module.exports = function (genPath, options) {
89
+ export default async function (genPath, options) {
90
90
  const configFile = options.config || genPath
91
91
  /** @type {string} */
92
92
  const testsPath = getTestRoot(configFile)
93
- const config = getConfig(configFile)
93
+ const config = await getConfig(configFile)
94
94
  if (!config) return
95
95
 
96
96
  /** @type {Object<string, string>} */
@@ -106,7 +106,8 @@ module.exports = function (genPath, options) {
106
106
  const targetFolderPath = (options.output && getTestRoot(options.output)) || testsPath
107
107
 
108
108
  const codecept = new Codecept(config, {})
109
- codecept.init(testsPath)
109
+ await codecept.init(testsPath)
110
+ await container.started()
110
111
 
111
112
  const helpers = container.helpers()
112
113
  const translations = container.translation()
@@ -229,7 +230,12 @@ function getImportString(testsPath, targetFolderPath, pathsToType, pathsToValue)
229
230
 
230
231
  for (const name in pathsToType) {
231
232
  const relativePath = getPath(pathsToType[name], targetFolderPath, testsPath)
232
- importStrings.push(`type ${name} = typeof import('${relativePath}');`)
233
+ // For ESM modules with default exports, we need to access the default export type
234
+ if (relativePath.endsWith('.js')) {
235
+ importStrings.push(`type ${name} = typeof import('${relativePath}')['default'];`)
236
+ } else {
237
+ importStrings.push(`type ${name} = typeof import('${relativePath}');`)
238
+ }
233
239
  }
234
240
 
235
241
  for (const name in pathsToValue) {
@@ -1,18 +1,18 @@
1
- const { getConfig, getTestRoot } = require('./utils')
2
- const Config = require('../config')
3
- const Codecept = require('../codecept')
4
- const output = require('../output')
5
- const event = require('../event')
6
- const store = require('../store')
7
- const Container = require('../container')
8
-
9
- module.exports = async function (test, options) {
1
+ import { getConfig, getTestRoot } from './utils.js'
2
+ import Config from '../config.js'
3
+ import Codecept from '../codecept.js'
4
+ import output from '../output.js'
5
+ import event from '../event.js'
6
+ import store from '../store.js'
7
+ import Container from '../container.js'
8
+
9
+ export default async function (test, options) {
10
10
  if (options.grep) process.env.grep = options.grep
11
11
  const configFile = options.config
12
12
  let codecept
13
13
 
14
14
  const testRoot = getTestRoot(configFile)
15
- let config = getConfig(configFile)
15
+ let config = await getConfig(configFile)
16
16
  if (options.override) {
17
17
  config = Config.append(JSON.parse(options.override))
18
18
  }
@@ -27,7 +27,7 @@ module.exports = async function (test, options) {
27
27
 
28
28
  try {
29
29
  codecept = new Codecept(config, options)
30
- codecept.init(testRoot)
30
+ await codecept.init(testRoot)
31
31
 
32
32
  if (options.bootstrap) await codecept.bootstrap()
33
33
 
@@ -35,20 +35,20 @@ module.exports = async function (test, options) {
35
35
  store.dryRun = true
36
36
 
37
37
  if (!options.steps && !options.verbose && !options.debug) {
38
- printTests(codecept.testFiles)
38
+ await printTests(codecept.testFiles)
39
39
  return
40
40
  }
41
41
  event.dispatcher.on(event.all.result, printFooter)
42
- codecept.run(test)
42
+ await codecept.run(test)
43
43
  } catch (err) {
44
44
  console.error(err)
45
45
  process.exit(1)
46
46
  }
47
47
  }
48
48
 
49
- function printTests(files) {
50
- const figures = require('figures')
51
- const colors = require('chalk')
49
+ async function printTests(files) {
50
+ const { default: figures } = await import('figures')
51
+ const { default: colors } = await import('chalk')
52
52
 
53
53
  output.print(output.styles.debug(`Tests from ${global.codecept_dir}:`))
54
54
  output.print()
@@ -1,12 +1,12 @@
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 { fileExists, ucfirst, lcfirst, beautify } = require('../utils')
7
- const output = require('../output')
8
- const generateDefinitions = require('./definitions')
9
- const { getConfig, getTestRoot, safeFileWrite, readConfig } = require('./utils')
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 { fileExists, ucfirst, lcfirst, beautify } from '../utils.js'
7
+ import output from '../output.js'
8
+ import generateDefinitions from './definitions.js'
9
+ import { getConfig, getTestRoot, safeFileWrite, readConfig } from './utils.js'
10
10
 
11
11
  let extension = 'js'
12
12
 
@@ -18,10 +18,10 @@ Scenario('test something', async ({ {{actor}} }) => {
18
18
  `
19
19
 
20
20
  // generates empty test
21
- module.exports.test = function (genPath) {
21
+ export async function test(genPath) {
22
22
  const testsPath = getTestRoot(genPath)
23
23
  global.codecept_dir = testsPath
24
- const config = getConfig(testsPath)
24
+ const config = await getConfig(testsPath)
25
25
  if (!config) return
26
26
 
27
27
  output.print('Creating a new test...')
@@ -46,7 +46,7 @@ module.exports.test = function (genPath) {
46
46
  },
47
47
  },
48
48
  ])
49
- .then(result => {
49
+ .then(async result => {
50
50
  const testFilePath = path.dirname(path.join(testsPath, config.tests)).replace(/\*\*$/, '')
51
51
  let testFile = path.join(testFilePath, result.filename)
52
52
  const ext = path.extname(testFile)
@@ -55,8 +55,9 @@ module.exports.test = function (genPath) {
55
55
  if (!fileExists(dir)) mkdirp.sync(dir)
56
56
  let testContent = testTemplate.replace('{{feature}}', result.feature)
57
57
 
58
- const container = require('../container')
59
- container.create(config, {})
58
+ const containerModule = await import('../container.js')
59
+ const container = containerModule.default || containerModule
60
+ await container.create(config, {})
60
61
  // translate scenario test
61
62
  if (container.translation().loaded) {
62
63
  const vocabulary = container.translation().vocabulary
@@ -76,7 +77,7 @@ module.exports.test = function (genPath) {
76
77
 
77
78
  const pageObjectTemplate = `const { I } = inject();
78
79
 
79
- module.exports = {
80
+ export default {
80
81
 
81
82
  // insert your locators and methods here
82
83
  }
@@ -101,13 +102,13 @@ class {{name}} {
101
102
  }
102
103
 
103
104
  // For inheritance
104
- module.exports = new {{name}}();
105
- export = {{name}};
105
+ export default new {{name}}();
106
+ export { {{name}} };
106
107
  `
107
108
 
108
- module.exports.pageObject = function (genPath, opts) {
109
+ export async function pageObject(genPath, opts) {
109
110
  const testsPath = getTestRoot(genPath)
110
- const config = getConfig(testsPath)
111
+ const config = await getConfig(testsPath)
111
112
  const kind = opts.T || 'page'
112
113
  if (!config) return
113
114
 
@@ -155,7 +156,7 @@ module.exports.pageObject = function (genPath, opts) {
155
156
  // relative path
156
157
  actorPath = path.relative(dir, path.dirname(path.join(testsPath, actorPath))) + actorPath.substring(1) // get an upper level
157
158
  }
158
- actor = `require('${actorPath}')`
159
+ actor = `import('${actorPath}')`
159
160
  }
160
161
 
161
162
  const name = lcfirst(result.name) + ucfirst(kind)
@@ -197,7 +198,7 @@ module.exports.pageObject = function (genPath, opts) {
197
198
  })
198
199
  }
199
200
 
200
- const helperTemplate = `const Helper = require('@codeceptjs/helper');
201
+ const helperTemplate = `import Helper from '@codeceptjs/helper';
201
202
 
202
203
  class {{name}} extends Helper {
203
204
 
@@ -222,10 +223,10 @@ class {{name}} extends Helper {
222
223
 
223
224
  }
224
225
 
225
- module.exports = {{name}};
226
+ export default {{name}};
226
227
  `
227
228
 
228
- module.exports.helper = function (genPath) {
229
+ export async function helper(genPath) {
229
230
  const testsPath = getTestRoot(genPath)
230
231
 
231
232
  output.print('Creating a new helper')
@@ -265,9 +266,11 @@ helpers: {
265
266
  })
266
267
  }
267
268
 
269
+ import { fileURLToPath } from 'url'
270
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
268
271
  const healTemplate = fs.readFileSync(path.join(__dirname, '../template/heal.js'), 'utf8').toString()
269
272
 
270
- module.exports.heal = function (genPath) {
273
+ export async function heal(genPath) {
271
274
  const testsPath = getTestRoot(genPath)
272
275
 
273
276
  let configFile = path.join(testsPath, `codecept.conf.${extension}`)
@@ -282,10 +285,10 @@ module.exports.heal = function (genPath) {
282
285
  output.print('Require this file in the config file and enable heal plugin:')
283
286
  output.print('--------------------------')
284
287
  output.print(`
285
- require('./heal')
288
+ import './heal.js'
286
289
 
287
- exports.config = {
288
- // ...
290
+ export const config = {
291
+ // ...
289
292
  plugins: {
290
293
  heal: {
291
294
  enabled: true
@@ -298,3 +301,35 @@ exports.config = {
298
301
  if (!safeFileWrite(healFile, healTemplate)) return
299
302
  output.success(`Heal recipes were created in ${healFile}`)
300
303
  }
304
+
305
+ export async function prompt(promptName, genPath) {
306
+ if (!promptName) {
307
+ output.error('Please specify prompt name: writeStep, healStep, or generatePageObject')
308
+ output.print('Usage: npx codeceptjs generate:prompt <promptName>')
309
+ return
310
+ }
311
+
312
+ const validPrompts = ['writeStep', 'healStep', 'generatePageObject']
313
+ if (!validPrompts.includes(promptName)) {
314
+ output.error(`Invalid prompt name: ${promptName}`)
315
+ output.print(`Valid prompts: ${validPrompts.join(', ')}`)
316
+ return
317
+ }
318
+
319
+ const testsPath = getTestRoot(genPath)
320
+
321
+ const promptsDir = path.join(testsPath, 'prompts')
322
+ if (!fileExists(promptsDir)) {
323
+ mkdirp.sync(promptsDir)
324
+ }
325
+
326
+ const templatePath = path.join(__dirname, `../template/prompts/${promptName}.js`)
327
+ const promptContent = fs.readFileSync(templatePath, 'utf8')
328
+
329
+ const promptFile = path.join(promptsDir, `${promptName}.${extension}`)
330
+ if (!safeFileWrite(promptFile, promptContent)) return
331
+
332
+ output.success(`Prompt ${promptName} was created in ${promptFile}`)
333
+ output.print('Customize this prompt to fit your needs.')
334
+ output.print('This prompt will be automatically loaded when AI features are enabled.')
335
+ }
@@ -1,11 +1,9 @@
1
- const path = require('path');
2
- const mkdirp = require('mkdirp');
1
+ import path from 'path'
2
+ import { mkdirp } from 'mkdirp'
3
3
 
4
- const output = require('../../output');
5
- const { fileExists } = require('../../utils');
6
- const {
7
- getConfig, getTestRoot, updateConfig, safeFileWrite, findConfigFile,
8
- } = require('../utils');
4
+ import output from '../../output.js'
5
+ import { fileExists } from '../../utils.js'
6
+ import { getConfig, getTestRoot, updateConfig, safeFileWrite, findConfigFile } from '../utils.js'
9
7
 
10
8
  const featureFile = `Feature: Business rules
11
9
  In order to achieve my goals
@@ -14,7 +12,7 @@ const featureFile = `Feature: Business rules
14
12
 
15
13
  Scenario: do something
16
14
  Given I have a defined step
17
- `;
15
+ `
18
16
 
19
17
  const stepsFile = `const { I } = inject();
20
18
  // Add in your custom step files
@@ -22,60 +20,60 @@ const stepsFile = `const { I } = inject();
22
20
  Given('I have a defined step', () => {
23
21
  // TODO: replace with your own step
24
22
  });
25
- `;
23
+ `
26
24
 
27
- module.exports = function (genPath) {
28
- const testsPath = getTestRoot(genPath);
29
- const configFile = findConfigFile(testsPath);
25
+ export default async function (genPath) {
26
+ const testsPath = getTestRoot(genPath)
27
+ const configFile = findConfigFile(testsPath)
30
28
 
31
29
  if (!configFile) {
32
- output.error(
33
- "Can't initialize Gherkin. This command must be run in an already initialized project.",
34
- );
35
- process.exit(1);
30
+ output.error("Can't initialize Gherkin. This command must be run in an already initialized project.")
31
+ process.exit(1)
36
32
  }
37
33
 
38
- const config = getConfig(testsPath);
39
- const extension = path.extname(configFile).substring(1);
34
+ const config = await getConfig(testsPath)
35
+ const extension = path.extname(configFile).substring(1)
40
36
 
41
- output.print('Initializing Gherkin (Cucumber BDD) for CodeceptJS');
42
- output.print('--------------------------');
37
+ output.print('Initializing Gherkin (Cucumber BDD) for CodeceptJS')
38
+ output.print('--------------------------')
43
39
 
44
40
  if (config.gherkin && config.gherkin.steps) {
45
- output.error('Gherkin is already initialized in this project. See `gherkin` section in the config');
46
- process.exit(1);
41
+ output.error('Gherkin is already initialized in this project. See `gherkin` section in the config')
42
+ process.exit(1)
47
43
  }
48
44
 
49
- let dir;
50
- dir = path.join(testsPath, 'features');
45
+ let dir
46
+ dir = path.join(testsPath, 'features')
51
47
  if (!fileExists(dir)) {
52
- mkdirp.sync(dir);
53
- output.success(`Created ${dir}, place your *.feature files in it`);
48
+ mkdirp.sync(dir)
49
+ // Use relative path for output
50
+ const relativeDir = path.relative(process.cwd(), dir)
51
+ output.success(`Created ${relativeDir}, place your *.feature files in it`)
54
52
  }
55
53
 
56
54
  if (safeFileWrite(path.join(dir, 'basic.feature'), featureFile)) {
57
- output.success('Created sample feature file: features/basic.feature');
55
+ output.success('Created sample feature file: features/basic.feature')
58
56
  }
59
57
 
60
- dir = path.join(testsPath, 'step_definitions');
58
+ dir = path.join(testsPath, 'step_definitions')
61
59
  if (!fileExists(dir)) {
62
- mkdirp.sync(dir);
63
- output.success(`Created ${dir}, place step definitions into it`);
60
+ mkdirp.sync(dir)
61
+ // Use relative path for output
62
+ const relativeDir = path.relative(process.cwd(), dir)
63
+ output.success(`Created ${relativeDir}, place step definitions into it`)
64
64
  }
65
65
 
66
66
  if (safeFileWrite(path.join(dir, `steps.${extension}`), stepsFile)) {
67
- output.success(
68
- `Created sample steps file: step_definitions/steps.${extension}`,
69
- );
67
+ output.success(`Created sample steps file: step_definitions/steps.${extension}`)
70
68
  }
71
69
 
72
70
  config.gherkin = {
73
71
  features: './features/*.feature',
74
72
  steps: [`./step_definitions/steps.${extension}`],
75
- };
73
+ }
76
74
 
77
- updateConfig(testsPath, config, extension);
75
+ updateConfig(testsPath, config, extension)
78
76
 
79
- output.success('Gherkin setup is done.');
80
- output.success('Start writing feature files and implement corresponding steps.');
81
- };
77
+ output.success('Gherkin setup is done.')
78
+ output.success('Start writing feature files and implement corresponding steps.')
79
+ }
@@ -1,29 +1,29 @@
1
- const escapeStringRegexp = require('escape-string-regexp')
2
- const fs = require('fs')
3
- const Gherkin = require('@cucumber/gherkin')
4
- const Messages = require('@cucumber/messages')
5
- const { globSync } = require('glob')
6
- const fsPath = require('path')
1
+ import escapeStringRegexp from 'escape-string-regexp'
2
+ import fs from 'fs'
3
+ import Gherkin from '@cucumber/gherkin'
4
+ import { IdGenerator } from '@cucumber/messages'
5
+ import { globSync } from 'glob'
6
+ import fsPath from 'path'
7
7
 
8
- const { getConfig, getTestRoot } = require('../utils')
9
- const Codecept = require('../../codecept')
10
- const output = require('../../output')
11
- const { matchStep } = require('../../mocha/bdd')
8
+ import { getConfig, getTestRoot } from '../utils.js'
9
+ import Codecept from '../../codecept.js'
10
+ import output from '../../output.js'
11
+ import { matchStep } from '../../mocha/bdd.js'
12
12
 
13
- const uuidFn = Messages.IdGenerator.uuid()
13
+ const uuidFn = IdGenerator.uuid()
14
14
  const builder = new Gherkin.AstBuilder(uuidFn)
15
15
  const matcher = new Gherkin.GherkinClassicTokenMatcher()
16
16
  const parser = new Gherkin.Parser(builder, matcher)
17
17
  parser.stopAtFirstError = false
18
18
 
19
- module.exports = function (genPath, options) {
19
+ export default async function (genPath, options) {
20
20
  const configFile = options.config || genPath
21
21
  const testsPath = getTestRoot(configFile)
22
- const config = getConfig(configFile)
22
+ const config = await getConfig(configFile)
23
23
  if (!config) return
24
24
 
25
25
  const codecept = new Codecept(config, {})
26
- codecept.init(testsPath)
26
+ await codecept.init(testsPath)
27
27
 
28
28
  if (!config.gherkin) {
29
29
  output.error('Gherkin is not enabled in config. Run `codecept gherkin:init` to enable it')
@@ -1,25 +1,28 @@
1
- const { getConfig, getTestRoot } = require('../utils');
2
- const Codecept = require('../../codecept');
3
- const output = require('../../output');
4
- const { getSteps } = require('../../mocha/bdd');
1
+ import { getConfig, getTestRoot } from '../utils.js'
2
+ import Codecept from '../../codecept.js'
3
+ import output from '../../output.js'
4
+ import { getSteps, clearSteps } from '../../mocha/bdd.js'
5
5
 
6
- module.exports = function (genPath, options) {
7
- const configFile = options.config || genPath;
8
- const testsPath = getTestRoot(configFile);
9
- const config = getConfig(configFile);
10
- if (!config) return;
6
+ export default async function (genPath, options) {
7
+ const configFile = options.config || genPath
8
+ const testsPath = getTestRoot(configFile)
9
+ const config = await getConfig(configFile)
10
+ if (!config) return
11
11
 
12
- const codecept = new Codecept(config, {});
13
- codecept.init(testsPath);
12
+ // Clear any previously loaded steps
13
+ clearSteps()
14
+
15
+ const codecept = new Codecept(config, {})
16
+ await codecept.init(testsPath)
14
17
 
15
- output.print('Gherkin Step Definitions:');
16
- output.print();
17
- const steps = getSteps();
18
+ output.print('Gherkin Step Definitions:')
19
+ output.print()
20
+ const steps = getSteps()
18
21
  for (const step of Object.keys(steps)) {
19
- output.print(` ${output.colors.bold(step)} ${output.colors.green(steps[step].line || '')}`);
22
+ output.print(` ${output.colors.bold(step)} ${output.colors.green(steps[step].line || '')}`)
20
23
  }
21
- output.print();
24
+ output.print()
22
25
  if (!Object.keys(steps).length) {
23
- output.error('No Gherkin steps defined');
26
+ output.error('No Gherkin steps defined')
24
27
  }
25
- };
28
+ }