codeceptjs 4.0.0-beta.2 → 4.0.0-beta.20

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 (209) 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 +262 -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 +301 -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 +109 -50
  39. package/lib/container.js +641 -261
  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/loaderCheck.js +124 -0
  157. package/lib/utils/mask_data.js +47 -0
  158. package/lib/utils/typescript.js +237 -0
  159. package/lib/utils.js +411 -228
  160. package/lib/workerStorage.js +37 -34
  161. package/lib/workers.js +532 -296
  162. package/package.json +124 -95
  163. package/translations/de-DE.js +5 -3
  164. package/translations/fr-FR.js +5 -4
  165. package/translations/index.js +22 -12
  166. package/translations/it-IT.js +4 -3
  167. package/translations/ja-JP.js +4 -3
  168. package/translations/nl-NL.js +76 -0
  169. package/translations/pl-PL.js +4 -3
  170. package/translations/pt-BR.js +4 -3
  171. package/translations/ru-RU.js +4 -3
  172. package/translations/utils.js +10 -0
  173. package/translations/zh-CN.js +4 -3
  174. package/translations/zh-TW.js +4 -3
  175. package/typings/index.d.ts +546 -185
  176. package/typings/promiseBasedTypes.d.ts +150 -875
  177. package/typings/types.d.ts +547 -992
  178. package/lib/cli.js +0 -249
  179. package/lib/dirname.js +0 -5
  180. package/lib/helper/Expect.js +0 -425
  181. package/lib/helper/ExpectHelper.js +0 -399
  182. package/lib/helper/MockServer.js +0 -223
  183. package/lib/helper/Nightmare.js +0 -1411
  184. package/lib/helper/Protractor.js +0 -1835
  185. package/lib/helper/SoftExpectHelper.js +0 -381
  186. package/lib/helper/TestCafe.js +0 -1410
  187. package/lib/helper/clientscripts/nightmare.js +0 -213
  188. package/lib/helper/testcafe/testControllerHolder.js +0 -42
  189. package/lib/helper/testcafe/testcafe-utils.js +0 -63
  190. package/lib/interfaces/bdd.js +0 -98
  191. package/lib/interfaces/featureConfig.js +0 -69
  192. package/lib/interfaces/gherkin.js +0 -195
  193. package/lib/listener/artifacts.js +0 -19
  194. package/lib/listener/retry.js +0 -68
  195. package/lib/listener/timeout.js +0 -109
  196. package/lib/mochaFactory.js +0 -110
  197. package/lib/plugin/allure.js +0 -15
  198. package/lib/plugin/commentStep.js +0 -136
  199. package/lib/plugin/debugErrors.js +0 -67
  200. package/lib/plugin/eachElement.js +0 -127
  201. package/lib/plugin/fakerTransform.js +0 -49
  202. package/lib/plugin/retryTo.js +0 -121
  203. package/lib/plugin/selenoid.js +0 -371
  204. package/lib/plugin/standardActingHelpers.js +0 -9
  205. package/lib/plugin/tryTo.js +0 -105
  206. package/lib/plugin/wdio.js +0 -246
  207. package/lib/scenario.js +0 -222
  208. package/lib/ui.js +0 -238
  209. package/lib/within.js +0 -70
package/lib/config.js CHANGED
@@ -1,9 +1,8 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import importSync from 'import-sync';
4
- import {
5
- fileExists, isFile, deepMerge, deepClone,
6
- } from './utils.js';
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import { createRequire } from 'module'
4
+ import { fileExists, isFile, deepMerge, deepClone } from './utils.js'
5
+ import { transpileTypeScript, cleanupTempFiles } from './utils/typescript.js'
7
6
 
8
7
  const defaultConfig = {
9
8
  output: './_output',
@@ -31,18 +30,12 @@ const defaultConfig = {
31
30
  timeout: 0,
32
31
  },
33
32
  ],
34
- };
33
+ }
35
34
 
36
- let hooks = [];
37
- let config = {};
35
+ let hooks = []
36
+ let config = {}
38
37
 
39
- const configFileNames = [
40
- 'codecept.config.js',
41
- 'codecept.conf.js',
42
- 'codecept.js',
43
- 'codecept.config.ts',
44
- 'codecept.conf.ts',
45
- ];
38
+ const configFileNames = ['codecept.config.js', 'codecept.conf.js', 'codecept.js', 'codecept.config.cjs', 'codecept.conf.cjs', 'codecept.config.ts', 'codecept.conf.ts']
46
39
 
47
40
  /**
48
41
  * Current configuration
@@ -55,9 +48,9 @@ class Config {
55
48
  * @return {Object<string, *>}
56
49
  */
57
50
  static create(newConfig) {
58
- config = deepMerge(deepClone(defaultConfig), newConfig);
59
- hooks.forEach(f => f(config));
60
- return config;
51
+ config = deepMerge(deepClone(defaultConfig), newConfig)
52
+ hooks.forEach(f => f(config))
53
+ return config
61
54
  }
62
55
 
63
56
  /**
@@ -73,34 +66,45 @@ class Config {
73
66
  * @param {string} configFile
74
67
  * @return {*}
75
68
  */
76
- static load(configFile) {
77
- configFile = path.resolve(configFile || '.');
69
+ static async load(configFile) {
70
+ configFile = path.resolve(configFile || '.')
78
71
 
79
72
  if (!fileExists(configFile)) {
80
- configFile = configFile.replace('.js', '.ts');
81
-
82
- if (!fileExists(configFile)) {
83
- throw new Error(`Config file ${configFile} does not exist. Execute 'codeceptjs init' to create config`);
73
+ // Try different extensions if the file doesn't exist
74
+ const extensions = ['.ts', '.cjs', '.mjs']
75
+ let found = false
76
+
77
+ for (const ext of extensions) {
78
+ const altConfig = configFile.replace(/\.js$/, ext)
79
+ if (fileExists(altConfig)) {
80
+ configFile = altConfig
81
+ found = true
82
+ break
83
+ }
84
+ }
85
+
86
+ if (!found) {
87
+ throw new Error(`Config file ${configFile} does not exist. Execute 'codeceptjs init' to create config`)
84
88
  }
85
89
  }
86
90
 
87
91
  // is config file
88
92
  if (isFile(configFile)) {
89
- return loadConfigFile(configFile);
93
+ return await loadConfigFile(configFile)
90
94
  }
91
95
 
92
96
  for (const name of configFileNames) {
93
97
  // is path to directory
94
- const jsConfig = path.join(configFile, name);
98
+ const jsConfig = path.join(configFile, name)
95
99
 
96
100
  if (isFile(jsConfig)) {
97
- return loadConfigFile(jsConfig);
101
+ return await loadConfigFile(jsConfig)
98
102
  }
99
103
  }
100
104
 
101
- const configPaths = configFileNames.map(name => path.join(configFile, name)).join(' or ');
105
+ const configPaths = configFileNames.map(name => path.join(configFile, name)).join(' or ')
102
106
 
103
- throw new Error(`Can not load config from ${configPaths}\nCodeceptJS is not initialized in this dir. Execute 'codeceptjs init' to start`);
107
+ throw new Error(`Can not load config from ${configPaths}\nCodeceptJS is not initialized in this dir. Execute 'codeceptjs init' to start`)
104
108
  }
105
109
 
106
110
  /**
@@ -111,13 +115,13 @@ class Config {
111
115
  */
112
116
  static get(key, val) {
113
117
  if (key) {
114
- return config[key] || val;
118
+ return config[key] || val
115
119
  }
116
- return config;
120
+ return config
117
121
  }
118
122
 
119
123
  static addHook(fn) {
120
- hooks.push(fn);
124
+ hooks.push(fn)
121
125
  }
122
126
 
123
127
  /**
@@ -127,7 +131,7 @@ class Config {
127
131
  * @return {Object<string, *>}
128
132
  */
129
133
  static append(additionalConfig) {
130
- return config = deepMerge(config, additionalConfig);
134
+ return (config = deepMerge(config, additionalConfig))
131
135
  }
132
136
 
133
137
  /**
@@ -135,34 +139,89 @@ class Config {
135
139
  * @return {Object<string, *>}
136
140
  */
137
141
  static reset() {
138
- hooks = [];
139
- return config = { ...defaultConfig };
142
+ hooks = []
143
+ return (config = { ...defaultConfig })
140
144
  }
141
145
  }
142
146
 
143
- export default Config;
147
+ export default Config
144
148
 
145
- function loadConfigFile(configFile) {
146
- const extensionName = path.extname(configFile);
149
+ async function loadConfigFile(configFile) {
150
+ const require = createRequire(import.meta.url)
151
+ const extensionName = path.extname(configFile)
147
152
 
148
- if (extensionName === '.ts') {
153
+ // .conf.js config file
154
+ if (extensionName === '.js' || extensionName === '.ts' || extensionName === '.cjs') {
155
+ let configModule
149
156
  try {
150
- require('ts-node/register');
151
- } catch (err) {
152
- console.log('ts-node package is required to parse codecept.conf.ts config correctly');
157
+ // For .ts files, try to compile and load as JavaScript
158
+ if (extensionName === '.ts') {
159
+ try {
160
+ // Use the TypeScript transpilation utility
161
+ const typescript = require('typescript')
162
+ const { tempFile, allTempFiles } = await transpileTypeScript(configFile, typescript)
163
+
164
+ try {
165
+ configModule = await import(tempFile)
166
+ cleanupTempFiles(allTempFiles)
167
+ } catch (err) {
168
+ cleanupTempFiles(allTempFiles)
169
+ throw err
170
+ }
171
+ } catch (tsError) {
172
+ // If TypeScript compilation fails, fallback to ts-node
173
+ try {
174
+ require('ts-node/register')
175
+ configModule = require(configFile)
176
+ } catch (tsNodeError) {
177
+ throw new Error(`Failed to load TypeScript config: ${tsError.message}`)
178
+ }
179
+ }
180
+ } else {
181
+ // Try ESM import first for JS files
182
+ configModule = await import(configFile)
183
+ }
184
+ } catch (importError) {
185
+ try {
186
+ // Fall back to CommonJS require for .js/.cjs files
187
+ if (extensionName !== '.ts') {
188
+ configModule = require(configFile)
189
+ } else {
190
+ throw importError
191
+ }
192
+ } catch (requireError) {
193
+ throw new Error(`Failed to load config file ${configFile}: ${importError.message}`)
194
+ }
153
195
  }
154
- }
155
196
 
156
- // .conf.js config file
157
- if (extensionName === '.js' || extensionName === '.ts' || extensionName === '.cjs') {
158
- const { config } = importSync(configFile);
159
- return Config.create(config);
197
+ const rawConfig = configModule.config || configModule.default?.config || configModule.default || configModule
198
+
199
+ // Process helpers to extract imported classes
200
+ if (rawConfig.helpers) {
201
+ const processedHelpers = {}
202
+ for (const [helperName, helperConfig] of Object.entries(rawConfig.helpers)) {
203
+ // Check if the helper name itself is a class (ESM import)
204
+ if (typeof helperName === 'function' && helperName.prototype) {
205
+ // This is an imported class, use its constructor name
206
+ const className = helperName.name
207
+ processedHelpers[className] = {
208
+ ...helperConfig,
209
+ _helperClass: helperName,
210
+ }
211
+ } else {
212
+ processedHelpers[helperName] = helperConfig
213
+ }
214
+ }
215
+ rawConfig.helpers = processedHelpers
216
+ }
217
+
218
+ return Config.create(rawConfig)
160
219
  }
161
220
 
162
221
  // json config provided
163
222
  if (extensionName === '.json') {
164
- return Config.create(JSON.parse(fs.readFileSync(configFile, 'utf8')));
223
+ return Config.create(JSON.parse(fs.readFileSync(configFile, 'utf8')))
165
224
  }
166
225
 
167
- throw new Error(`Config file ${configFile} can't be loaded`);
226
+ throw new Error(`Config file ${configFile} can't be loaded`)
168
227
  }