codeceptjs 4.0.0-beta.1 → 4.0.0-beta.11.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 (207) hide show
  1. package/README.md +133 -120
  2. package/bin/codecept.js +107 -96
  3. package/bin/test-server.js +64 -0
  4. package/docs/webapi/clearCookie.mustache +1 -1
  5. package/docs/webapi/click.mustache +5 -1
  6. package/lib/actor.js +71 -103
  7. package/lib/ai.js +159 -188
  8. package/lib/assert/empty.js +22 -24
  9. package/lib/assert/equal.js +30 -37
  10. package/lib/assert/error.js +14 -14
  11. package/lib/assert/include.js +43 -48
  12. package/lib/assert/throws.js +11 -11
  13. package/lib/assert/truth.js +22 -22
  14. package/lib/assert.js +20 -18
  15. package/lib/codecept.js +238 -162
  16. package/lib/colorUtils.js +50 -52
  17. package/lib/command/check.js +206 -0
  18. package/lib/command/configMigrate.js +56 -51
  19. package/lib/command/definitions.js +96 -109
  20. package/lib/command/dryRun.js +77 -79
  21. package/lib/command/generate.js +234 -194
  22. package/lib/command/gherkin/init.js +42 -33
  23. package/lib/command/gherkin/snippets.js +76 -74
  24. package/lib/command/gherkin/steps.js +20 -17
  25. package/lib/command/info.js +74 -38
  26. package/lib/command/init.js +300 -290
  27. package/lib/command/interactive.js +41 -32
  28. package/lib/command/list.js +28 -27
  29. package/lib/command/run-multiple/chunk.js +51 -48
  30. package/lib/command/run-multiple/collection.js +5 -5
  31. package/lib/command/run-multiple/run.js +5 -1
  32. package/lib/command/run-multiple.js +97 -97
  33. package/lib/command/run-rerun.js +19 -25
  34. package/lib/command/run-workers.js +68 -92
  35. package/lib/command/run.js +39 -27
  36. package/lib/command/utils.js +80 -64
  37. package/lib/command/workers/runTests.js +388 -226
  38. package/lib/config.js +124 -50
  39. package/lib/container.js +765 -260
  40. package/lib/data/context.js +60 -61
  41. package/lib/data/dataScenarioConfig.js +47 -47
  42. package/lib/data/dataTableArgument.js +32 -32
  43. package/lib/data/table.js +22 -22
  44. package/lib/effects.js +307 -0
  45. package/lib/element/WebElement.js +327 -0
  46. package/lib/els.js +160 -0
  47. package/lib/event.js +173 -163
  48. package/lib/globals.js +141 -0
  49. package/lib/heal.js +89 -85
  50. package/lib/helper/AI.js +131 -41
  51. package/lib/helper/ApiDataFactory.js +107 -75
  52. package/lib/helper/Appium.js +542 -404
  53. package/lib/helper/FileSystem.js +100 -79
  54. package/lib/helper/GraphQL.js +44 -43
  55. package/lib/helper/GraphQLDataFactory.js +52 -52
  56. package/lib/helper/JSONResponse.js +126 -88
  57. package/lib/helper/Mochawesome.js +54 -29
  58. package/lib/helper/Playwright.js +2547 -1316
  59. package/lib/helper/Puppeteer.js +1578 -1181
  60. package/lib/helper/REST.js +209 -68
  61. package/lib/helper/WebDriver.js +1482 -1342
  62. package/lib/helper/errors/ConnectionRefused.js +6 -6
  63. package/lib/helper/errors/ElementAssertion.js +11 -16
  64. package/lib/helper/errors/ElementNotFound.js +5 -9
  65. package/lib/helper/errors/RemoteBrowserConnectionRefused.js +5 -5
  66. package/lib/helper/extras/Console.js +11 -11
  67. package/lib/helper/extras/PlaywrightLocator.js +110 -0
  68. package/lib/helper/extras/PlaywrightPropEngine.js +18 -18
  69. package/lib/helper/extras/PlaywrightReactVueLocator.js +17 -8
  70. package/lib/helper/extras/PlaywrightRestartOpts.js +25 -11
  71. package/lib/helper/extras/Popup.js +22 -22
  72. package/lib/helper/extras/React.js +27 -28
  73. package/lib/helper/network/actions.js +36 -42
  74. package/lib/helper/network/utils.js +78 -84
  75. package/lib/helper/scripts/blurElement.js +5 -5
  76. package/lib/helper/scripts/focusElement.js +5 -5
  77. package/lib/helper/scripts/highlightElement.js +8 -8
  78. package/lib/helper/scripts/isElementClickable.js +34 -34
  79. package/lib/helper.js +2 -3
  80. package/lib/history.js +23 -19
  81. package/lib/hooks.js +8 -8
  82. package/lib/html.js +94 -104
  83. package/lib/index.js +38 -27
  84. package/lib/listener/config.js +30 -23
  85. package/lib/listener/emptyRun.js +54 -0
  86. package/lib/listener/enhancedGlobalRetry.js +110 -0
  87. package/lib/listener/exit.js +16 -18
  88. package/lib/listener/globalRetry.js +70 -0
  89. package/lib/listener/globalTimeout.js +181 -0
  90. package/lib/listener/helpers.js +76 -51
  91. package/lib/listener/mocha.js +10 -11
  92. package/lib/listener/result.js +11 -0
  93. package/lib/listener/retryEnhancer.js +85 -0
  94. package/lib/listener/steps.js +71 -59
  95. package/lib/listener/store.js +20 -0
  96. package/lib/locator.js +214 -197
  97. package/lib/mocha/asyncWrapper.js +274 -0
  98. package/lib/mocha/bdd.js +167 -0
  99. package/lib/mocha/cli.js +341 -0
  100. package/lib/mocha/factory.js +163 -0
  101. package/lib/mocha/featureConfig.js +89 -0
  102. package/lib/mocha/gherkin.js +231 -0
  103. package/lib/mocha/hooks.js +121 -0
  104. package/lib/mocha/index.js +21 -0
  105. package/lib/mocha/inject.js +46 -0
  106. package/lib/{interfaces → mocha}/scenarioConfig.js +58 -34
  107. package/lib/mocha/suite.js +89 -0
  108. package/lib/mocha/test.js +184 -0
  109. package/lib/mocha/types.d.ts +42 -0
  110. package/lib/mocha/ui.js +242 -0
  111. package/lib/output.js +141 -71
  112. package/lib/parser.js +47 -44
  113. package/lib/pause.js +173 -145
  114. package/lib/plugin/analyze.js +403 -0
  115. package/lib/plugin/{autoLogin.js → auth.js} +178 -79
  116. package/lib/plugin/autoDelay.js +36 -40
  117. package/lib/plugin/coverage.js +131 -78
  118. package/lib/plugin/customLocator.js +22 -21
  119. package/lib/plugin/customReporter.js +53 -0
  120. package/lib/plugin/enhancedRetryFailedStep.js +99 -0
  121. package/lib/plugin/heal.js +101 -110
  122. package/lib/plugin/htmlReporter.js +3648 -0
  123. package/lib/plugin/pageInfo.js +140 -0
  124. package/lib/plugin/pauseOnFail.js +12 -11
  125. package/lib/plugin/retryFailedStep.js +82 -47
  126. package/lib/plugin/screenshotOnFail.js +111 -92
  127. package/lib/plugin/stepByStepReport.js +159 -101
  128. package/lib/plugin/stepTimeout.js +20 -25
  129. package/lib/plugin/subtitles.js +38 -38
  130. package/lib/recorder.js +193 -130
  131. package/lib/rerun.js +94 -49
  132. package/lib/result.js +238 -0
  133. package/lib/retryCoordinator.js +207 -0
  134. package/lib/secret.js +20 -18
  135. package/lib/session.js +95 -89
  136. package/lib/step/base.js +239 -0
  137. package/lib/step/comment.js +10 -0
  138. package/lib/step/config.js +50 -0
  139. package/lib/step/func.js +46 -0
  140. package/lib/step/helper.js +50 -0
  141. package/lib/step/meta.js +99 -0
  142. package/lib/step/record.js +74 -0
  143. package/lib/step/retry.js +11 -0
  144. package/lib/step/section.js +55 -0
  145. package/lib/step.js +18 -329
  146. package/lib/steps.js +54 -0
  147. package/lib/store.js +38 -7
  148. package/lib/template/heal.js +3 -12
  149. package/lib/template/prompts/generatePageObject.js +31 -0
  150. package/lib/template/prompts/healStep.js +13 -0
  151. package/lib/template/prompts/writeStep.js +9 -0
  152. package/lib/test-server.js +334 -0
  153. package/lib/timeout.js +60 -0
  154. package/lib/transform.js +8 -8
  155. package/lib/translation.js +34 -21
  156. package/lib/utils/mask_data.js +47 -0
  157. package/lib/utils.js +411 -228
  158. package/lib/workerStorage.js +37 -34
  159. package/lib/workers.js +532 -296
  160. package/package.json +115 -95
  161. package/translations/de-DE.js +5 -3
  162. package/translations/fr-FR.js +5 -4
  163. package/translations/index.js +22 -12
  164. package/translations/it-IT.js +4 -3
  165. package/translations/ja-JP.js +4 -3
  166. package/translations/nl-NL.js +76 -0
  167. package/translations/pl-PL.js +4 -3
  168. package/translations/pt-BR.js +4 -3
  169. package/translations/ru-RU.js +4 -3
  170. package/translations/utils.js +10 -0
  171. package/translations/zh-CN.js +4 -3
  172. package/translations/zh-TW.js +4 -3
  173. package/typings/index.d.ts +546 -185
  174. package/typings/promiseBasedTypes.d.ts +150 -879
  175. package/typings/types.d.ts +547 -996
  176. package/lib/cli.js +0 -249
  177. package/lib/dirname.js +0 -5
  178. package/lib/helper/Expect.js +0 -425
  179. package/lib/helper/ExpectHelper.js +0 -399
  180. package/lib/helper/MockServer.js +0 -223
  181. package/lib/helper/Nightmare.js +0 -1411
  182. package/lib/helper/Protractor.js +0 -1835
  183. package/lib/helper/SoftExpectHelper.js +0 -381
  184. package/lib/helper/TestCafe.js +0 -1410
  185. package/lib/helper/clientscripts/nightmare.js +0 -213
  186. package/lib/helper/testcafe/testControllerHolder.js +0 -42
  187. package/lib/helper/testcafe/testcafe-utils.js +0 -63
  188. package/lib/interfaces/bdd.js +0 -98
  189. package/lib/interfaces/featureConfig.js +0 -69
  190. package/lib/interfaces/gherkin.js +0 -195
  191. package/lib/listener/artifacts.js +0 -19
  192. package/lib/listener/retry.js +0 -68
  193. package/lib/listener/timeout.js +0 -109
  194. package/lib/mochaFactory.js +0 -110
  195. package/lib/plugin/allure.js +0 -15
  196. package/lib/plugin/commentStep.js +0 -136
  197. package/lib/plugin/debugErrors.js +0 -67
  198. package/lib/plugin/eachElement.js +0 -127
  199. package/lib/plugin/fakerTransform.js +0 -49
  200. package/lib/plugin/retryTo.js +0 -121
  201. package/lib/plugin/selenoid.js +0 -371
  202. package/lib/plugin/standardActingHelpers.js +0 -9
  203. package/lib/plugin/tryTo.js +0 -105
  204. package/lib/plugin/wdio.js +0 -246
  205. package/lib/scenario.js +0 -222
  206. package/lib/ui.js +0 -238
  207. package/lib/within.js +0 -70
@@ -1,6 +1,6 @@
1
- import path from 'path';
2
- import Helper from '@codeceptjs/helper';
3
- import REST from './REST';
1
+ import path from 'path'
2
+ import Helper from '@codeceptjs/helper'
3
+ import REST from './REST.js'
4
4
 
5
5
  /**
6
6
  * Helper for managing remote data using REST API.
@@ -50,7 +50,7 @@ import REST from './REST';
50
50
  *
51
51
  * module.exports = new Factory()
52
52
  * // no need to set id, it will be set by REST API
53
- * .attr('author', () => faker.name.findName())
53
+ * .attr('author', () => faker.person.findName())
54
54
  * .attr('title', () => faker.lorem.sentence())
55
55
  * .attr('body', () => faker.lorem.paragraph());
56
56
  * ```
@@ -183,67 +183,83 @@ import REST from './REST';
183
183
  */
184
184
  class ApiDataFactory extends Helper {
185
185
  constructor(config) {
186
- super(config);
186
+ super(config)
187
187
 
188
188
  const defaultConfig = {
189
189
  cleanup: true,
190
190
  REST: {},
191
191
  factories: {},
192
192
  returnId: false,
193
- };
194
- this.config = Object.assign(defaultConfig, this.config);
193
+ }
194
+ this.config = Object.assign(defaultConfig, this.config)
195
195
 
196
- if (this.config.headers) this.config.REST.defaultHeaders = this.config.headers;
197
- if (this.config.onRequest) this.config.REST.onRequest = this.config.onRequest;
198
- this.restHelper = new REST(Object.assign(this.config.REST, { endpoint: this.config.endpoint }));
199
- this.factories = this.config.factories;
196
+ if (this.config.headers) this.config.REST.defaultHeaders = this.config.headers
197
+ if (this.config.onRequest) this.config.REST.onRequest = this.config.onRequest
198
+ this.restHelper = new REST(Object.assign(this.config.REST, { endpoint: this.config.endpoint }))
199
+ this.factories = this.config.factories
200
200
 
201
201
  for (const factory in this.factories) {
202
- const factoryConfig = this.factories[factory];
202
+ const factoryConfig = this.factories[factory]
203
203
  if (!factoryConfig.uri && !factoryConfig.create) {
204
204
  throw new Error(`Uri for factory "${factory}" is not defined. Please set "uri" parameter:
205
205
 
206
206
  "factories": {
207
207
  "${factory}": {
208
208
  "uri": ...
209
- `);
209
+ `)
210
210
  }
211
211
 
212
- if (!factoryConfig.create) factoryConfig.create = { post: factoryConfig.uri };
213
- if (!factoryConfig.delete) factoryConfig.delete = { delete: `${factoryConfig.uri}/{id}` };
212
+ if (!factoryConfig.create) factoryConfig.create = { post: factoryConfig.uri }
213
+ if (!factoryConfig.delete) factoryConfig.delete = { delete: `${factoryConfig.uri}/{id}` }
214
214
 
215
- this.factories[factory] = factoryConfig;
215
+ this.factories[factory] = factoryConfig
216
216
  }
217
217
 
218
- this.created = {};
219
- Object.keys(this.factories).forEach(f => this.created[f] = []);
218
+ this.created = {}
219
+ Object.keys(this.factories).forEach(f => (this.created[f] = []))
220
220
  }
221
221
 
222
222
  static _checkRequirements() {
223
223
  try {
224
- require('axios');
225
- 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
226
227
  } catch (e) {
227
- return ['axios', 'rosie'];
228
+ return ['axios']
228
229
  }
229
230
  }
230
231
 
231
232
  _after() {
232
233
  if (!this.config.cleanup || this.config.cleanup === false) {
233
- return Promise.resolve();
234
+ return Promise.resolve()
234
235
  }
235
- const promises = [];
236
+ const promises = []
236
237
 
237
238
  // clean up all created items
238
239
  for (const factoryName in this.created) {
239
- const createdItems = this.created[factoryName];
240
- if (!createdItems.length) continue;
241
- this.debug(`Deleting ${createdItems.length} ${factoryName}(s)`);
240
+ const createdItems = this.created[factoryName]
241
+ if (!createdItems.length) continue
242
+ this.debug(`Deleting ${createdItems.length} ${factoryName}(s)`)
242
243
  for (const id in createdItems) {
243
- 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
+ }
244
252
  }
245
253
  }
246
- 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
+ })
247
263
  }
248
264
 
249
265
  /**
@@ -264,10 +280,10 @@ class ApiDataFactory extends Helper {
264
280
  * @param {*} [options] options for programmatically generate the attributes
265
281
  * @returns {Promise<*>}
266
282
  */
267
- have(factory, params, options) {
268
- const item = this._createItem(factory, params, options);
269
- this.debug(`Creating ${factory} ${JSON.stringify(item)}`);
270
- return this._requestCreate(factory, item);
283
+ async have(factory, params, options) {
284
+ const item = await this._createItem(factory, params, options)
285
+ this.debug(`Creating ${factory} ${JSON.stringify(item)}`)
286
+ return this._requestCreate(factory, item)
271
287
  }
272
288
 
273
289
  /**
@@ -290,27 +306,30 @@ class ApiDataFactory extends Helper {
290
306
  * @param {*} [options]
291
307
  */
292
308
  haveMultiple(factory, times, params, options) {
293
- const promises = [];
309
+ const promises = []
294
310
  for (let i = 0; i < times; i++) {
295
- promises.push(this.have(factory, params, options));
311
+ promises.push(this.have(factory, params, options))
296
312
  }
297
- return Promise.all(promises);
313
+ return Promise.all(promises)
298
314
  }
299
315
 
300
- _createItem(model, data, options) {
316
+ async _createItem(model, data, options) {
301
317
  if (!this.factories[model]) {
302
- throw new Error(`Factory ${model} is not defined in config`);
318
+ throw new Error(`Factory ${model} is not defined in config`)
303
319
  }
304
- let modulePath = this.factories[model].factory;
320
+ let modulePath = this.factories[model].factory
305
321
  try {
306
322
  try {
307
- require.resolve(modulePath);
323
+ // Try to resolve the path as-is first
324
+ await import.meta.resolve(modulePath)
308
325
  } catch (e) {
309
- modulePath = path.join(global.codecept_dir, modulePath);
326
+ // If not found, try relative to codecept_dir
327
+ modulePath = path.join(global.codecept_dir, modulePath)
310
328
  }
311
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()`.
312
- const builder = require(modulePath).default || require(modulePath);
313
- return builder.build(data, options);
330
+ const module = await import(modulePath)
331
+ const builder = module.default || module
332
+ return builder.build(data, options)
314
333
  } catch (err) {
315
334
  throw new Error(`Couldn't load factory file from ${modulePath}, check that
316
335
 
@@ -321,17 +340,17 @@ class ApiDataFactory extends Helper {
321
340
  points to valid factory file.
322
341
  Factory file should export an object with build method.
323
342
 
324
- Current file error: ${err.message}`);
343
+ Current file error: ${err.message}`)
325
344
  }
326
345
  }
327
346
 
328
347
  _fetchId(body, factory) {
329
348
  if (this.config.factories[factory].fetchId) {
330
- return this.config.factories[factory].fetchId(body);
349
+ return this.config.factories[factory].fetchId(body)
331
350
  }
332
- if (body.id) return body.id;
333
- if (body[factory] && body[factory].id) return body[factory].id;
334
- return null;
351
+ if (body.id) return body.id
352
+ if (body[factory] && body[factory].id) return body[factory].id
353
+ return null
335
354
  }
336
355
 
337
356
  /**
@@ -342,27 +361,27 @@ Current file error: ${err.message}`);
342
361
  * @param {*} data
343
362
  */
344
363
  _requestCreate(factory, data) {
345
- let request = createRequestFromFunction(this.factories[factory].create, data);
364
+ let request = createRequestFromFunction(this.factories[factory].create, data)
346
365
 
347
366
  if (!request) {
348
- const method = Object.keys(this.factories[factory].create)[0];
349
- const url = this.factories[factory].create[method];
367
+ const method = Object.keys(this.factories[factory].create)[0]
368
+ const url = this.factories[factory].create[method]
350
369
  request = {
351
370
  method,
352
371
  url,
353
372
  data,
354
- };
373
+ }
355
374
  }
356
375
 
357
- request.baseURL = this.config.endpoint;
376
+ request.baseURL = this.config.endpoint
358
377
 
359
- return this.restHelper._executeRequest(request).then((resp) => {
360
- const id = this._fetchId(resp.data, factory);
361
- this.created[factory].push(id);
362
- this.debugSection('Created', `Id: ${id}`);
363
- if (this.config.returnId) return id;
364
- return resp.data;
365
- });
378
+ return this.restHelper._executeRequest(request).then(resp => {
379
+ const id = this._fetchId(resp.data, factory)
380
+ this.created[factory].push(id)
381
+ this.debugSection('Created', `Id: ${id}`)
382
+ if (this.config.returnId) return id
383
+ return resp.data
384
+ })
366
385
  }
367
386
 
368
387
  /**
@@ -373,37 +392,50 @@ Current file error: ${err.message}`);
373
392
  * @param {*} id
374
393
  */
375
394
  _requestDelete(factory, id) {
376
- if (!this.factories[factory].delete) return;
377
- let request = createRequestFromFunction(this.factories[factory].delete, id);
395
+ if (!this.factories[factory].delete) return
396
+ let request = createRequestFromFunction(this.factories[factory].delete, id)
378
397
 
379
398
  if (!request) {
380
- const method = Object.keys(this.factories[factory].delete)[0];
399
+ const method = Object.keys(this.factories[factory].delete)[0]
381
400
 
382
- const url = this.factories[factory].delete[method].replace('{id}', id);
401
+ const url = this.factories[factory].delete[method].replace('{id}', id)
383
402
 
384
403
  request = {
385
- method,
404
+ method: method.toUpperCase(), // Ensure HTTP method is uppercase
386
405
  url,
387
- };
406
+ }
388
407
  }
389
408
 
390
- request.baseURL = this.config.endpoint;
409
+ // Ensure method is uppercase (some servers require uppercase HTTP methods)
410
+ if (request.method) {
411
+ request.method = request.method.toUpperCase()
412
+ }
413
+
414
+ request.baseURL = this.config.endpoint
391
415
 
392
416
  if (request.url.match(/^undefined/)) {
393
- return this.debugSection('Please configure the delete request in your ApiDataFactory helper', 'delete: () => ({ method: \'DELETE\', url: \'/api/users\' })');
417
+ return this.debugSection('Please configure the delete request in your ApiDataFactory helper', "delete: () => ({ method: 'DELETE', url: '/api/users' })")
394
418
  }
395
419
 
396
- return this.restHelper._executeRequest(request).then(() => {
397
- const idx = this.created[factory].indexOf(id);
398
- this.debugSection('Deleted Id', `Id: ${id}`);
399
- this.created[factory].splice(idx, 1);
400
- });
420
+ this.debugSection('Deleting', `${request.method} ${request.baseURL}${request.url} (ID: ${id})`)
421
+
422
+ return this.restHelper._executeRequest(request).then((resp) => {
423
+ const idx = this.created[factory].indexOf(id)
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
432
+ })
401
433
  }
402
434
  }
403
435
 
404
- export default ApiDataFactory;
436
+ export { ApiDataFactory as default }
405
437
 
406
438
  function createRequestFromFunction(param, data) {
407
- if (typeof param !== 'function') return;
408
- return param(data);
439
+ if (typeof param !== 'function') return
440
+ return param(data)
409
441
  }