codeceptjs 3.7.0-beta.1 → 3.7.0-beta.10

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 (73) hide show
  1. package/README.md +9 -10
  2. package/bin/codecept.js +7 -0
  3. package/lib/actor.js +46 -92
  4. package/lib/ai.js +130 -121
  5. package/lib/codecept.js +2 -2
  6. package/lib/command/check.js +186 -0
  7. package/lib/command/definitions.js +3 -1
  8. package/lib/command/interactive.js +1 -1
  9. package/lib/command/run-workers.js +2 -54
  10. package/lib/command/workers/runTests.js +64 -225
  11. package/lib/container.js +27 -0
  12. package/lib/effects.js +218 -0
  13. package/lib/els.js +87 -106
  14. package/lib/event.js +18 -17
  15. package/lib/heal.js +10 -0
  16. package/lib/helper/AI.js +2 -1
  17. package/lib/helper/Appium.js +31 -22
  18. package/lib/helper/Playwright.js +22 -1
  19. package/lib/helper/Puppeteer.js +5 -0
  20. package/lib/helper/WebDriver.js +29 -8
  21. package/lib/listener/emptyRun.js +2 -5
  22. package/lib/listener/exit.js +5 -8
  23. package/lib/listener/globalTimeout.js +66 -10
  24. package/lib/listener/result.js +12 -0
  25. package/lib/listener/steps.js +3 -6
  26. package/lib/listener/store.js +9 -1
  27. package/lib/mocha/asyncWrapper.js +15 -3
  28. package/lib/mocha/cli.js +79 -28
  29. package/lib/mocha/featureConfig.js +13 -0
  30. package/lib/mocha/hooks.js +32 -3
  31. package/lib/mocha/inject.js +5 -0
  32. package/lib/mocha/scenarioConfig.js +11 -0
  33. package/lib/mocha/suite.js +27 -1
  34. package/lib/mocha/test.js +102 -3
  35. package/lib/mocha/types.d.ts +11 -0
  36. package/lib/output.js +75 -73
  37. package/lib/pause.js +3 -10
  38. package/lib/plugin/analyze.js +349 -0
  39. package/lib/plugin/autoDelay.js +2 -2
  40. package/lib/plugin/commentStep.js +5 -0
  41. package/lib/plugin/customReporter.js +52 -0
  42. package/lib/plugin/heal.js +30 -0
  43. package/lib/plugin/pageInfo.js +140 -0
  44. package/lib/plugin/retryTo.js +18 -118
  45. package/lib/plugin/screenshotOnFail.js +12 -17
  46. package/lib/plugin/standardActingHelpers.js +4 -1
  47. package/lib/plugin/stepByStepReport.js +6 -5
  48. package/lib/plugin/stepTimeout.js +1 -1
  49. package/lib/plugin/tryTo.js +17 -107
  50. package/lib/recorder.js +5 -5
  51. package/lib/rerun.js +43 -42
  52. package/lib/result.js +161 -0
  53. package/lib/step/base.js +228 -0
  54. package/lib/step/config.js +50 -0
  55. package/lib/step/func.js +46 -0
  56. package/lib/step/helper.js +50 -0
  57. package/lib/step/meta.js +99 -0
  58. package/lib/step/record.js +74 -0
  59. package/lib/step/retry.js +11 -0
  60. package/lib/step/section.js +55 -0
  61. package/lib/step.js +20 -347
  62. package/lib/steps.js +50 -0
  63. package/lib/store.js +4 -0
  64. package/lib/timeout.js +66 -0
  65. package/lib/utils.js +93 -0
  66. package/lib/within.js +2 -2
  67. package/lib/workers.js +29 -49
  68. package/package.json +23 -20
  69. package/typings/index.d.ts +5 -4
  70. package/typings/promiseBasedTypes.d.ts +617 -7
  71. package/typings/types.d.ts +663 -34
  72. package/lib/listener/artifacts.js +0 -19
  73. package/lib/plugin/debugErrors.js +0 -67
package/lib/workers.js CHANGED
@@ -1,11 +1,6 @@
1
1
  const path = require('path')
2
2
  const mkdirp = require('mkdirp')
3
3
  const { Worker } = require('worker_threads')
4
- const {
5
- Suite,
6
- Test,
7
- reporters: { Base },
8
- } = require('mocha')
9
4
  const { EventEmitter } = require('events')
10
5
  const ms = require('ms')
11
6
  const Codecept = require('./codecept')
@@ -17,6 +12,8 @@ const { replaceValueDeep, deepClone } = require('./utils')
17
12
  const mainConfig = require('./config')
18
13
  const output = require('./output')
19
14
  const event = require('./event')
15
+ const { deserializeTest } = require('./mocha/test')
16
+ const { deserializeSuite } = require('./mocha/suite')
20
17
  const recorder = require('./recorder')
21
18
  const runHook = require('./hooks')
22
19
  const WorkerStorage = require('./workerStorage')
@@ -78,12 +75,6 @@ const simplifyObject = object => {
78
75
  }, {})
79
76
  }
80
77
 
81
- const repackTest = test => {
82
- test = Object.assign(new Test(test.title || '', () => {}), test)
83
- test.parent = Object.assign(new Suite(test.parent.title), test.parent)
84
- return test
85
- }
86
-
87
78
  const createWorkerObjects = (testGroups, config, testRoot, options, selectedRuns) => {
88
79
  selectedRuns = options && options.all && config.multiple ? Object.keys(config.multiple) : selectedRuns
89
80
  if (selectedRuns === undefined || !selectedRuns.length || config.multiple === undefined) {
@@ -240,17 +231,10 @@ class Workers extends EventEmitter {
240
231
  super()
241
232
  this.setMaxListeners(50)
242
233
  this.codecept = initializeCodecept(config.testConfig, config.options)
243
- this.failuresLog = []
244
234
  this.errors = []
245
235
  this.numberOfWorkers = 0
246
236
  this.closedWorkers = 0
247
237
  this.workers = []
248
- this.stats = {
249
- passes: 0,
250
- failures: 0,
251
- tests: 0,
252
- pending: 0,
253
- }
254
238
  this.testGroups = []
255
239
 
256
240
  createOutputDir(config.testConfig)
@@ -363,8 +347,6 @@ class Workers extends EventEmitter {
363
347
  }
364
348
 
365
349
  run() {
366
- this.stats.start = new Date()
367
- this.stats.failedHooks = 0
368
350
  recorder.startUnlessRunning()
369
351
  event.dispatcher.emit(event.workers.before)
370
352
  process.env.RUNS_WITH_WORKERS = 'true'
@@ -390,7 +372,7 @@ class Workers extends EventEmitter {
390
372
  * @returns {Boolean}
391
373
  */
392
374
  isFailed() {
393
- return (this.stats.failures || this.errors.length) > 0
375
+ return (Container.result().failures.length || this.errors.length) > 0
394
376
  }
395
377
 
396
378
  _listenWorkerEvents(worker) {
@@ -403,33 +385,37 @@ class Workers extends EventEmitter {
403
385
  }
404
386
 
405
387
  switch (message.event) {
406
- case event.all.failures:
407
- this.failuresLog = this.failuresLog.concat(message.data.failuresLog)
408
- this._appendStats(message.data.stats)
388
+ case event.all.result:
389
+ // we ensure consistency of result by adding tests in the very end
390
+ Container.result().addFailures(message.data.failures)
391
+ Container.result().addStats(message.data.stats)
392
+ message.data.tests.forEach(test => {
393
+ Container.result().addTest(deserializeTest(test))
394
+ })
409
395
  break
410
396
  case event.suite.before:
411
- this.emit(event.suite.before, repackTest(message.data))
397
+ this.emit(event.suite.before, deserializeSuite(message.data))
412
398
  break
413
399
  case event.test.before:
414
- this.emit(event.test.before, repackTest(message.data))
400
+ this.emit(event.test.before, deserializeTest(message.data))
415
401
  break
416
402
  case event.test.started:
417
- this.emit(event.test.started, repackTest(message.data))
403
+ this.emit(event.test.started, deserializeTest(message.data))
418
404
  break
419
405
  case event.test.failed:
420
- this.emit(event.test.failed, repackTest(message.data))
406
+ this.emit(event.test.failed, deserializeTest(message.data))
421
407
  break
422
408
  case event.test.passed:
423
- this.emit(event.test.passed, repackTest(message.data))
409
+ this.emit(event.test.passed, deserializeTest(message.data))
424
410
  break
425
411
  case event.test.skipped:
426
- this.emit(event.test.skipped, repackTest(message.data))
412
+ this.emit(event.test.skipped, deserializeTest(message.data))
427
413
  break
428
414
  case event.test.finished:
429
- this.emit(event.test.finished, repackTest(message.data))
415
+ this.emit(event.test.finished, deserializeTest(message.data))
430
416
  break
431
417
  case event.test.after:
432
- this.emit(event.test.after, repackTest(message.data))
418
+ this.emit(event.test.after, deserializeTest(message.data))
433
419
  break
434
420
  case event.step.finished:
435
421
  this.emit(event.step.finished, message.data)
@@ -441,7 +427,7 @@ class Workers extends EventEmitter {
441
427
  this.emit(event.step.passed, message.data)
442
428
  break
443
429
  case event.step.failed:
444
- this.emit(event.step.failed, message.data)
430
+ this.emit(event.step.failed, message.data, message.data.error)
445
431
  break
446
432
  }
447
433
  })
@@ -459,34 +445,27 @@ class Workers extends EventEmitter {
459
445
  }
460
446
 
461
447
  _finishRun() {
462
- event.dispatcher.emit(event.workers.after)
463
- if (this.isFailed()) {
448
+ event.dispatcher.emit(event.workers.after, { tests: this.workers.map(worker => worker.tests) })
449
+ if (Container.result().hasFailed) {
464
450
  process.exitCode = 1
465
451
  } else {
466
452
  process.exitCode = 0
467
453
  }
468
- // removed this.finishedTests because in all /lib only first argument (!this.isFailed()) is used)
469
- this.emit(event.all.result, !this.isFailed())
470
- this.emit('end') // internal event
471
- }
472
454
 
473
- _appendStats(newStats) {
474
- this.stats.passes += newStats.passes
475
- this.stats.failures += newStats.failures
476
- this.stats.tests += newStats.tests
477
- this.stats.pending += newStats.pending
478
- this.stats.failedHooks += newStats.failedHooks
455
+ this.emit(event.all.result, Container.result())
456
+ event.dispatcher.emit(event.workers.result, Container.result())
457
+ this.emit('end') // internal event
479
458
  }
480
459
 
481
460
  printResults() {
482
- this.stats.end = new Date()
483
- this.stats.duration = this.stats.end - this.stats.start
461
+ const result = Container.result()
462
+ result.finish()
484
463
 
485
464
  // Reset process for logs in main thread
486
465
  output.process(null)
487
466
  output.print()
488
467
 
489
- this.failuresLog = this.failuresLog
468
+ this.failuresLog = result.failures
490
469
  .filter(log => log.length && typeof log[1] === 'number')
491
470
  // mocha/lib/reporters/base.js
492
471
  .map(([format, num, title, message, stack], i) => [format, i + 1, title, message, stack])
@@ -497,7 +476,8 @@ class Workers extends EventEmitter {
497
476
  this.failuresLog.forEach(log => output.print(...log))
498
477
  }
499
478
 
500
- output.result(this.stats.passes, this.stats.failures, this.stats.pending, ms(this.stats.duration), this.stats.failedHooks)
479
+ output.result(result.stats.passes, result.stats.failures, result.stats.pending, ms(result.duration), result.stats.failedHooks)
480
+
501
481
  process.env.RUNS_WITH_WORKERS = 'false'
502
482
  }
503
483
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeceptjs",
3
- "version": "3.7.0-beta.1",
3
+ "version": "3.7.0-beta.10",
4
4
  "description": "Supercharged End 2 End Testing Framework for NodeJS",
5
5
  "keywords": [
6
6
  "acceptance",
@@ -31,7 +31,9 @@
31
31
  "main": "lib/index.js",
32
32
  "exports": {
33
33
  ".": "./lib/index.js",
34
- "./els": "./lib/els.js"
34
+ "./els": "./lib/els.js",
35
+ "./effects": "./lib/effects.js",
36
+ "./steps": "./lib/steps.js"
35
37
  },
36
38
  "types": "typings/index.d.ts",
37
39
  "bin": {
@@ -48,10 +50,10 @@
48
50
  "test:unit": "mocha test/unit --recursive --timeout 10000",
49
51
  "test:runner": "mocha test/runner --recursive --timeout 10000",
50
52
  "test": "npm run test:unit && npm run test:runner",
51
- "test:appium-quick": "mocha test/helper/AppiumV2_test.js --grep 'quick'",
52
- "test:appium-other": "mocha test/helper/AppiumV2_test.js --grep 'second'",
53
- "test:ios:appium-quick": "mocha test/helper/AppiumV2_ios_test.js --grep 'quick'",
54
- "test:ios:appium-other": "mocha test/helper/AppiumV2_ios_test.js --grep 'second'",
53
+ "test:appium-quick": "mocha test/helper/Appium_test.js --grep 'quick'",
54
+ "test:appium-other": "mocha test/helper/Appium_test.js --grep 'second'",
55
+ "test:ios:appium-quick": "mocha test/helper/Appium_ios_test.js --grep 'quick'",
56
+ "test:ios:appium-other": "mocha test/helper/Appium_ios_test.js --grep 'second'",
55
57
  "test-app:start": "php -S 127.0.0.1:8000 -t test/data/app",
56
58
  "test-app:stop": "kill -9 $(lsof -t -i:8000)",
57
59
  "test:unit:webbapi:playwright": "mocha test/helper/Playwright_test.js",
@@ -77,7 +79,7 @@
77
79
  "@cucumber/cucumber-expressions": "18",
78
80
  "@cucumber/gherkin": "30",
79
81
  "@cucumber/messages": "27.0.2",
80
- "@xmldom/xmldom": "0.9.6",
82
+ "@xmldom/xmldom": "0.9.7",
81
83
  "acorn": "8.14.0",
82
84
  "arrify": "3.0.0",
83
85
  "axios": "1.7.9",
@@ -91,8 +93,9 @@
91
93
  "escape-string-regexp": "4.0.0",
92
94
  "figures": "3.2.0",
93
95
  "fn-args": "4.0.0",
96
+ "fs-extra": "11.3.0",
94
97
  "fs-extra": "11.2.0",
95
- "glob": "^11.0.0",
98
+ "glob": "^11.0.1",
96
99
  "fuse.js": "^7.0.0",
97
100
  "html-minifier-terser": "7.2.0",
98
101
  "inquirer": "6.5.2",
@@ -103,7 +106,7 @@
103
106
  "lodash.merge": "4.6.2",
104
107
  "mkdirp": "3.0.1",
105
108
  "mocha": "11.1.0",
106
- "monocart-coverage-reports": "2.11.5",
109
+ "monocart-coverage-reports": "2.12.0",
107
110
  "ms": "2.1.3",
108
111
  "ora-classic": "5.4.2",
109
112
  "parse-function": "5.6.10",
@@ -111,33 +114,33 @@
111
114
  "promise-retry": "1.1.1",
112
115
  "resq": "1.11.0",
113
116
  "sprintf-js": "1.1.3",
114
- "uuid": "11.0.4"
117
+ "uuid": "11.0.5"
115
118
  },
116
119
  "optionalDependencies": {
117
- "@codeceptjs/detox-helper": "1.1.4"
120
+ "@codeceptjs/detox-helper": "1.1.5"
118
121
  },
119
122
  "devDependencies": {
120
123
  "@apollo/server": "^4",
121
124
  "@codeceptjs/expect-helper": "^0.2.2",
122
125
  "@codeceptjs/mock-request": "0.3.1",
123
126
  "@eslint/eslintrc": "3.2.0",
124
- "@eslint/js": "9.17.0",
125
- "@faker-js/faker": "9.3.0",
127
+ "@eslint/js": "9.18.0",
128
+ "@faker-js/faker": "9.4.0",
126
129
  "@pollyjs/adapter-puppeteer": "6.0.6",
127
130
  "@pollyjs/core": "5.1.0",
128
131
  "@types/chai": "4.3.19",
129
132
  "@types/inquirer": "9.0.7",
130
- "@types/node": "22.10.5",
131
- "@wdio/sauce-service": "9.5.1",
133
+ "@types/node": "22.10.7",
134
+ "@wdio/sauce-service": "9.5.7",
132
135
  "@wdio/selenium-standalone-service": "8.15.0",
133
136
  "@wdio/utils": "9.5.0",
134
- "@xmldom/xmldom": "0.9.6",
137
+ "@xmldom/xmldom": "0.9.7",
135
138
  "chai": "^4.0.0",
136
139
  "chai-as-promised": "7.1.2",
137
140
  "chai-subset": "1.6.0",
138
141
  "documentation": "14.0.3",
139
- "electron": "33.2.1",
140
- "eslint": "^9.17.0",
142
+ "electron": "34.0.0",
143
+ "eslint": "^9.18.0",
141
144
  "eslint-plugin-import": "2.31.0",
142
145
  "eslint-plugin-mocha": "10.5.0",
143
146
  "expect": "29.7.0",
@@ -152,7 +155,7 @@
152
155
  "json-server": "0.17.4",
153
156
  "playwright": "1.49.1",
154
157
  "prettier": "^3.3.2",
155
- "puppeteer": "23.11.1",
158
+ "puppeteer": "24.1.0",
156
159
  "qrcode-terminal": "0.12.0",
157
160
  "rosie": "2.1.1",
158
161
  "runok": "0.9.3",
@@ -166,7 +169,7 @@
166
169
  "tsd-jsdoc": "2.5.0",
167
170
  "typedoc": "0.27.6",
168
171
  "typedoc-plugin-markdown": "4.4.1",
169
- "typescript": "5.7.2",
172
+ "typescript": "5.7.3",
170
173
  "wdio-docker-service": "1.5.0",
171
174
  "webdriverio": "^9.5.1",
172
175
  "xml2js": "0.6.2",
@@ -451,9 +451,6 @@ declare namespace CodeceptJS {
451
451
  }
452
452
 
453
453
  // Extending JSDoc generated typings
454
- interface Step {
455
- isMetaStep(): this is MetaStep
456
- }
457
454
 
458
455
  // Types who are not be defined by JSDoc
459
456
  type actor = <T extends { [action: string]: (...args: any[]) => void }>(customSteps?: T & ThisType<WithTranslation<Methods & T>>) => WithTranslation<Methods & T>
@@ -502,7 +499,7 @@ declare namespace CodeceptJS {
502
499
  (title: string, opts: { [key: string]: any }, callback: HookCallback): ScenarioConfig
503
500
  }
504
501
  interface IHook {
505
- (callback: HookCallback): void
502
+ (callback: HookCallback): HookConfig
506
503
  }
507
504
 
508
505
  interface Globals {
@@ -516,6 +513,10 @@ declare namespace CodeceptJS {
516
513
  useForSnippets?: boolean
517
514
  preferForRegexpMatch?: boolean
518
515
  }
516
+
517
+ interface HookConfig {
518
+ retry(retries?: number): HookConfig
519
+ }
519
520
  }
520
521
 
521
522
  // Globals