codeceptjs 4.0.0-beta.3 → 4.0.0-beta.5

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 (155) hide show
  1. package/README.md +134 -119
  2. package/bin/codecept.js +12 -2
  3. package/bin/test-server.js +53 -0
  4. package/docs/webapi/clearCookie.mustache +1 -1
  5. package/lib/actor.js +66 -102
  6. package/lib/ai.js +130 -121
  7. package/lib/assert/empty.js +3 -5
  8. package/lib/assert/equal.js +4 -7
  9. package/lib/assert/include.js +4 -6
  10. package/lib/assert/throws.js +2 -4
  11. package/lib/assert/truth.js +2 -2
  12. package/lib/codecept.js +141 -86
  13. package/lib/command/check.js +201 -0
  14. package/lib/command/configMigrate.js +2 -4
  15. package/lib/command/definitions.js +8 -26
  16. package/lib/command/dryRun.js +30 -35
  17. package/lib/command/generate.js +10 -14
  18. package/lib/command/gherkin/snippets.js +75 -73
  19. package/lib/command/gherkin/steps.js +1 -1
  20. package/lib/command/info.js +42 -8
  21. package/lib/command/init.js +13 -12
  22. package/lib/command/interactive.js +10 -2
  23. package/lib/command/list.js +1 -1
  24. package/lib/command/run-multiple/chunk.js +48 -45
  25. package/lib/command/run-multiple.js +12 -35
  26. package/lib/command/run-workers.js +21 -58
  27. package/lib/command/utils.js +5 -6
  28. package/lib/command/workers/runTests.js +263 -222
  29. package/lib/container.js +386 -238
  30. package/lib/data/context.js +10 -13
  31. package/lib/data/dataScenarioConfig.js +8 -8
  32. package/lib/data/dataTableArgument.js +6 -6
  33. package/lib/data/table.js +5 -11
  34. package/lib/effects.js +223 -0
  35. package/lib/element/WebElement.js +327 -0
  36. package/lib/els.js +158 -0
  37. package/lib/event.js +21 -17
  38. package/lib/heal.js +88 -80
  39. package/lib/helper/AI.js +2 -1
  40. package/lib/helper/ApiDataFactory.js +4 -7
  41. package/lib/helper/Appium.js +50 -57
  42. package/lib/helper/FileSystem.js +3 -3
  43. package/lib/helper/GraphQLDataFactory.js +4 -4
  44. package/lib/helper/JSONResponse.js +75 -37
  45. package/lib/helper/Mochawesome.js +31 -9
  46. package/lib/helper/Nightmare.js +37 -58
  47. package/lib/helper/Playwright.js +267 -272
  48. package/lib/helper/Protractor.js +56 -87
  49. package/lib/helper/Puppeteer.js +247 -264
  50. package/lib/helper/REST.js +29 -17
  51. package/lib/helper/TestCafe.js +22 -47
  52. package/lib/helper/WebDriver.js +157 -368
  53. package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
  54. package/lib/helper/extras/Popup.js +22 -22
  55. package/lib/helper/network/utils.js +1 -1
  56. package/lib/helper/testcafe/testcafe-utils.js +27 -28
  57. package/lib/listener/emptyRun.js +55 -0
  58. package/lib/listener/exit.js +7 -10
  59. package/lib/listener/{retry.js → globalRetry.js} +5 -5
  60. package/lib/listener/globalTimeout.js +165 -0
  61. package/lib/listener/helpers.js +15 -15
  62. package/lib/listener/mocha.js +1 -1
  63. package/lib/listener/result.js +12 -0
  64. package/lib/listener/retryEnhancer.js +85 -0
  65. package/lib/listener/steps.js +32 -18
  66. package/lib/listener/store.js +20 -0
  67. package/lib/locator.js +1 -1
  68. package/lib/mocha/asyncWrapper.js +231 -0
  69. package/lib/{interfaces → mocha}/bdd.js +3 -3
  70. package/lib/mocha/cli.js +308 -0
  71. package/lib/mocha/factory.js +104 -0
  72. package/lib/{interfaces → mocha}/featureConfig.js +32 -12
  73. package/lib/{interfaces → mocha}/gherkin.js +26 -28
  74. package/lib/mocha/hooks.js +112 -0
  75. package/lib/mocha/index.js +12 -0
  76. package/lib/mocha/inject.js +29 -0
  77. package/lib/{interfaces → mocha}/scenarioConfig.js +31 -7
  78. package/lib/mocha/suite.js +82 -0
  79. package/lib/mocha/test.js +181 -0
  80. package/lib/mocha/types.d.ts +42 -0
  81. package/lib/mocha/ui.js +232 -0
  82. package/lib/output.js +93 -65
  83. package/lib/pause.js +160 -138
  84. package/lib/plugin/analyze.js +396 -0
  85. package/lib/plugin/auth.js +435 -0
  86. package/lib/plugin/autoDelay.js +8 -8
  87. package/lib/plugin/autoLogin.js +3 -338
  88. package/lib/plugin/commentStep.js +6 -1
  89. package/lib/plugin/coverage.js +10 -22
  90. package/lib/plugin/customLocator.js +3 -3
  91. package/lib/plugin/customReporter.js +52 -0
  92. package/lib/plugin/eachElement.js +1 -1
  93. package/lib/plugin/fakerTransform.js +1 -1
  94. package/lib/plugin/heal.js +36 -9
  95. package/lib/plugin/htmlReporter.js +1947 -0
  96. package/lib/plugin/pageInfo.js +140 -0
  97. package/lib/plugin/retryFailedStep.js +17 -18
  98. package/lib/plugin/retryTo.js +2 -113
  99. package/lib/plugin/screenshotOnFail.js +17 -58
  100. package/lib/plugin/selenoid.js +15 -35
  101. package/lib/plugin/standardActingHelpers.js +4 -1
  102. package/lib/plugin/stepByStepReport.js +56 -17
  103. package/lib/plugin/stepTimeout.js +5 -12
  104. package/lib/plugin/subtitles.js +4 -4
  105. package/lib/plugin/tryTo.js +3 -102
  106. package/lib/plugin/wdio.js +8 -10
  107. package/lib/recorder.js +155 -124
  108. package/lib/rerun.js +43 -42
  109. package/lib/result.js +161 -0
  110. package/lib/secret.js +1 -2
  111. package/lib/step/base.js +239 -0
  112. package/lib/step/comment.js +10 -0
  113. package/lib/step/config.js +50 -0
  114. package/lib/step/func.js +46 -0
  115. package/lib/step/helper.js +50 -0
  116. package/lib/step/meta.js +99 -0
  117. package/lib/step/record.js +74 -0
  118. package/lib/step/retry.js +11 -0
  119. package/lib/step/section.js +55 -0
  120. package/lib/step.js +21 -332
  121. package/lib/steps.js +50 -0
  122. package/lib/store.js +37 -5
  123. package/lib/template/heal.js +2 -11
  124. package/lib/test-server.js +323 -0
  125. package/lib/timeout.js +66 -0
  126. package/lib/utils.js +351 -218
  127. package/lib/within.js +75 -55
  128. package/lib/workerStorage.js +2 -1
  129. package/lib/workers.js +386 -277
  130. package/package.json +81 -75
  131. package/translations/de-DE.js +5 -3
  132. package/translations/fr-FR.js +5 -4
  133. package/translations/index.js +1 -0
  134. package/translations/it-IT.js +4 -3
  135. package/translations/ja-JP.js +4 -3
  136. package/translations/nl-NL.js +76 -0
  137. package/translations/pl-PL.js +4 -3
  138. package/translations/pt-BR.js +4 -3
  139. package/translations/ru-RU.js +4 -3
  140. package/translations/utils.js +9 -0
  141. package/translations/zh-CN.js +4 -3
  142. package/translations/zh-TW.js +4 -3
  143. package/typings/index.d.ts +197 -187
  144. package/typings/promiseBasedTypes.d.ts +53 -903
  145. package/typings/types.d.ts +372 -1042
  146. package/lib/cli.js +0 -257
  147. package/lib/helper/ExpectHelper.js +0 -391
  148. package/lib/helper/MockServer.js +0 -221
  149. package/lib/helper/SoftExpectHelper.js +0 -381
  150. package/lib/listener/artifacts.js +0 -19
  151. package/lib/listener/timeout.js +0 -109
  152. package/lib/mochaFactory.js +0 -113
  153. package/lib/plugin/debugErrors.js +0 -67
  154. package/lib/scenario.js +0 -224
  155. package/lib/ui.js +0 -236
@@ -0,0 +1,112 @@
1
+ const event = require('../event')
2
+ const { serializeError } = require('../utils')
3
+ // const { serializeTest } = require('./test')
4
+
5
+ /**
6
+ * Represents a test hook in the testing framework
7
+ * @class
8
+ * @property {Object} suite - The test suite this hook belongs to
9
+ * @property {Object} test - The test object associated with this hook
10
+ * @property {Object} runnable - The current test being executed
11
+ * @property {Object} ctx - The context object
12
+ * @property {Error|null} err - The error that occurred during hook execution, if any
13
+ */
14
+ class Hook {
15
+ /**
16
+ * Creates a new Hook instance
17
+ * @param {Object} context - The context object containing suite and test information
18
+ * @param {Object} context.suite - The test suite
19
+ * @param {Object} context.test - The test object
20
+ * @param {Object} context.ctx - The context object
21
+ * @param {Error} error - The error object if hook execution failed
22
+ */
23
+ constructor(context, error) {
24
+ this.suite = context.suite
25
+ this.test = context.test
26
+ this.runnable = context?.ctx?.test
27
+ this.ctx = context.ctx
28
+ this.err = error
29
+ }
30
+
31
+ get hookName() {
32
+ return this.constructor.name.replace('Hook', '')
33
+ }
34
+
35
+ simplify() {
36
+ return {
37
+ hookName: this.hookName,
38
+ title: this.title,
39
+ // test: this.test ? serializeTest(this.test) : null,
40
+ // suite: this.suite ? serializeSuite(this.suite) : null,
41
+ error: this.err ? serializeError(this.err) : null,
42
+ }
43
+ }
44
+
45
+ toString() {
46
+ return this.hookName
47
+ }
48
+
49
+ toCode() {
50
+ return this.toString() + '()'
51
+ }
52
+
53
+ retry(n) {
54
+ this.suite.opts[`retry${this.hookName}`] = n
55
+ }
56
+
57
+ get title() {
58
+ return this.ctx?.test?.title || this.name
59
+ }
60
+
61
+ get name() {
62
+ return this.constructor.name
63
+ }
64
+ }
65
+
66
+ class BeforeHook extends Hook {}
67
+
68
+ class AfterHook extends Hook {}
69
+
70
+ class BeforeSuiteHook extends Hook {}
71
+
72
+ class AfterSuiteHook extends Hook {}
73
+
74
+ function fireHook(eventType, suite, error) {
75
+ const hook = suite.ctx?.test?.title?.match(/"([^"]*)"/)[1]
76
+ switch (hook) {
77
+ case 'before each':
78
+ event.emit(eventType, new BeforeHook(suite, error))
79
+ break
80
+ case 'after each':
81
+ event.emit(eventType, new AfterHook(suite, error))
82
+ break
83
+ case 'before all':
84
+ event.emit(eventType, new BeforeSuiteHook(suite, error))
85
+ break
86
+ case 'after all':
87
+ event.emit(eventType, new AfterSuiteHook(suite, error))
88
+ break
89
+ default:
90
+ event.emit(eventType, suite, error)
91
+ }
92
+ }
93
+
94
+ class HookConfig {
95
+ constructor(hook) {
96
+ this.hook = hook
97
+ }
98
+
99
+ retry(n) {
100
+ this.hook.retry(n)
101
+ return this
102
+ }
103
+ }
104
+
105
+ module.exports = {
106
+ BeforeHook,
107
+ AfterHook,
108
+ BeforeSuiteHook,
109
+ AfterSuiteHook,
110
+ fireHook,
111
+ HookConfig,
112
+ }
@@ -0,0 +1,12 @@
1
+ const Suite = require('mocha/lib/suite')
2
+ const Test = require('mocha/lib/test')
3
+ const { BeforeHook, AfterHook, BeforeSuiteHook, AfterSuiteHook } = require('./hooks')
4
+
5
+ module.exports = {
6
+ Suite,
7
+ Test,
8
+ BeforeHook,
9
+ AfterHook,
10
+ BeforeSuiteHook,
11
+ AfterSuiteHook,
12
+ }
@@ -0,0 +1,29 @@
1
+ const parser = require('../parser')
2
+
3
+ const getInjectedArguments = (fn, test) => {
4
+ const container = require('../container')
5
+ const testArgs = {}
6
+ const params = parser.getParams(fn) || []
7
+ const objects = container.support()
8
+
9
+ for (const key of params) {
10
+ testArgs[key] = {}
11
+ if (test && test.inject && test.inject[key]) {
12
+ // @FIX: need fix got inject
13
+ testArgs[key] = test.inject[key]
14
+ continue
15
+ }
16
+ if (!objects[key]) {
17
+ throw new Error(`Object of type ${key} is not defined in container`)
18
+ }
19
+ testArgs[key] = container.support(key)
20
+ }
21
+
22
+ if (test) {
23
+ testArgs.suite = test?.parent
24
+ testArgs.test = test
25
+ }
26
+ return testArgs
27
+ }
28
+
29
+ module.exports.getInjectedArguments = getInjectedArguments
@@ -1,5 +1,10 @@
1
+ const { isAsyncFunction } = require('../utils')
2
+
1
3
  /** @class */
2
4
  class ScenarioConfig {
5
+ /**
6
+ * @param {CodeceptJS.Test} test
7
+ */
3
8
  constructor(test) {
4
9
  this.test = test
5
10
  }
@@ -40,6 +45,17 @@ class ScenarioConfig {
40
45
  return this
41
46
  }
42
47
 
48
+ /**
49
+ * Set metadata for this test
50
+ * @param {string} key
51
+ * @param {string} value
52
+ * @returns {this}
53
+ */
54
+ meta(key, value) {
55
+ this.test.meta[key] = value
56
+ return this
57
+ }
58
+
43
59
  /**
44
60
  * Set timeout for this test
45
61
  * @param {number} timeout
@@ -64,24 +80,32 @@ class ScenarioConfig {
64
80
  return this
65
81
  }
66
82
 
83
+ /**
84
+ * @callback ScenarioConfigCallback
85
+ * @param {CodeceptJS.Test} test
86
+ * @returns {Object<string, any>}
87
+ */
88
+
67
89
  /**
68
90
  * Configures a helper.
69
91
  * Helper name can be omitted and values will be applied to first helper.
70
- * @param {string | Object<string, any>} helper
92
+ * @param {string | Object<string, any> | ScenarioConfigCallback} helper
71
93
  * @param {Object<string, any>} [obj]
72
94
  * @returns {this}
73
95
  */
74
- async config(helper, obj) {
96
+ config(helper, obj) {
75
97
  if (!obj) {
76
98
  obj = helper
77
99
  helper = 0
78
100
  }
79
101
  if (typeof obj === 'function') {
80
- obj = await obj(this.test)
81
- }
82
- if (!this.test.config) {
83
- this.test.config = {}
102
+ if (isAsyncFunction(obj)) {
103
+ obj(this.test).then(res => (this.test.config[helper] = res))
104
+ return this
105
+ }
106
+ obj = obj(this.test)
84
107
  }
108
+
85
109
  this.test.config[helper] = obj
86
110
  return this
87
111
  }
@@ -104,7 +128,7 @@ class ScenarioConfig {
104
128
  * @returns {this}
105
129
  */
106
130
  injectDependencies(dependencies) {
107
- Object.keys(dependencies).forEach((key) => {
131
+ Object.keys(dependencies).forEach(key => {
108
132
  this.test.inject[key] = dependencies[key]
109
133
  })
110
134
  return this
@@ -0,0 +1,82 @@
1
+ const MochaSuite = require('mocha/lib/suite')
2
+ /**
3
+ * @typedef {import('mocha')} Mocha
4
+ */
5
+
6
+ /**
7
+ * Enhances MochaSuite with CodeceptJS specific functionality using composition
8
+ */
9
+ function enhanceMochaSuite(suite) {
10
+ if (!suite) suite = new MochaSuite('Suite', null, false)
11
+ // already enhanced
12
+ if (suite.codeceptjs) return suite
13
+
14
+ suite.codeceptjs = true
15
+ // Add properties
16
+ suite.tags = suite.title.match(/(\@[a-zA-Z0-9-_]+)/g) || []
17
+ suite.opts = {}
18
+ // suite.totalTimeout = undefined
19
+
20
+ // Override fullTitle method
21
+ suite.fullTitle = () => `${suite.title}:`
22
+
23
+ // Add new methods
24
+ suite.applyOptions = function (opts) {
25
+ if (!opts) opts = {}
26
+ suite.opts = opts
27
+
28
+ if (opts.retries) suite.retries(opts.retries)
29
+ if (opts.timeout) suite.totalTimeout = opts.timeout
30
+
31
+ if (opts.skipInfo && opts.skipInfo.skipped) {
32
+ suite.pending = true
33
+ suite.opts = { ...this.opts, skipInfo: opts.skipInfo }
34
+ }
35
+ }
36
+
37
+ suite.simplify = function () {
38
+ return serializeSuite(this)
39
+ }
40
+
41
+ return suite
42
+ }
43
+
44
+ /**
45
+ * Factory function to create enhanced suites
46
+ * @param {Mocha.Suite} parent - Parent suite
47
+ * @param {string} title - Suite title
48
+ * @returns {CodeceptJS.Suite & Mocha.Suite} New enhanced suite instance
49
+ */
50
+ function createSuite(parent, title) {
51
+ const suite = MochaSuite.create(parent, title)
52
+ suite.timeout(0)
53
+ return enhanceMochaSuite(suite)
54
+ }
55
+
56
+ function serializeSuite(suite) {
57
+ suite = { ...suite }
58
+
59
+ return {
60
+ opts: suite.opts || {},
61
+ tags: suite.tags || [],
62
+ retries: suite._retries,
63
+ title: suite.title,
64
+ status: suite.status,
65
+ notes: suite.notes || [],
66
+ meta: suite.meta || {},
67
+ duration: suite.duration || 0,
68
+ }
69
+ }
70
+
71
+ function deserializeSuite(suite) {
72
+ suite = Object.assign(new MochaSuite(suite.title), suite)
73
+ enhanceMochaSuite(suite)
74
+ return suite
75
+ }
76
+
77
+ module.exports = {
78
+ createSuite,
79
+ enhanceMochaSuite,
80
+ serializeSuite,
81
+ deserializeSuite,
82
+ }
@@ -0,0 +1,181 @@
1
+ const Test = require('mocha/lib/test')
2
+ const Suite = require('mocha/lib/suite')
3
+ const { test: testWrapper } = require('./asyncWrapper')
4
+ const { enhanceMochaSuite, createSuite } = require('./suite')
5
+ const { genTestId, serializeError, clearString, relativeDir } = require('../utils')
6
+ const Step = require('../step/base')
7
+ /**
8
+ * Factory function to create enhanced tests
9
+ * @param {string} title - Test title
10
+ * @param {Function} fn - Test function
11
+ * @returns {CodeceptJS.Test & Mocha.Test} New enhanced test instance
12
+ */
13
+ function createTest(title, fn) {
14
+ const test = new Test(title, fn)
15
+ return enhanceMochaTest(test)
16
+ }
17
+
18
+ /**
19
+ * Enhances Mocha Test with CodeceptJS specific functionality using composition
20
+ * @param {CodeceptJS.Test & Mocha.Test} test - Test instance to enhance
21
+ * @returns {CodeceptJS.Test & Mocha.Test} Enhanced test instance
22
+ */
23
+ function enhanceMochaTest(test) {
24
+ // if no test, create a dummy one
25
+ if (!test) test = createTest('...', () => {})
26
+ // already enhanced
27
+ if (test.codeceptjs) return test
28
+
29
+ test.codeceptjs = true
30
+ // Add properties
31
+ test.tags = test.title.match(/(\@[a-zA-Z0-9-_]+)/g) || []
32
+ test.steps = []
33
+ test.config = {}
34
+ test.artifacts = []
35
+ test.inject = {}
36
+ test.opts = {}
37
+ test.meta = {}
38
+
39
+ test.notes = []
40
+ test.addNote = (type, note) => {
41
+ test.notes.push({ type, text: note })
42
+ }
43
+
44
+ // Add new methods
45
+ /**
46
+ * @param {Mocha.Suite} suite - The Mocha suite to add this test to
47
+ */
48
+ test.addToSuite = function (suite) {
49
+ enhanceMochaSuite(suite)
50
+ suite.addTest(testWrapper(this))
51
+ if (test.file && !suite.file) suite.file = test.file
52
+ test.tags = [...(test.tags || []), ...(suite.tags || [])]
53
+ test.fullTitle = () => `${suite.title}: ${test.title}`
54
+ test.uid = genTestId(test)
55
+ }
56
+
57
+ test.applyOptions = function (opts) {
58
+ if (!opts) opts = {}
59
+ test.opts = opts
60
+ test.meta = opts.meta || {}
61
+ test.totalTimeout = opts.timeout
62
+ if (opts.retries) this.retries(opts.retries)
63
+ }
64
+
65
+ test.simplify = function () {
66
+ return serializeTest(this)
67
+ }
68
+
69
+ return test
70
+ }
71
+
72
+ function deserializeTest(test) {
73
+ test = Object.assign(
74
+ createTest(test.title || '', () => {}),
75
+ test,
76
+ )
77
+ test.parent = Object.assign(new Suite(test.parent?.title || 'Suite'), test.parent)
78
+ enhanceMochaSuite(test.parent)
79
+ if (test.steps) test.steps = test.steps.map(step => Object.assign(new Step(step.title), step))
80
+
81
+ // Restore the custom fullTitle function to maintain consistency with original test
82
+ if (test.parent) {
83
+ test.fullTitle = () => `${test.parent.title}: ${test.title}`
84
+ }
85
+
86
+ return test
87
+ }
88
+
89
+ function serializeTest(test, error = null) {
90
+ // test = { ...test }
91
+
92
+ if (test.start && !test.duration) {
93
+ const end = +new Date()
94
+ test.duration = end - test.start
95
+ }
96
+
97
+ let err
98
+
99
+ if (test.err) {
100
+ err = serializeError(test.err)
101
+ test.state = 'failed'
102
+ } else if (error) {
103
+ err = serializeError(error)
104
+ test.state = 'failed'
105
+ }
106
+ const parent = {}
107
+ if (test.parent) {
108
+ parent.title = test.parent.title
109
+ }
110
+
111
+ if (test.opts) {
112
+ Object.keys(test.opts).forEach(k => {
113
+ if (typeof test.opts[k] === 'object') delete test.opts[k]
114
+ if (typeof test.opts[k] === 'function') delete test.opts[k]
115
+ })
116
+ }
117
+
118
+ let steps = undefined
119
+ if (Array.isArray(test.steps)) {
120
+ steps = test.steps.map(step => (step.simplify ? step.simplify() : step))
121
+ }
122
+
123
+ return {
124
+ opts: test.opts || {},
125
+ tags: test.tags || [],
126
+ uid: test.uid,
127
+ retries: test._retries,
128
+ title: test.title,
129
+ state: test.state,
130
+ notes: test.notes || [],
131
+ meta: test.meta || {},
132
+ artifacts: test.artifacts || {},
133
+ duration: test.duration || 0,
134
+ err,
135
+ parent,
136
+ steps,
137
+ }
138
+ }
139
+
140
+ function cloneTest(test) {
141
+ return deserializeTest(serializeTest(test))
142
+ }
143
+
144
+ /**
145
+ * Get a filename from the test object
146
+ * @param {CodeceptJS.Test} test
147
+ * @param {Object} options
148
+ * @param {string} options.suffix Add a suffix to the filename
149
+ * @param {boolean} options.unique Add a unique suffix to the file
150
+ *
151
+ * @returns {string} the filename
152
+ */
153
+ function testToFileName(test, { suffix = '', unique = false } = {}) {
154
+ let fileName = test.title
155
+
156
+ if (unique) fileName = `${fileName}_${test?.uid || Math.floor(new Date().getTime() / 1000)}`
157
+ if (suffix) fileName = `${fileName}_${suffix}`
158
+ // remove tags with empty string (disable for now)
159
+ // fileName = fileName.replace(/\@\w+/g, '')
160
+ fileName = fileName.slice(0, 100)
161
+ if (fileName.indexOf('{') !== -1) {
162
+ fileName = fileName.substr(0, fileName.indexOf('{') - 3).trim()
163
+ }
164
+ if (test.ctx && test.ctx.test && test.ctx.test.type === 'hook') fileName = clearString(`${test.title}_${test.ctx.test.title}`)
165
+ // TODO: add suite title to file name
166
+ // if (test.parent && test.parent.title) {
167
+ // fileName = `${clearString(test.parent.title)}_${fileName}`
168
+ // }
169
+ fileName = clearString(fileName).slice(0, 100)
170
+
171
+ return fileName
172
+ }
173
+
174
+ module.exports = {
175
+ createTest,
176
+ testToFileName,
177
+ enhanceMochaTest,
178
+ serializeTest,
179
+ deserializeTest,
180
+ cloneTest,
181
+ }
@@ -0,0 +1,42 @@
1
+ import { Test as MochaTest, Suite as MochaSuite } from 'mocha'
2
+
3
+ declare global {
4
+ namespace CodeceptJS {
5
+ interface Test extends MochaTest {
6
+ uid: string
7
+ title: string
8
+ tags: string[]
9
+ steps: string[]
10
+ meta: Record<string, any>
11
+ notes: Array<{
12
+ type: string
13
+ text: string
14
+ }>
15
+ state: string
16
+ err?: Error
17
+ config: Record<string, any>
18
+ artifacts: string[]
19
+ inject: Record<string, any>
20
+ opts: Record<string, any>
21
+ throws?: Error | string | RegExp | Function
22
+ totalTimeout?: number
23
+ relativeFile?: string
24
+ addToSuite(suite: Mocha.Suite): void
25
+ applyOptions(opts: Record<string, any>): void
26
+ simplify(): Record<string, any>
27
+ toFileName(): string
28
+ addNote(type: string, note: string): void
29
+ codeceptjs: boolean
30
+ }
31
+
32
+ interface Suite extends MochaSuite {
33
+ title: string
34
+ tags: string[]
35
+ opts: Record<string, any>
36
+ totalTimeout?: number
37
+ addTest(test: Test): void
38
+ applyOptions(opts: Record<string, any>): void
39
+ codeceptjs: boolean
40
+ }
41
+ }
42
+ }