codeceptjs 4.0.0-beta.2 → 4.0.0-beta.21
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.
- package/README.md +133 -120
- package/bin/codecept.js +107 -96
- package/bin/test-server.js +64 -0
- package/docs/webapi/clearCookie.mustache +1 -1
- package/docs/webapi/click.mustache +5 -1
- package/lib/actor.js +73 -103
- package/lib/ai.js +159 -188
- package/lib/assert/empty.js +22 -24
- package/lib/assert/equal.js +30 -37
- package/lib/assert/error.js +14 -14
- package/lib/assert/include.js +43 -48
- package/lib/assert/throws.js +11 -11
- package/lib/assert/truth.js +22 -22
- package/lib/assert.js +20 -18
- package/lib/codecept.js +262 -162
- package/lib/colorUtils.js +50 -52
- package/lib/command/check.js +206 -0
- package/lib/command/configMigrate.js +56 -51
- package/lib/command/definitions.js +96 -109
- package/lib/command/dryRun.js +77 -79
- package/lib/command/generate.js +234 -194
- package/lib/command/gherkin/init.js +42 -33
- package/lib/command/gherkin/snippets.js +76 -74
- package/lib/command/gherkin/steps.js +20 -17
- package/lib/command/info.js +74 -38
- package/lib/command/init.js +301 -290
- package/lib/command/interactive.js +41 -32
- package/lib/command/list.js +28 -27
- package/lib/command/run-multiple/chunk.js +51 -48
- package/lib/command/run-multiple/collection.js +5 -5
- package/lib/command/run-multiple/run.js +5 -1
- package/lib/command/run-multiple.js +97 -97
- package/lib/command/run-rerun.js +19 -25
- package/lib/command/run-workers.js +68 -92
- package/lib/command/run.js +39 -27
- package/lib/command/utils.js +80 -64
- package/lib/command/workers/runTests.js +388 -226
- package/lib/config.js +109 -50
- package/lib/container.js +765 -261
- package/lib/data/context.js +60 -61
- package/lib/data/dataScenarioConfig.js +47 -47
- package/lib/data/dataTableArgument.js +32 -32
- package/lib/data/table.js +22 -22
- package/lib/effects.js +307 -0
- package/lib/element/WebElement.js +327 -0
- package/lib/els.js +160 -0
- package/lib/event.js +173 -163
- package/lib/globals.js +141 -0
- package/lib/heal.js +89 -85
- package/lib/helper/AI.js +131 -41
- package/lib/helper/ApiDataFactory.js +107 -75
- package/lib/helper/Appium.js +542 -404
- package/lib/helper/FileSystem.js +100 -79
- package/lib/helper/GraphQL.js +44 -43
- package/lib/helper/GraphQLDataFactory.js +52 -52
- package/lib/helper/JSONResponse.js +126 -88
- package/lib/helper/Mochawesome.js +54 -29
- package/lib/helper/Playwright.js +2547 -1316
- package/lib/helper/Puppeteer.js +1578 -1181
- package/lib/helper/REST.js +209 -68
- package/lib/helper/WebDriver.js +1482 -1342
- package/lib/helper/errors/ConnectionRefused.js +6 -6
- package/lib/helper/errors/ElementAssertion.js +11 -16
- package/lib/helper/errors/ElementNotFound.js +5 -9
- package/lib/helper/errors/RemoteBrowserConnectionRefused.js +5 -5
- package/lib/helper/extras/Console.js +11 -11
- package/lib/helper/extras/PlaywrightLocator.js +110 -0
- package/lib/helper/extras/PlaywrightPropEngine.js +18 -18
- package/lib/helper/extras/PlaywrightReactVueLocator.js +17 -8
- package/lib/helper/extras/PlaywrightRestartOpts.js +25 -11
- package/lib/helper/extras/Popup.js +22 -22
- package/lib/helper/extras/React.js +27 -28
- package/lib/helper/network/actions.js +36 -42
- package/lib/helper/network/utils.js +78 -84
- package/lib/helper/scripts/blurElement.js +5 -5
- package/lib/helper/scripts/focusElement.js +5 -5
- package/lib/helper/scripts/highlightElement.js +8 -8
- package/lib/helper/scripts/isElementClickable.js +34 -34
- package/lib/helper.js +2 -3
- package/lib/history.js +23 -19
- package/lib/hooks.js +8 -8
- package/lib/html.js +94 -104
- package/lib/index.js +38 -27
- package/lib/listener/config.js +30 -23
- package/lib/listener/emptyRun.js +54 -0
- package/lib/listener/enhancedGlobalRetry.js +110 -0
- package/lib/listener/exit.js +16 -18
- package/lib/listener/globalRetry.js +70 -0
- package/lib/listener/globalTimeout.js +181 -0
- package/lib/listener/helpers.js +76 -51
- package/lib/listener/mocha.js +10 -11
- package/lib/listener/result.js +11 -0
- package/lib/listener/retryEnhancer.js +85 -0
- package/lib/listener/steps.js +71 -59
- package/lib/listener/store.js +20 -0
- package/lib/locator.js +214 -197
- package/lib/mocha/asyncWrapper.js +274 -0
- package/lib/mocha/bdd.js +167 -0
- package/lib/mocha/cli.js +341 -0
- package/lib/mocha/factory.js +163 -0
- package/lib/mocha/featureConfig.js +89 -0
- package/lib/mocha/gherkin.js +231 -0
- package/lib/mocha/hooks.js +121 -0
- package/lib/mocha/index.js +21 -0
- package/lib/mocha/inject.js +46 -0
- package/lib/{interfaces → mocha}/scenarioConfig.js +58 -34
- package/lib/mocha/suite.js +89 -0
- package/lib/mocha/test.js +184 -0
- package/lib/mocha/types.d.ts +42 -0
- package/lib/mocha/ui.js +242 -0
- package/lib/output.js +141 -71
- package/lib/parser.js +54 -44
- package/lib/pause.js +173 -145
- package/lib/plugin/analyze.js +403 -0
- package/lib/plugin/{autoLogin.js → auth.js} +178 -79
- package/lib/plugin/autoDelay.js +36 -40
- package/lib/plugin/coverage.js +131 -78
- package/lib/plugin/customLocator.js +22 -21
- package/lib/plugin/customReporter.js +53 -0
- package/lib/plugin/enhancedRetryFailedStep.js +99 -0
- package/lib/plugin/heal.js +101 -110
- package/lib/plugin/htmlReporter.js +3648 -0
- package/lib/plugin/pageInfo.js +140 -0
- package/lib/plugin/pauseOnFail.js +12 -11
- package/lib/plugin/retryFailedStep.js +82 -47
- package/lib/plugin/screenshotOnFail.js +111 -92
- package/lib/plugin/stepByStepReport.js +159 -101
- package/lib/plugin/stepTimeout.js +20 -25
- package/lib/plugin/subtitles.js +38 -38
- package/lib/recorder.js +193 -130
- package/lib/rerun.js +94 -49
- package/lib/result.js +238 -0
- package/lib/retryCoordinator.js +207 -0
- package/lib/secret.js +20 -18
- package/lib/session.js +95 -89
- package/lib/step/base.js +239 -0
- package/lib/step/comment.js +10 -0
- package/lib/step/config.js +50 -0
- package/lib/step/func.js +46 -0
- package/lib/step/helper.js +50 -0
- package/lib/step/meta.js +99 -0
- package/lib/step/record.js +74 -0
- package/lib/step/retry.js +11 -0
- package/lib/step/section.js +55 -0
- package/lib/step.js +18 -329
- package/lib/steps.js +54 -0
- package/lib/store.js +38 -7
- package/lib/template/heal.js +3 -12
- package/lib/template/prompts/generatePageObject.js +31 -0
- package/lib/template/prompts/healStep.js +13 -0
- package/lib/template/prompts/writeStep.js +9 -0
- package/lib/test-server.js +334 -0
- package/lib/timeout.js +60 -0
- package/lib/transform.js +8 -8
- package/lib/translation.js +34 -21
- package/lib/utils/loaderCheck.js +124 -0
- package/lib/utils/mask_data.js +47 -0
- package/lib/utils/typescript.js +237 -0
- package/lib/utils.js +411 -228
- package/lib/workerStorage.js +37 -34
- package/lib/workers.js +532 -296
- package/package.json +124 -95
- package/translations/de-DE.js +5 -3
- package/translations/fr-FR.js +5 -4
- package/translations/index.js +22 -12
- package/translations/it-IT.js +4 -3
- package/translations/ja-JP.js +4 -3
- package/translations/nl-NL.js +76 -0
- package/translations/pl-PL.js +4 -3
- package/translations/pt-BR.js +4 -3
- package/translations/ru-RU.js +4 -3
- package/translations/utils.js +10 -0
- package/translations/zh-CN.js +4 -3
- package/translations/zh-TW.js +4 -3
- package/typings/index.d.ts +546 -185
- package/typings/promiseBasedTypes.d.ts +150 -875
- package/typings/types.d.ts +547 -992
- package/lib/cli.js +0 -249
- package/lib/dirname.js +0 -5
- package/lib/helper/Expect.js +0 -425
- package/lib/helper/ExpectHelper.js +0 -399
- package/lib/helper/MockServer.js +0 -223
- package/lib/helper/Nightmare.js +0 -1411
- package/lib/helper/Protractor.js +0 -1835
- package/lib/helper/SoftExpectHelper.js +0 -381
- package/lib/helper/TestCafe.js +0 -1410
- package/lib/helper/clientscripts/nightmare.js +0 -213
- package/lib/helper/testcafe/testControllerHolder.js +0 -42
- package/lib/helper/testcafe/testcafe-utils.js +0 -63
- package/lib/interfaces/bdd.js +0 -98
- package/lib/interfaces/featureConfig.js +0 -69
- package/lib/interfaces/gherkin.js +0 -195
- package/lib/listener/artifacts.js +0 -19
- package/lib/listener/retry.js +0 -68
- package/lib/listener/timeout.js +0 -109
- package/lib/mochaFactory.js +0 -110
- package/lib/plugin/allure.js +0 -15
- package/lib/plugin/commentStep.js +0 -136
- package/lib/plugin/debugErrors.js +0 -67
- package/lib/plugin/eachElement.js +0 -127
- package/lib/plugin/fakerTransform.js +0 -49
- package/lib/plugin/retryTo.js +0 -121
- package/lib/plugin/selenoid.js +0 -371
- package/lib/plugin/standardActingHelpers.js +0 -9
- package/lib/plugin/tryTo.js +0 -105
- package/lib/plugin/wdio.js +0 -246
- package/lib/scenario.js +0 -222
- package/lib/ui.js +0 -238
- 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
|
|
4
|
-
import {
|
|
5
|
-
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
|
149
|
+
async function loadConfigFile(configFile) {
|
|
150
|
+
const require = createRequire(import.meta.url)
|
|
151
|
+
const extensionName = path.extname(configFile)
|
|
147
152
|
|
|
148
|
-
|
|
153
|
+
// .conf.js config file
|
|
154
|
+
if (extensionName === '.js' || extensionName === '.ts' || extensionName === '.cjs') {
|
|
155
|
+
let configModule
|
|
149
156
|
try {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
}
|