codeceptjs 3.7.6-beta.4 → 4.0.0-beta.10.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.
- package/README.md +1 -3
- package/bin/codecept.js +51 -53
- package/bin/test-server.js +14 -3
- package/docs/webapi/click.mustache +5 -1
- package/lib/actor.js +15 -11
- package/lib/ai.js +72 -107
- package/lib/assert/empty.js +9 -8
- package/lib/assert/equal.js +15 -17
- package/lib/assert/error.js +2 -2
- package/lib/assert/include.js +9 -11
- package/lib/assert/throws.js +1 -1
- package/lib/assert/truth.js +8 -5
- package/lib/assert.js +18 -18
- package/lib/codecept.js +102 -75
- package/lib/colorUtils.js +48 -50
- package/lib/command/check.js +32 -27
- package/lib/command/configMigrate.js +11 -10
- package/lib/command/definitions.js +16 -10
- package/lib/command/dryRun.js +16 -16
- package/lib/command/generate.js +62 -27
- package/lib/command/gherkin/init.js +36 -38
- package/lib/command/gherkin/snippets.js +14 -14
- package/lib/command/gherkin/steps.js +21 -18
- package/lib/command/info.js +8 -8
- package/lib/command/init.js +36 -29
- package/lib/command/interactive.js +11 -10
- package/lib/command/list.js +10 -9
- package/lib/command/run-multiple/chunk.js +5 -5
- package/lib/command/run-multiple/collection.js +5 -5
- package/lib/command/run-multiple/run.js +3 -3
- package/lib/command/run-multiple.js +16 -13
- package/lib/command/run-rerun.js +6 -7
- package/lib/command/run-workers.js +24 -9
- package/lib/command/run.js +23 -8
- package/lib/command/utils.js +20 -18
- package/lib/command/workers/runTests.js +197 -114
- package/lib/config.js +124 -51
- package/lib/container.js +438 -87
- package/lib/data/context.js +6 -5
- package/lib/data/dataScenarioConfig.js +1 -1
- package/lib/data/dataTableArgument.js +1 -1
- package/lib/data/table.js +1 -1
- package/lib/effects.js +94 -10
- package/lib/element/WebElement.js +2 -2
- package/lib/els.js +11 -9
- package/lib/event.js +11 -10
- package/lib/globals.js +141 -0
- package/lib/heal.js +12 -12
- package/lib/helper/AI.js +11 -11
- package/lib/helper/ApiDataFactory.js +50 -19
- package/lib/helper/Appium.js +19 -27
- package/lib/helper/FileSystem.js +32 -12
- package/lib/helper/GraphQL.js +3 -3
- package/lib/helper/GraphQLDataFactory.js +4 -4
- package/lib/helper/JSONResponse.js +25 -29
- package/lib/helper/Mochawesome.js +7 -4
- package/lib/helper/Playwright.js +902 -164
- package/lib/helper/Puppeteer.js +383 -76
- package/lib/helper/REST.js +29 -12
- package/lib/helper/WebDriver.js +268 -61
- package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
- 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 +18 -9
- package/lib/helper/extras/PlaywrightRestartOpts.js +34 -23
- package/lib/helper/extras/Popup.js +1 -1
- package/lib/helper/extras/React.js +29 -30
- package/lib/helper/network/actions.js +29 -44
- package/lib/helper/network/utils.js +76 -83
- package/lib/helper/scripts/blurElement.js +6 -6
- package/lib/helper/scripts/focusElement.js +6 -6
- package/lib/helper/scripts/highlightElement.js +9 -9
- package/lib/helper/scripts/isElementClickable.js +34 -34
- package/lib/helper.js +2 -1
- package/lib/history.js +23 -20
- package/lib/hooks.js +10 -10
- package/lib/html.js +90 -100
- package/lib/index.js +48 -21
- package/lib/listener/config.js +19 -12
- package/lib/listener/emptyRun.js +6 -7
- package/lib/listener/enhancedGlobalRetry.js +6 -6
- package/lib/listener/exit.js +4 -3
- package/lib/listener/globalRetry.js +5 -5
- package/lib/listener/globalTimeout.js +30 -14
- package/lib/listener/helpers.js +39 -14
- package/lib/listener/mocha.js +3 -4
- package/lib/listener/result.js +4 -5
- package/lib/listener/retryEnhancer.js +3 -3
- package/lib/listener/steps.js +8 -7
- package/lib/listener/store.js +3 -3
- package/lib/locator.js +213 -192
- package/lib/mocha/asyncWrapper.js +105 -62
- package/lib/mocha/bdd.js +99 -13
- package/lib/mocha/cli.js +59 -26
- package/lib/mocha/factory.js +78 -19
- package/lib/mocha/featureConfig.js +1 -1
- package/lib/mocha/gherkin.js +56 -24
- package/lib/mocha/hooks.js +12 -3
- package/lib/mocha/index.js +13 -4
- package/lib/mocha/inject.js +22 -5
- package/lib/mocha/scenarioConfig.js +2 -2
- package/lib/mocha/suite.js +9 -2
- package/lib/mocha/test.js +10 -7
- package/lib/mocha/ui.js +28 -18
- package/lib/output.js +10 -8
- package/lib/parser.js +44 -44
- package/lib/pause.js +15 -16
- package/lib/plugin/analyze.js +19 -12
- package/lib/plugin/auth.js +20 -21
- package/lib/plugin/autoDelay.js +12 -8
- package/lib/plugin/coverage.js +28 -11
- package/lib/plugin/customLocator.js +3 -3
- package/lib/plugin/customReporter.js +3 -2
- package/lib/plugin/enhancedRetryFailedStep.js +6 -6
- package/lib/plugin/heal.js +14 -9
- package/lib/plugin/htmlReporter.js +724 -99
- package/lib/plugin/pageInfo.js +10 -10
- package/lib/plugin/pauseOnFail.js +4 -3
- package/lib/plugin/retryFailedStep.js +48 -5
- package/lib/plugin/screenshotOnFail.js +75 -37
- package/lib/plugin/stepByStepReport.js +14 -14
- package/lib/plugin/stepTimeout.js +4 -3
- package/lib/plugin/subtitles.js +6 -5
- package/lib/recorder.js +33 -14
- package/lib/rerun.js +69 -26
- package/lib/result.js +4 -4
- package/lib/retryCoordinator.js +2 -2
- package/lib/secret.js +18 -17
- package/lib/session.js +95 -89
- package/lib/step/base.js +7 -7
- package/lib/step/comment.js +2 -2
- package/lib/step/config.js +1 -1
- package/lib/step/func.js +3 -3
- package/lib/step/helper.js +3 -3
- package/lib/step/meta.js +5 -5
- package/lib/step/record.js +11 -11
- package/lib/step/retry.js +3 -3
- package/lib/step/section.js +3 -3
- package/lib/step.js +7 -10
- package/lib/steps.js +9 -5
- package/lib/store.js +1 -1
- package/lib/template/heal.js +1 -1
- 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 +17 -6
- package/lib/timeout.js +1 -7
- package/lib/transform.js +8 -8
- package/lib/translation.js +32 -18
- package/lib/utils/mask_data.js +4 -10
- package/lib/utils.js +66 -64
- package/lib/workerStorage.js +17 -17
- package/lib/workers.js +214 -84
- package/package.json +41 -37
- package/translations/de-DE.js +2 -2
- package/translations/fr-FR.js +2 -2
- package/translations/index.js +23 -10
- package/translations/it-IT.js +2 -2
- package/translations/ja-JP.js +2 -2
- package/translations/nl-NL.js +2 -2
- package/translations/pl-PL.js +2 -2
- package/translations/pt-BR.js +2 -2
- package/translations/ru-RU.js +2 -2
- package/translations/utils.js +4 -3
- package/translations/zh-CN.js +2 -2
- package/translations/zh-TW.js +2 -2
- package/typings/index.d.ts +5 -3
- package/typings/promiseBasedTypes.d.ts +4 -0
- package/typings/types.d.ts +4 -0
- package/lib/helper/Nightmare.js +0 -1486
- package/lib/helper/Protractor.js +0 -1840
- package/lib/helper/TestCafe.js +0 -1391
- package/lib/helper/clientscripts/nightmare.js +0 -213
- package/lib/helper/testcafe/testControllerHolder.js +0 -42
- package/lib/helper/testcafe/testcafe-utils.js +0 -61
- package/lib/plugin/allure.js +0 -15
- package/lib/plugin/autoLogin.js +0 -5
- package/lib/plugin/commentStep.js +0 -141
- package/lib/plugin/eachElement.js +0 -127
- package/lib/plugin/fakerTransform.js +0 -49
- package/lib/plugin/retryTo.js +0 -16
- package/lib/plugin/selenoid.js +0 -364
- package/lib/plugin/standardActingHelpers.js +0 -6
- package/lib/plugin/tryTo.js +0 -16
- package/lib/plugin/wdio.js +0 -247
- package/lib/within.js +0 -90
package/lib/command/check.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { getConfig, getTestRoot } from './utils.js'
|
|
2
|
+
import Codecept from '../codecept.js'
|
|
3
|
+
import output from '../output.js'
|
|
4
|
+
import store from '../store.js'
|
|
5
|
+
import Container from '../container.js'
|
|
6
|
+
import figures from 'figures'
|
|
7
|
+
import chalk from 'chalk'
|
|
8
|
+
import { createTest } from '../mocha/test.js'
|
|
9
|
+
import { getMachineInfo } from './info.js'
|
|
10
|
+
import definitions from './definitions.js'
|
|
11
|
+
|
|
12
|
+
export default async function (options) {
|
|
13
13
|
const configFile = options.config
|
|
14
14
|
|
|
15
15
|
setTimeout(() => {
|
|
@@ -31,10 +31,10 @@ module.exports = async function (options) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
const testRoot = getTestRoot(configFile)
|
|
34
|
-
let config = getConfig(configFile)
|
|
34
|
+
let config = await getConfig(configFile)
|
|
35
35
|
|
|
36
36
|
try {
|
|
37
|
-
config = getConfig(configFile)
|
|
37
|
+
config = await getConfig(configFile)
|
|
38
38
|
checks['config'] = true
|
|
39
39
|
} catch (err) {
|
|
40
40
|
checks['config'] = err
|
|
@@ -45,14 +45,14 @@ module.exports = async function (options) {
|
|
|
45
45
|
let codecept
|
|
46
46
|
try {
|
|
47
47
|
codecept = new Codecept(config, options)
|
|
48
|
-
codecept.init(testRoot)
|
|
49
|
-
await
|
|
48
|
+
await codecept.init(testRoot)
|
|
49
|
+
await Container.started()
|
|
50
50
|
checks.container = true
|
|
51
51
|
} catch (err) {
|
|
52
52
|
checks.container = err
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
const standardActingHelpers =
|
|
55
|
+
const standardActingHelpers = Container.STANDARD_ACTING_HELPERS
|
|
56
56
|
|
|
57
57
|
printCheck('container', checks['container'])
|
|
58
58
|
|
|
@@ -70,12 +70,17 @@ module.exports = async function (options) {
|
|
|
70
70
|
if (codecept) {
|
|
71
71
|
try {
|
|
72
72
|
codecept.loadTests()
|
|
73
|
-
const
|
|
74
|
-
mocha
|
|
73
|
+
const files = codecept.testFiles
|
|
74
|
+
const mocha = Container.mocha()
|
|
75
|
+
mocha.files = files
|
|
75
76
|
mocha.loadFiles()
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
|
|
78
|
+
for (const suite of mocha.suite.suites) {
|
|
79
|
+
if (suite && suite.tests) {
|
|
80
|
+
numTests += suite.tests.length
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
79
84
|
if (numTests > 0) {
|
|
80
85
|
checks.tests = true
|
|
81
86
|
} else {
|
|
@@ -97,13 +102,13 @@ module.exports = async function (options) {
|
|
|
97
102
|
|
|
98
103
|
store.dryRun = true
|
|
99
104
|
|
|
100
|
-
const helpers =
|
|
105
|
+
const helpers = Container.helpers()
|
|
101
106
|
|
|
102
107
|
try {
|
|
103
108
|
if (!Object.keys(helpers).length) throw new Error('No helpers found')
|
|
104
109
|
// load helpers
|
|
105
110
|
for (const helper of Object.values(helpers)) {
|
|
106
|
-
if (helper._init) helper._init()
|
|
111
|
+
if (helper._init) await helper._init()
|
|
107
112
|
}
|
|
108
113
|
checks.helpers = true
|
|
109
114
|
} catch (err) {
|
|
@@ -112,7 +117,7 @@ module.exports = async function (options) {
|
|
|
112
117
|
|
|
113
118
|
printCheck('helpers', checks['helpers'], `${Object.keys(helpers).join(', ')}`)
|
|
114
119
|
|
|
115
|
-
const pageObjects =
|
|
120
|
+
const pageObjects = Container.support()
|
|
116
121
|
|
|
117
122
|
try {
|
|
118
123
|
if (Object.keys(pageObjects).length) {
|
|
@@ -127,10 +132,10 @@ module.exports = async function (options) {
|
|
|
127
132
|
printCheck('page objects', checks['pageObjects'], `Total: ${Object.keys(pageObjects).length} support objects`)
|
|
128
133
|
|
|
129
134
|
checks.plugins = true // how to check plugins?
|
|
130
|
-
printCheck('plugins', checks['plugins'], Object.keys(
|
|
135
|
+
printCheck('plugins', checks['plugins'], Object.keys(Container.plugins()).join(', '))
|
|
131
136
|
|
|
132
137
|
if (Object.keys(helpers).length) {
|
|
133
|
-
const suite =
|
|
138
|
+
const suite = Container.mocha().suite
|
|
134
139
|
const test = createTest('test', () => {})
|
|
135
140
|
checks.setup = true
|
|
136
141
|
for (const helper of Object.values(helpers)) {
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import colors from 'chalk'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import inquirer from 'inquirer'
|
|
4
|
+
import { mkdirp } from 'mkdirp'
|
|
5
|
+
import path from 'path'
|
|
6
|
+
import util from 'util'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
const {
|
|
10
|
-
|
|
8
|
+
import output from '../output.js'
|
|
9
|
+
const { print, success, error } = output
|
|
10
|
+
import { fileExists } from '../utils.js'
|
|
11
|
+
import { getTestRoot } from './utils.js'
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
export default function (initPath) {
|
|
13
14
|
const testsPath = getTestRoot(initPath)
|
|
14
15
|
|
|
15
16
|
print()
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
import { getConfig, getTestRoot } from './utils.js'
|
|
5
|
+
import Codecept from '../codecept.js'
|
|
6
|
+
import container from '../container.js'
|
|
7
|
+
import output from '../output.js'
|
|
8
8
|
const actingHelpers = [...container.STANDARD_ACTING_HELPERS, 'REST']
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -86,11 +86,11 @@ const helperNames = []
|
|
|
86
86
|
/** @type {Array<string>} */
|
|
87
87
|
const customHelpers = []
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
export default async function (genPath, options) {
|
|
90
90
|
const configFile = options.config || genPath
|
|
91
91
|
/** @type {string} */
|
|
92
92
|
const testsPath = getTestRoot(configFile)
|
|
93
|
-
const config = getConfig(configFile)
|
|
93
|
+
const config = await getConfig(configFile)
|
|
94
94
|
if (!config) return
|
|
95
95
|
|
|
96
96
|
/** @type {Object<string, string>} */
|
|
@@ -106,7 +106,8 @@ module.exports = function (genPath, options) {
|
|
|
106
106
|
const targetFolderPath = (options.output && getTestRoot(options.output)) || testsPath
|
|
107
107
|
|
|
108
108
|
const codecept = new Codecept(config, {})
|
|
109
|
-
codecept.init(testsPath)
|
|
109
|
+
await codecept.init(testsPath)
|
|
110
|
+
await container.started()
|
|
110
111
|
|
|
111
112
|
const helpers = container.helpers()
|
|
112
113
|
const translations = container.translation()
|
|
@@ -229,7 +230,12 @@ function getImportString(testsPath, targetFolderPath, pathsToType, pathsToValue)
|
|
|
229
230
|
|
|
230
231
|
for (const name in pathsToType) {
|
|
231
232
|
const relativePath = getPath(pathsToType[name], targetFolderPath, testsPath)
|
|
232
|
-
|
|
233
|
+
// For ESM modules with default exports, we need to access the default export type
|
|
234
|
+
if (relativePath.endsWith('.js')) {
|
|
235
|
+
importStrings.push(`type ${name} = typeof import('${relativePath}')['default'];`)
|
|
236
|
+
} else {
|
|
237
|
+
importStrings.push(`type ${name} = typeof import('${relativePath}');`)
|
|
238
|
+
}
|
|
233
239
|
}
|
|
234
240
|
|
|
235
241
|
for (const name in pathsToValue) {
|
package/lib/command/dryRun.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { getConfig, getTestRoot } from './utils.js'
|
|
2
|
+
import Config from '../config.js'
|
|
3
|
+
import Codecept from '../codecept.js'
|
|
4
|
+
import output from '../output.js'
|
|
5
|
+
import event from '../event.js'
|
|
6
|
+
import store from '../store.js'
|
|
7
|
+
import Container from '../container.js'
|
|
8
|
+
|
|
9
|
+
export default async function (test, options) {
|
|
10
10
|
if (options.grep) process.env.grep = options.grep
|
|
11
11
|
const configFile = options.config
|
|
12
12
|
let codecept
|
|
13
13
|
|
|
14
14
|
const testRoot = getTestRoot(configFile)
|
|
15
|
-
let config = getConfig(configFile)
|
|
15
|
+
let config = await getConfig(configFile)
|
|
16
16
|
if (options.override) {
|
|
17
17
|
config = Config.append(JSON.parse(options.override))
|
|
18
18
|
}
|
|
@@ -27,7 +27,7 @@ module.exports = async function (test, options) {
|
|
|
27
27
|
|
|
28
28
|
try {
|
|
29
29
|
codecept = new Codecept(config, options)
|
|
30
|
-
codecept.init(testRoot)
|
|
30
|
+
await codecept.init(testRoot)
|
|
31
31
|
|
|
32
32
|
if (options.bootstrap) await codecept.bootstrap()
|
|
33
33
|
|
|
@@ -35,20 +35,20 @@ module.exports = async function (test, options) {
|
|
|
35
35
|
store.dryRun = true
|
|
36
36
|
|
|
37
37
|
if (!options.steps && !options.verbose && !options.debug) {
|
|
38
|
-
printTests(codecept.testFiles)
|
|
38
|
+
await printTests(codecept.testFiles)
|
|
39
39
|
return
|
|
40
40
|
}
|
|
41
41
|
event.dispatcher.on(event.all.result, printFooter)
|
|
42
|
-
codecept.run(test)
|
|
42
|
+
await codecept.run(test)
|
|
43
43
|
} catch (err) {
|
|
44
44
|
console.error(err)
|
|
45
45
|
process.exit(1)
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
function printTests(files) {
|
|
50
|
-
const figures =
|
|
51
|
-
const colors =
|
|
49
|
+
async function printTests(files) {
|
|
50
|
+
const { default: figures } = await import('figures')
|
|
51
|
+
const { default: colors } = await import('chalk')
|
|
52
52
|
|
|
53
53
|
output.print(output.styles.debug(`Tests from ${global.codecept_dir}:`))
|
|
54
54
|
output.print()
|
package/lib/command/generate.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import colors from 'chalk'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import inquirer from 'inquirer'
|
|
4
|
+
import { mkdirp } from 'mkdirp'
|
|
5
|
+
import path from 'path'
|
|
6
|
+
import { fileExists, ucfirst, lcfirst, beautify } from '../utils.js'
|
|
7
|
+
import output from '../output.js'
|
|
8
|
+
import generateDefinitions from './definitions.js'
|
|
9
|
+
import { getConfig, getTestRoot, safeFileWrite, readConfig } from './utils.js'
|
|
10
10
|
|
|
11
11
|
let extension = 'js'
|
|
12
12
|
|
|
@@ -18,10 +18,10 @@ Scenario('test something', async ({ {{actor}} }) => {
|
|
|
18
18
|
`
|
|
19
19
|
|
|
20
20
|
// generates empty test
|
|
21
|
-
|
|
21
|
+
export async function test(genPath) {
|
|
22
22
|
const testsPath = getTestRoot(genPath)
|
|
23
23
|
global.codecept_dir = testsPath
|
|
24
|
-
const config = getConfig(testsPath)
|
|
24
|
+
const config = await getConfig(testsPath)
|
|
25
25
|
if (!config) return
|
|
26
26
|
|
|
27
27
|
output.print('Creating a new test...')
|
|
@@ -46,7 +46,7 @@ module.exports.test = function (genPath) {
|
|
|
46
46
|
},
|
|
47
47
|
},
|
|
48
48
|
])
|
|
49
|
-
.then(result => {
|
|
49
|
+
.then(async result => {
|
|
50
50
|
const testFilePath = path.dirname(path.join(testsPath, config.tests)).replace(/\*\*$/, '')
|
|
51
51
|
let testFile = path.join(testFilePath, result.filename)
|
|
52
52
|
const ext = path.extname(testFile)
|
|
@@ -55,8 +55,9 @@ module.exports.test = function (genPath) {
|
|
|
55
55
|
if (!fileExists(dir)) mkdirp.sync(dir)
|
|
56
56
|
let testContent = testTemplate.replace('{{feature}}', result.feature)
|
|
57
57
|
|
|
58
|
-
const
|
|
59
|
-
container.
|
|
58
|
+
const containerModule = await import('../container.js')
|
|
59
|
+
const container = containerModule.default || containerModule
|
|
60
|
+
await container.create(config, {})
|
|
60
61
|
// translate scenario test
|
|
61
62
|
if (container.translation().loaded) {
|
|
62
63
|
const vocabulary = container.translation().vocabulary
|
|
@@ -76,7 +77,7 @@ module.exports.test = function (genPath) {
|
|
|
76
77
|
|
|
77
78
|
const pageObjectTemplate = `const { I } = inject();
|
|
78
79
|
|
|
79
|
-
|
|
80
|
+
export default {
|
|
80
81
|
|
|
81
82
|
// insert your locators and methods here
|
|
82
83
|
}
|
|
@@ -101,13 +102,13 @@ class {{name}} {
|
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
// For inheritance
|
|
104
|
-
|
|
105
|
-
export
|
|
105
|
+
export default new {{name}}();
|
|
106
|
+
export { {{name}} };
|
|
106
107
|
`
|
|
107
108
|
|
|
108
|
-
|
|
109
|
+
export async function pageObject(genPath, opts) {
|
|
109
110
|
const testsPath = getTestRoot(genPath)
|
|
110
|
-
const config = getConfig(testsPath)
|
|
111
|
+
const config = await getConfig(testsPath)
|
|
111
112
|
const kind = opts.T || 'page'
|
|
112
113
|
if (!config) return
|
|
113
114
|
|
|
@@ -155,7 +156,7 @@ module.exports.pageObject = function (genPath, opts) {
|
|
|
155
156
|
// relative path
|
|
156
157
|
actorPath = path.relative(dir, path.dirname(path.join(testsPath, actorPath))) + actorPath.substring(1) // get an upper level
|
|
157
158
|
}
|
|
158
|
-
actor = `
|
|
159
|
+
actor = `import('${actorPath}')`
|
|
159
160
|
}
|
|
160
161
|
|
|
161
162
|
const name = lcfirst(result.name) + ucfirst(kind)
|
|
@@ -197,7 +198,7 @@ module.exports.pageObject = function (genPath, opts) {
|
|
|
197
198
|
})
|
|
198
199
|
}
|
|
199
200
|
|
|
200
|
-
const helperTemplate = `
|
|
201
|
+
const helperTemplate = `import Helper from '@codeceptjs/helper';
|
|
201
202
|
|
|
202
203
|
class {{name}} extends Helper {
|
|
203
204
|
|
|
@@ -222,10 +223,10 @@ class {{name}} extends Helper {
|
|
|
222
223
|
|
|
223
224
|
}
|
|
224
225
|
|
|
225
|
-
|
|
226
|
+
export default {{name}};
|
|
226
227
|
`
|
|
227
228
|
|
|
228
|
-
|
|
229
|
+
export async function helper(genPath) {
|
|
229
230
|
const testsPath = getTestRoot(genPath)
|
|
230
231
|
|
|
231
232
|
output.print('Creating a new helper')
|
|
@@ -265,9 +266,11 @@ helpers: {
|
|
|
265
266
|
})
|
|
266
267
|
}
|
|
267
268
|
|
|
269
|
+
import { fileURLToPath } from 'url'
|
|
270
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
268
271
|
const healTemplate = fs.readFileSync(path.join(__dirname, '../template/heal.js'), 'utf8').toString()
|
|
269
272
|
|
|
270
|
-
|
|
273
|
+
export async function heal(genPath) {
|
|
271
274
|
const testsPath = getTestRoot(genPath)
|
|
272
275
|
|
|
273
276
|
let configFile = path.join(testsPath, `codecept.conf.${extension}`)
|
|
@@ -282,10 +285,10 @@ module.exports.heal = function (genPath) {
|
|
|
282
285
|
output.print('Require this file in the config file and enable heal plugin:')
|
|
283
286
|
output.print('--------------------------')
|
|
284
287
|
output.print(`
|
|
285
|
-
|
|
288
|
+
import './heal.js'
|
|
286
289
|
|
|
287
|
-
|
|
288
|
-
// ...
|
|
290
|
+
export const config = {
|
|
291
|
+
// ...
|
|
289
292
|
plugins: {
|
|
290
293
|
heal: {
|
|
291
294
|
enabled: true
|
|
@@ -298,3 +301,35 @@ exports.config = {
|
|
|
298
301
|
if (!safeFileWrite(healFile, healTemplate)) return
|
|
299
302
|
output.success(`Heal recipes were created in ${healFile}`)
|
|
300
303
|
}
|
|
304
|
+
|
|
305
|
+
export async function prompt(promptName, genPath) {
|
|
306
|
+
if (!promptName) {
|
|
307
|
+
output.error('Please specify prompt name: writeStep, healStep, or generatePageObject')
|
|
308
|
+
output.print('Usage: npx codeceptjs generate:prompt <promptName>')
|
|
309
|
+
return
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const validPrompts = ['writeStep', 'healStep', 'generatePageObject']
|
|
313
|
+
if (!validPrompts.includes(promptName)) {
|
|
314
|
+
output.error(`Invalid prompt name: ${promptName}`)
|
|
315
|
+
output.print(`Valid prompts: ${validPrompts.join(', ')}`)
|
|
316
|
+
return
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const testsPath = getTestRoot(genPath)
|
|
320
|
+
|
|
321
|
+
const promptsDir = path.join(testsPath, 'prompts')
|
|
322
|
+
if (!fileExists(promptsDir)) {
|
|
323
|
+
mkdirp.sync(promptsDir)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const templatePath = path.join(__dirname, `../template/prompts/${promptName}.js`)
|
|
327
|
+
const promptContent = fs.readFileSync(templatePath, 'utf8')
|
|
328
|
+
|
|
329
|
+
const promptFile = path.join(promptsDir, `${promptName}.${extension}`)
|
|
330
|
+
if (!safeFileWrite(promptFile, promptContent)) return
|
|
331
|
+
|
|
332
|
+
output.success(`Prompt ${promptName} was created in ${promptFile}`)
|
|
333
|
+
output.print('Customize this prompt to fit your needs.')
|
|
334
|
+
output.print('This prompt will be automatically loaded when AI features are enabled.')
|
|
335
|
+
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import { mkdirp } from 'mkdirp'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
getConfig, getTestRoot, updateConfig, safeFileWrite, findConfigFile,
|
|
8
|
-
} = require('../utils');
|
|
4
|
+
import output from '../../output.js'
|
|
5
|
+
import { fileExists } from '../../utils.js'
|
|
6
|
+
import { getConfig, getTestRoot, updateConfig, safeFileWrite, findConfigFile } from '../utils.js'
|
|
9
7
|
|
|
10
8
|
const featureFile = `Feature: Business rules
|
|
11
9
|
In order to achieve my goals
|
|
@@ -14,7 +12,7 @@ const featureFile = `Feature: Business rules
|
|
|
14
12
|
|
|
15
13
|
Scenario: do something
|
|
16
14
|
Given I have a defined step
|
|
17
|
-
|
|
15
|
+
`
|
|
18
16
|
|
|
19
17
|
const stepsFile = `const { I } = inject();
|
|
20
18
|
// Add in your custom step files
|
|
@@ -22,60 +20,60 @@ const stepsFile = `const { I } = inject();
|
|
|
22
20
|
Given('I have a defined step', () => {
|
|
23
21
|
// TODO: replace with your own step
|
|
24
22
|
});
|
|
25
|
-
|
|
23
|
+
`
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
const testsPath = getTestRoot(genPath)
|
|
29
|
-
const configFile = findConfigFile(testsPath)
|
|
25
|
+
export default async function (genPath) {
|
|
26
|
+
const testsPath = getTestRoot(genPath)
|
|
27
|
+
const configFile = findConfigFile(testsPath)
|
|
30
28
|
|
|
31
29
|
if (!configFile) {
|
|
32
|
-
output.error(
|
|
33
|
-
|
|
34
|
-
);
|
|
35
|
-
process.exit(1);
|
|
30
|
+
output.error("Can't initialize Gherkin. This command must be run in an already initialized project.")
|
|
31
|
+
process.exit(1)
|
|
36
32
|
}
|
|
37
33
|
|
|
38
|
-
const config = getConfig(testsPath)
|
|
39
|
-
const extension = path.extname(configFile).substring(1)
|
|
34
|
+
const config = await getConfig(testsPath)
|
|
35
|
+
const extension = path.extname(configFile).substring(1)
|
|
40
36
|
|
|
41
|
-
output.print('Initializing Gherkin (Cucumber BDD) for CodeceptJS')
|
|
42
|
-
output.print('--------------------------')
|
|
37
|
+
output.print('Initializing Gherkin (Cucumber BDD) for CodeceptJS')
|
|
38
|
+
output.print('--------------------------')
|
|
43
39
|
|
|
44
40
|
if (config.gherkin && config.gherkin.steps) {
|
|
45
|
-
output.error('Gherkin is already initialized in this project. See `gherkin` section in the config')
|
|
46
|
-
process.exit(1)
|
|
41
|
+
output.error('Gherkin is already initialized in this project. See `gherkin` section in the config')
|
|
42
|
+
process.exit(1)
|
|
47
43
|
}
|
|
48
44
|
|
|
49
|
-
let dir
|
|
50
|
-
dir = path.join(testsPath, 'features')
|
|
45
|
+
let dir
|
|
46
|
+
dir = path.join(testsPath, 'features')
|
|
51
47
|
if (!fileExists(dir)) {
|
|
52
|
-
mkdirp.sync(dir)
|
|
53
|
-
|
|
48
|
+
mkdirp.sync(dir)
|
|
49
|
+
// Use relative path for output
|
|
50
|
+
const relativeDir = path.relative(process.cwd(), dir)
|
|
51
|
+
output.success(`Created ${relativeDir}, place your *.feature files in it`)
|
|
54
52
|
}
|
|
55
53
|
|
|
56
54
|
if (safeFileWrite(path.join(dir, 'basic.feature'), featureFile)) {
|
|
57
|
-
output.success('Created sample feature file: features/basic.feature')
|
|
55
|
+
output.success('Created sample feature file: features/basic.feature')
|
|
58
56
|
}
|
|
59
57
|
|
|
60
|
-
dir = path.join(testsPath, 'step_definitions')
|
|
58
|
+
dir = path.join(testsPath, 'step_definitions')
|
|
61
59
|
if (!fileExists(dir)) {
|
|
62
|
-
mkdirp.sync(dir)
|
|
63
|
-
|
|
60
|
+
mkdirp.sync(dir)
|
|
61
|
+
// Use relative path for output
|
|
62
|
+
const relativeDir = path.relative(process.cwd(), dir)
|
|
63
|
+
output.success(`Created ${relativeDir}, place step definitions into it`)
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
if (safeFileWrite(path.join(dir, `steps.${extension}`), stepsFile)) {
|
|
67
|
-
output.success(
|
|
68
|
-
`Created sample steps file: step_definitions/steps.${extension}`,
|
|
69
|
-
);
|
|
67
|
+
output.success(`Created sample steps file: step_definitions/steps.${extension}`)
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
config.gherkin = {
|
|
73
71
|
features: './features/*.feature',
|
|
74
72
|
steps: [`./step_definitions/steps.${extension}`],
|
|
75
|
-
}
|
|
73
|
+
}
|
|
76
74
|
|
|
77
|
-
updateConfig(testsPath, config, extension)
|
|
75
|
+
updateConfig(testsPath, config, extension)
|
|
78
76
|
|
|
79
|
-
output.success('Gherkin setup is done.')
|
|
80
|
-
output.success('Start writing feature files and implement corresponding steps.')
|
|
81
|
-
}
|
|
77
|
+
output.success('Gherkin setup is done.')
|
|
78
|
+
output.success('Start writing feature files and implement corresponding steps.')
|
|
79
|
+
}
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import escapeStringRegexp from 'escape-string-regexp'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import Gherkin from '@cucumber/gherkin'
|
|
4
|
+
import { IdGenerator } from '@cucumber/messages'
|
|
5
|
+
import { globSync } from 'glob'
|
|
6
|
+
import fsPath from 'path'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
import { getConfig, getTestRoot } from '../utils.js'
|
|
9
|
+
import Codecept from '../../codecept.js'
|
|
10
|
+
import output from '../../output.js'
|
|
11
|
+
import { matchStep } from '../../mocha/bdd.js'
|
|
12
12
|
|
|
13
|
-
const uuidFn =
|
|
13
|
+
const uuidFn = IdGenerator.uuid()
|
|
14
14
|
const builder = new Gherkin.AstBuilder(uuidFn)
|
|
15
15
|
const matcher = new Gherkin.GherkinClassicTokenMatcher()
|
|
16
16
|
const parser = new Gherkin.Parser(builder, matcher)
|
|
17
17
|
parser.stopAtFirstError = false
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
export default async function (genPath, options) {
|
|
20
20
|
const configFile = options.config || genPath
|
|
21
21
|
const testsPath = getTestRoot(configFile)
|
|
22
|
-
const config = getConfig(configFile)
|
|
22
|
+
const config = await getConfig(configFile)
|
|
23
23
|
if (!config) return
|
|
24
24
|
|
|
25
25
|
const codecept = new Codecept(config, {})
|
|
26
|
-
codecept.init(testsPath)
|
|
26
|
+
await codecept.init(testsPath)
|
|
27
27
|
|
|
28
28
|
if (!config.gherkin) {
|
|
29
29
|
output.error('Gherkin is not enabled in config. Run `codecept gherkin:init` to enable it')
|
|
@@ -1,25 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { getConfig, getTestRoot } from '../utils.js'
|
|
2
|
+
import Codecept from '../../codecept.js'
|
|
3
|
+
import output from '../../output.js'
|
|
4
|
+
import { getSteps, clearSteps } from '../../mocha/bdd.js'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
const configFile = options.config || genPath
|
|
8
|
-
const testsPath = getTestRoot(configFile)
|
|
9
|
-
const config = getConfig(configFile)
|
|
10
|
-
if (!config) return
|
|
6
|
+
export default async function (genPath, options) {
|
|
7
|
+
const configFile = options.config || genPath
|
|
8
|
+
const testsPath = getTestRoot(configFile)
|
|
9
|
+
const config = await getConfig(configFile)
|
|
10
|
+
if (!config) return
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
// Clear any previously loaded steps
|
|
13
|
+
clearSteps()
|
|
14
|
+
|
|
15
|
+
const codecept = new Codecept(config, {})
|
|
16
|
+
await codecept.init(testsPath)
|
|
14
17
|
|
|
15
|
-
output.print('Gherkin Step Definitions:')
|
|
16
|
-
output.print()
|
|
17
|
-
const steps = getSteps()
|
|
18
|
+
output.print('Gherkin Step Definitions:')
|
|
19
|
+
output.print()
|
|
20
|
+
const steps = getSteps()
|
|
18
21
|
for (const step of Object.keys(steps)) {
|
|
19
|
-
output.print(` ${output.colors.bold(step)} ${output.colors.green(steps[step].line || '')}`)
|
|
22
|
+
output.print(` ${output.colors.bold(step)} ${output.colors.green(steps[step].line || '')}`)
|
|
20
23
|
}
|
|
21
|
-
output.print()
|
|
24
|
+
output.print()
|
|
22
25
|
if (!Object.keys(steps).length) {
|
|
23
|
-
output.error('No Gherkin steps defined')
|
|
26
|
+
output.error('No Gherkin steps defined')
|
|
24
27
|
}
|
|
25
|
-
}
|
|
28
|
+
}
|