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,9 +1,10 @@
1
- const { isGenerator } = require('../utils')
2
- const DataTable = require('./table')
3
- const DataScenarioConfig = require('./dataScenarioConfig')
4
- const Secret = require('../secret')
1
+ import { isGenerator } from '../utils.js'
2
+ import DataTable from './table.js'
3
+ import DataScenarioConfig from './dataScenarioConfig.js'
4
+ import secretModule from '../secret.js'
5
+ const Secret = secretModule.default || secretModule
5
6
 
6
- module.exports = function (context) {
7
+ export default function (context) {
7
8
  context.Data = function (dataTable) {
8
9
  const data = detectDataType(dataTable)
9
10
  return {
@@ -81,4 +81,4 @@ class DataScenarioConfig {
81
81
  }
82
82
  }
83
83
 
84
- module.exports = DataScenarioConfig
84
+ export default DataScenarioConfig
@@ -63,4 +63,4 @@ class DataTableArgument {
63
63
  }
64
64
  }
65
65
 
66
- module.exports = DataTableArgument
66
+ export default DataTableArgument
package/lib/data/table.js CHANGED
@@ -40,4 +40,4 @@ class DataTable {
40
40
  }
41
41
  }
42
42
 
43
- module.exports = DataTable
43
+ export default DataTable
package/lib/effects.js CHANGED
@@ -1,8 +1,89 @@
1
- const recorder = require('./recorder')
2
- const { debug } = require('./output')
3
- const store = require('./store')
4
- const event = require('./event')
5
- const within = require('./within')
1
+ import recorder from './recorder.js'
2
+ import output from './output.js'
3
+ import store from './store.js'
4
+ import event from './event.js'
5
+ import container from './container.js'
6
+ import MetaStep from './step/meta.js'
7
+ import { isAsyncFunction } from './utils.js'
8
+
9
+ /**
10
+ * @param {CodeceptJS.LocatorOrString} context
11
+ * @param {Function} fn
12
+ * @return {Promise<*> | undefined}
13
+ */
14
+ function within(context, fn) {
15
+ const helpers = store.dryRun ? {} : container.helpers()
16
+ const locator = typeof context === 'object' ? JSON.stringify(context) : context
17
+
18
+ return recorder.add(
19
+ 'register within wrapper',
20
+ () => {
21
+ const metaStep = new WithinStep(locator, fn)
22
+ const defineMetaStep = step => (step.metaStep = metaStep)
23
+ recorder.session.start('within')
24
+
25
+ event.dispatcher.prependListener(event.step.before, defineMetaStep)
26
+
27
+ Object.keys(helpers).forEach(helper => {
28
+ if (helpers[helper]._withinBegin) recorder.add(`[${helper}] start within`, () => helpers[helper]._withinBegin(context))
29
+ })
30
+
31
+ const finalize = () => {
32
+ event.dispatcher.removeListener(event.step.before, defineMetaStep)
33
+ recorder.add('Finalize session within session', () => {
34
+ output.stepShift = 1
35
+ recorder.session.restore('within')
36
+ })
37
+ }
38
+ const finishHelpers = () => {
39
+ Object.keys(helpers).forEach(helper => {
40
+ if (helpers[helper]._withinEnd) recorder.add(`[${helper}] finish within`, () => helpers[helper]._withinEnd())
41
+ })
42
+ }
43
+
44
+ if (isAsyncFunction(fn)) {
45
+ return fn()
46
+ .then(res => {
47
+ finishHelpers()
48
+ finalize()
49
+ return recorder.promise().then(() => res)
50
+ })
51
+ .catch(e => {
52
+ finalize()
53
+ recorder.throw(e)
54
+ })
55
+ }
56
+
57
+ let res
58
+ try {
59
+ res = fn()
60
+ } catch (err) {
61
+ recorder.throw(err)
62
+ } finally {
63
+ finishHelpers()
64
+ recorder.catch(err => {
65
+ output.stepShift = 1
66
+ throw err
67
+ })
68
+ }
69
+ finalize()
70
+ return recorder.promise().then(() => res)
71
+ },
72
+ false,
73
+ false,
74
+ )
75
+ }
76
+
77
+ class WithinStep extends MetaStep {
78
+ constructor(locator, fn) {
79
+ super('Within')
80
+ this.args = [locator]
81
+ }
82
+
83
+ toString() {
84
+ return `${this.prefix}Within ${this.humanizeArgs()}${this.suffix}`
85
+ }
86
+ }
6
87
 
7
88
  /**
8
89
  * A utility function for CodeceptJS tests that acts as a soft assertion.
@@ -49,8 +130,9 @@ async function hopeThat(callback) {
49
130
  recorder.session.catch(err => {
50
131
  result = false
51
132
  const msg = err.inspect ? err.inspect() : err.toString()
52
- debug(`Unsuccessful assertion > ${msg}`)
133
+ output.debug(`Unsuccessful assertion > ${msg}`)
53
134
  event.dispatcher.once(event.test.finished, test => {
135
+ if (!test.notes) test.notes = []
54
136
  test.notes.push({ type: 'conditionalError', text: msg })
55
137
  })
56
138
  recorder.session.restore(sessionName)
@@ -130,7 +212,7 @@ async function retryTo(callback, maxTries, pollInterval = 200) {
130
212
  recorder.session.catch(err => {
131
213
  recorder.session.restore(`${sessionName} ${tries}`)
132
214
  if (tries <= maxTries) {
133
- debug(`Error ${err}... Retrying`)
215
+ output.debug(`Error ${err}... Retrying`)
134
216
  recorder.add(`${sessionName} ${tries}`, () => setTimeout(tryBlock, pollInterval))
135
217
  } else {
136
218
  // if maxTries reached
@@ -185,7 +267,7 @@ async function tryTo(callback) {
185
267
  () => {
186
268
  recorder.session.start(sessionName)
187
269
  isAutoRetriesEnabled = store.autoRetries
188
- if (isAutoRetriesEnabled) debug('Auto retries disabled inside tryTo effect')
270
+ if (isAutoRetriesEnabled) output.debug('Auto retries disabled inside tryTo effect')
189
271
  store.autoRetries = false
190
272
  callback()
191
273
  recorder.add(() => {
@@ -196,7 +278,7 @@ async function tryTo(callback) {
196
278
  recorder.session.catch(err => {
197
279
  result = false
198
280
  const msg = err.inspect ? err.inspect() : err.toString()
199
- debug(`Unsuccessful try > ${msg}`)
281
+ output.debug(`Unsuccessful try > ${msg}`)
200
282
  recorder.session.restore(sessionName)
201
283
  return result
202
284
  })
@@ -215,7 +297,9 @@ async function tryTo(callback) {
215
297
  )
216
298
  }
217
299
 
218
- module.exports = {
300
+ export { hopeThat, retryTo, tryTo, within }
301
+
302
+ export default {
219
303
  hopeThat,
220
304
  retryTo,
221
305
  tryTo,
@@ -1,4 +1,4 @@
1
- const assert = require('assert')
1
+ import assert from 'assert'
2
2
 
3
3
  /**
4
4
  * Unified WebElement class that wraps native element instances from different helpers
@@ -324,4 +324,4 @@ class WebElement {
324
324
  }
325
325
  }
326
326
 
327
- module.exports = WebElement
327
+ export default WebElement
package/lib/els.js CHANGED
@@ -1,11 +1,11 @@
1
- const output = require('./output')
2
- const store = require('./store')
3
- const container = require('./container')
4
- const StepConfig = require('./step/config')
5
- const recordStep = require('./step/record')
6
- const FuncStep = require('./step/func')
7
- const { truth } = require('./assert/truth')
8
- const { isAsyncFunction, humanizeFunction } = require('./utils')
1
+ import output from './output.js'
2
+ import store from './store.js'
3
+ import container from './container.js'
4
+ import StepConfig from './step/config.js'
5
+ import recordStep from './step/record.js'
6
+ import FuncStep from './step/func.js'
7
+ import { truth } from './assert/truth.js'
8
+ import { isAsyncFunction, humanizeFunction } from './utils.js'
9
9
 
10
10
  function element(purpose, locator, fn) {
11
11
  let stepConfig
@@ -121,7 +121,9 @@ function expectAllElements(locator, fn) {
121
121
  })
122
122
  }
123
123
 
124
- module.exports = {
124
+ export { element, eachElement, expectElement, expectAnyElement, expectAllElements }
125
+
126
+ export default {
125
127
  element,
126
128
  eachElement,
127
129
  expectElement,
package/lib/event.js CHANGED
@@ -1,6 +1,7 @@
1
- const debug = require('debug')('codeceptjs:event')
2
- const events = require('events')
3
- const { error } = require('./output')
1
+ import debugModule from 'debug'
2
+ const debug = debugModule('codeceptjs:event')
3
+ import events from 'events'
4
+ import output from './output.js'
4
5
 
5
6
  const MAX_LISTENERS = 200
6
7
 
@@ -18,7 +19,7 @@ if (typeof process.setMaxListeners === 'function') {
18
19
  * @alias event
19
20
  */
20
21
 
21
- module.exports = {
22
+ export default {
22
23
  /**
23
24
  * @type {NodeJS.EventEmitter}
24
25
  * @constant
@@ -161,25 +162,25 @@ module.exports = {
161
162
  try {
162
163
  this.dispatcher.emit.apply(this.dispatcher, arguments)
163
164
  } catch (err) {
164
- error(`Error processing ${event} event:`)
165
- error(err.stack)
165
+ output.error(`Error processing ${event} event:`)
166
+ output.error(err.stack)
166
167
  }
167
168
  },
168
169
 
169
170
  /** for testing only! */
170
- cleanDispatcher: () => {
171
+ cleanDispatcher() {
171
172
  let event
172
173
  for (event in this.test) {
173
174
  this.dispatcher.removeAllListeners(this.test[event])
174
175
  }
175
176
  for (event in this.suite) {
176
- this.dispatcher.removeAllListeners(this.test[event])
177
+ this.dispatcher.removeAllListeners(this.suite[event])
177
178
  }
178
179
  for (event in this.step) {
179
- this.dispatcher.removeAllListeners(this.test[event])
180
+ this.dispatcher.removeAllListeners(this.step[event])
180
181
  }
181
182
  for (event in this.all) {
182
- this.dispatcher.removeAllListeners(this.test[event])
183
+ this.dispatcher.removeAllListeners(this.all[event])
183
184
  }
184
185
  },
185
186
  }
package/lib/globals.js ADDED
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Global variables initialization module
3
+ *
4
+ * Centralizes all global variable setup for CodeceptJS from codecept.js and mocha/ui.js
5
+ */
6
+
7
+ import fsPath from 'path'
8
+ import ActorFactory from './actor.js'
9
+ import output from './output.js'
10
+ import locator from './locator.js'
11
+
12
+ /**
13
+ * Initialize CodeceptJS core globals
14
+ * Called from Codecept.initGlobals()
15
+ */
16
+ export async function initCodeceptGlobals(dir, config, container) {
17
+ global.codecept_dir = dir
18
+ global.output_dir = fsPath.resolve(dir, config.output)
19
+
20
+ if (config.noGlobals) return;
21
+ // Set up actor global - will use container when available
22
+ global.actor = global.codecept_actor = (obj) => {
23
+ return ActorFactory(obj, global.container || container)
24
+ }
25
+ global.Actor = global.actor
26
+
27
+ // Use dynamic imports for modules to avoid circular dependencies
28
+ global.pause = async (...args) => {
29
+ const pauseModule = await import('./pause.js')
30
+ return (pauseModule.default || pauseModule)(...args)
31
+ }
32
+
33
+ global.within = async (...args) => {
34
+ return (await import('./effects.js')).within(...args)
35
+ }
36
+
37
+ global.session = async (...args) => {
38
+ const sessionModule = await import('./session.js')
39
+ return (sessionModule.default || sessionModule)(...args)
40
+ }
41
+
42
+ const dataTableModule = await import('./data/table.js')
43
+ global.DataTable = dataTableModule.default || dataTableModule
44
+
45
+ global.locate = locatorQuery => {
46
+ return locator.build(locatorQuery)
47
+ }
48
+
49
+ global.inject = () => container.support()
50
+ global.share = container.share
51
+
52
+ const secretModule = await import('./secret.js')
53
+ global.secret = secretModule.secret || (secretModule.default && secretModule.default.secret)
54
+
55
+ global.codecept_debug = output.debug
56
+
57
+ const codeceptjsModule = await import('./index.js') // load all objects
58
+ global.codeceptjs = codeceptjsModule.default || codeceptjsModule
59
+
60
+ // BDD step definitions
61
+ const stepDefinitionsModule = await import('./mocha/bdd.js')
62
+ const stepDefinitions = stepDefinitionsModule.default || stepDefinitionsModule
63
+ global.Given = stepDefinitions.Given
64
+ global.When = stepDefinitions.When
65
+ global.Then = stepDefinitions.Then
66
+ global.DefineParameterType = stepDefinitions.defineParameterType
67
+
68
+ // debug mode
69
+ global.debugMode = false
70
+
71
+ // mask sensitive data
72
+ global.maskSensitiveData = config.maskSensitiveData || false
73
+
74
+ }
75
+
76
+ /**
77
+ * Initialize Mocha test framework globals (Feature, Scenario, etc.)
78
+ * Called from mocha/ui.js pre-require event
79
+ */
80
+ export function initMochaGlobals(context) {
81
+ // Mocha test framework globals
82
+ global.BeforeAll = context.BeforeAll
83
+ global.AfterAll = context.AfterAll
84
+ global.Feature = context.Feature
85
+ global.xFeature = context.xFeature
86
+ global.BeforeSuite = context.BeforeSuite
87
+ global.AfterSuite = context.AfterSuite
88
+ global.Background = context.Background
89
+ global.Before = context.Before
90
+ global.After = context.After
91
+ global.Scenario = context.Scenario
92
+ global.xScenario = context.xScenario
93
+ }
94
+
95
+ /**
96
+ * Clear all CodeceptJS globals (useful for testing/cleanup)
97
+ */
98
+ export function clearGlobals() {
99
+ getGlobalNames().forEach(name => delete global[name]);
100
+ }
101
+
102
+ /**
103
+ * Get list of all CodeceptJS global variable names
104
+ */
105
+ export function getGlobalNames() {
106
+ return [
107
+ 'codecept_dir',
108
+ 'output_dir',
109
+ 'actor',
110
+ 'codecept_actor',
111
+ 'Actor',
112
+ 'pause',
113
+ 'within',
114
+ 'session',
115
+ 'DataTable',
116
+ 'locate',
117
+ 'inject',
118
+ 'share',
119
+ 'secret',
120
+ 'codecept_debug',
121
+ 'codeceptjs',
122
+ 'Given',
123
+ 'When',
124
+ 'Then',
125
+ 'DefineParameterType',
126
+ 'debugMode',
127
+ 'maskSensitiveData',
128
+ 'BeforeAll',
129
+ 'AfterAll',
130
+ 'Feature',
131
+ 'xFeature',
132
+ 'BeforeSuite',
133
+ 'AfterSuite',
134
+ 'Background',
135
+ 'Before',
136
+ 'After',
137
+ 'Scenario',
138
+ 'xScenario',
139
+ 'container'
140
+ ]
141
+ }
package/lib/heal.js CHANGED
@@ -1,9 +1,9 @@
1
- const debug = require('debug')('codeceptjs:heal')
2
- const colors = require('chalk')
3
- const Container = require('./container')
4
- const recorder = require('./recorder')
5
- const output = require('./output')
6
- const event = require('./event')
1
+ import debugModule from 'debug'
2
+ const debug = debugModule('codeceptjs:heal')
3
+ import colors from 'chalk'
4
+ import recorder from './recorder.js'
5
+ import output from './output.js'
6
+ import event from './event.js'
7
7
 
8
8
  /**
9
9
  * @class
@@ -69,7 +69,7 @@ class Heal {
69
69
  if (!prepareFn) continue
70
70
 
71
71
  if (context[property]) continue
72
- context[property] = await prepareFn(Container.support())
72
+ context[property] = await prepareFn(global.inject())
73
73
  }
74
74
 
75
75
  output.level(currentOutputLevel)
@@ -116,10 +116,10 @@ class Heal {
116
116
  })
117
117
 
118
118
  if (typeof codeSnippet === 'string') {
119
- const I = Container.support('I')
119
+ const I = global.container.support('I')
120
120
  await eval(codeSnippet)
121
121
  } else if (typeof codeSnippet === 'function') {
122
- await codeSnippet(Container.support())
122
+ await codeSnippet(global.container.support())
123
123
  }
124
124
 
125
125
  this.fixes.push({
@@ -155,14 +155,14 @@ class Heal {
155
155
  recorder.throw(error)
156
156
  }
157
157
 
158
- static setDefaultHealers() {
159
- require('./template/heal')
158
+ static async setDefaultHealers() {
159
+ await import('./template/heal.js')
160
160
  }
161
161
  }
162
162
 
163
163
  const heal = new Heal()
164
164
 
165
- module.exports = heal
165
+ export default heal
166
166
 
167
167
  function matchRecipes(recipes, contextName) {
168
168
  return Object.entries(recipes)
package/lib/helper/AI.js CHANGED
@@ -1,13 +1,13 @@
1
- const Helper = require('@codeceptjs/helper')
2
- const ora = require('ora-classic')
3
- const fs = require('fs')
4
- const path = require('path')
5
- const ai = require('../ai')
6
- const Container = require('../container')
7
- const { splitByChunks, minifyHtml } = require('../html')
8
- const { beautify } = require('../utils')
9
- const output = require('../output')
10
- const { registerVariable } = require('../pause')
1
+ import HelperModule from '@codeceptjs/helper'
2
+ import ora from 'ora-classic'
3
+ import fs from 'fs'
4
+ import path from 'path'
5
+ import ai from '../ai.js'
6
+ import Container from '../container.js'
7
+ import { splitByChunks, minifyHtml } from '../html.js'
8
+ import { beautify } from '../utils.js'
9
+ import output from '../output.js'
10
+ import { registerVariable } from '../pause.js'
11
11
 
12
12
  const standardActingHelpers = Container.STANDARD_ACTING_HELPERS
13
13
 
@@ -211,4 +211,4 @@ class AI extends Helper {
211
211
  }
212
212
  }
213
213
 
214
- module.exports = AI
214
+ export default AI
@@ -1,7 +1,6 @@
1
- const path = require('path')
2
-
3
- const Helper = require('@codeceptjs/helper')
4
- const REST = require('./REST')
1
+ import path from 'path'
2
+ import Helper from '@codeceptjs/helper'
3
+ import REST from './REST.js'
5
4
 
6
5
  /**
7
6
  * Helper for managing remote data using REST API.
@@ -222,10 +221,11 @@ class ApiDataFactory extends Helper {
222
221
 
223
222
  static _checkRequirements() {
224
223
  try {
225
- require('axios')
226
- require('rosie')
224
+ // In ESM, dependencies are already imported at the top
225
+ // The import will fail at module load time if dependencies are missing
226
+ return null
227
227
  } catch (e) {
228
- return ['axios', 'rosie']
228
+ return ['axios']
229
229
  }
230
230
  }
231
231
 
@@ -241,10 +241,25 @@ class ApiDataFactory extends Helper {
241
241
  if (!createdItems.length) continue
242
242
  this.debug(`Deleting ${createdItems.length} ${factoryName}(s)`)
243
243
  for (const id in createdItems) {
244
- promises.push(this._requestDelete(factoryName, createdItems[id]))
244
+ const deletePromise = this._requestDelete(factoryName, createdItems[id])
245
+ if (deletePromise) {
246
+ promises.push(deletePromise.catch(err => {
247
+ this.debugSection('Delete Error', `Failed to delete ${factoryName} with id ${createdItems[id]}: ${err.message}`)
248
+ // Don't reject Promise.all, just log the error
249
+ return Promise.resolve()
250
+ }))
251
+ }
245
252
  }
246
253
  }
247
- return Promise.all(promises)
254
+ return Promise.all(promises).then(() => {
255
+ // Clear the created items after successful cleanup
256
+ for (const factoryName in this.created) {
257
+ this.created[factoryName] = []
258
+ }
259
+ // Add a small delay to ensure file system changes propagate in Docker environments
260
+ // This helps avoid race conditions where GET requests after DELETE don't see the changes yet
261
+ return new Promise(resolve => setTimeout(resolve, 100))
262
+ })
248
263
  }
249
264
 
250
265
  /**
@@ -265,8 +280,8 @@ class ApiDataFactory extends Helper {
265
280
  * @param {*} [options] options for programmatically generate the attributes
266
281
  * @returns {Promise<*>}
267
282
  */
268
- have(factory, params, options) {
269
- const item = this._createItem(factory, params, options)
283
+ async have(factory, params, options) {
284
+ const item = await this._createItem(factory, params, options)
270
285
  this.debug(`Creating ${factory} ${JSON.stringify(item)}`)
271
286
  return this._requestCreate(factory, item)
272
287
  }
@@ -298,19 +313,22 @@ class ApiDataFactory extends Helper {
298
313
  return Promise.all(promises)
299
314
  }
300
315
 
301
- _createItem(model, data, options) {
316
+ async _createItem(model, data, options) {
302
317
  if (!this.factories[model]) {
303
318
  throw new Error(`Factory ${model} is not defined in config`)
304
319
  }
305
320
  let modulePath = this.factories[model].factory
306
321
  try {
307
322
  try {
308
- require.resolve(modulePath)
323
+ // Try to resolve the path as-is first
324
+ await import.meta.resolve(modulePath)
309
325
  } catch (e) {
326
+ // If not found, try relative to codecept_dir
310
327
  modulePath = path.join(global.codecept_dir, modulePath)
311
328
  }
312
329
  // check if the new syntax `export default new Factory()` is used and loads the builder, otherwise loads the module that used old syntax `module.exports = new Factory()`.
313
- const builder = require(modulePath).default || require(modulePath)
330
+ const module = await import(modulePath)
331
+ const builder = module.default || module
314
332
  return builder.build(data, options)
315
333
  } catch (err) {
316
334
  throw new Error(`Couldn't load factory file from ${modulePath}, check that
@@ -383,26 +401,39 @@ Current file error: ${err.message}`)
383
401
  const url = this.factories[factory].delete[method].replace('{id}', id)
384
402
 
385
403
  request = {
386
- method,
404
+ method: method.toUpperCase(), // Ensure HTTP method is uppercase
387
405
  url,
388
406
  }
389
407
  }
390
408
 
409
+ // Ensure method is uppercase (some servers require uppercase HTTP methods)
410
+ if (request.method) {
411
+ request.method = request.method.toUpperCase()
412
+ }
413
+
391
414
  request.baseURL = this.config.endpoint
392
415
 
393
416
  if (request.url.match(/^undefined/)) {
394
417
  return this.debugSection('Please configure the delete request in your ApiDataFactory helper', "delete: () => ({ method: 'DELETE', url: '/api/users' })")
395
418
  }
396
419
 
397
- return this.restHelper._executeRequest(request).then(() => {
420
+ this.debugSection('Deleting', `${request.method} ${request.baseURL}${request.url} (ID: ${id})`)
421
+
422
+ return this.restHelper._executeRequest(request).then((resp) => {
398
423
  const idx = this.created[factory].indexOf(id)
399
- this.debugSection('Deleted Id', `Id: ${id}`)
400
- this.created[factory].splice(idx, 1)
424
+ this.debugSection('Deleted Successfully', `${factory} ID: ${id}, Status: ${resp.status || 'OK'}`)
425
+ if (idx !== -1) {
426
+ this.created[factory].splice(idx, 1)
427
+ }
428
+ return resp
429
+ }).catch(err => {
430
+ this.debugSection('Delete Failed', `${factory} ID: ${id}, Error: ${err.message}`)
431
+ throw err
401
432
  })
402
433
  }
403
434
  }
404
435
 
405
- module.exports = ApiDataFactory
436
+ export { ApiDataFactory as default }
406
437
 
407
438
  function createRequestFromFunction(param, data) {
408
439
  if (typeof param !== 'function') return