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.
- 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 +71 -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 +641 -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 +47 -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/bin/codecept.js
CHANGED
|
@@ -1,26 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Command } from 'commander'
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import * as interactive from '../lib/command/interactive.js';
|
|
9
|
-
import * as definitions from '../lib/command/definitions.js';
|
|
10
|
-
import * as list from '../lib/command/list.js';
|
|
11
|
-
import * as gherkinInit from '../lib/command/gherkin/init.js';
|
|
12
|
-
import * as gherkinSteps from '../lib/command/gherkin/steps.js';
|
|
13
|
-
import * as gherkinSnippets from '../lib/command/gherkin/snippets.js';
|
|
14
|
-
import * as generate from '../lib/command/generate.js';
|
|
15
|
-
import * as run from '../lib/command/run.js';
|
|
16
|
-
import * as runWorkers from '../lib/command/run-workers.js';
|
|
17
|
-
import * as runMultiple from '../lib/command/run-multiple.js';
|
|
18
|
-
import { runRerun } from '../lib/command/run-rerun.js';
|
|
19
|
-
import * as dryRun from '../lib/command/dryRun.js';
|
|
20
|
-
import * as info from '../lib/command/info.js';
|
|
21
|
-
import { heal } from "../lib/command/generate.js";
|
|
22
|
-
|
|
23
|
-
const program = new Command();
|
|
2
|
+
import { Command } from 'commander'
|
|
3
|
+
const program = new Command()
|
|
4
|
+
import Codecept from '../lib/codecept.js'
|
|
5
|
+
import output from '../lib/output.js'
|
|
6
|
+
const { print, error } = output
|
|
7
|
+
import { printError } from '../lib/command/utils.js'
|
|
24
8
|
|
|
25
9
|
const commandFlags = {
|
|
26
10
|
ai: {
|
|
@@ -47,104 +31,124 @@ const commandFlags = {
|
|
|
47
31
|
flag: '--steps',
|
|
48
32
|
description: 'show step-by-step execution',
|
|
49
33
|
},
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const errorHandler =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const errorHandler =
|
|
37
|
+
fn =>
|
|
38
|
+
async (...args) => {
|
|
39
|
+
try {
|
|
40
|
+
await fn(...args)
|
|
41
|
+
} catch (e) {
|
|
42
|
+
printError(e)
|
|
43
|
+
process.exitCode = 1
|
|
44
|
+
}
|
|
58
45
|
}
|
|
59
|
-
|
|
46
|
+
|
|
47
|
+
const dynamicImport = async modulePath => {
|
|
48
|
+
const module = await import(modulePath)
|
|
49
|
+
return module.default || module
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const commandHandler = modulePath =>
|
|
53
|
+
errorHandler(async (...args) => {
|
|
54
|
+
const handler = await dynamicImport(modulePath)
|
|
55
|
+
return handler(...args)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const commandHandlerWithProperty = (modulePath, property) =>
|
|
59
|
+
errorHandler(async (...args) => {
|
|
60
|
+
const module = await dynamicImport(modulePath)
|
|
61
|
+
return module[property](...args)
|
|
62
|
+
})
|
|
60
63
|
|
|
61
64
|
if (process.versions.node && process.versions.node.split('.') && process.versions.node.split('.')[0] < 12) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
process.exit(1)
|
|
65
|
+
error('NodeJS >= 12 is required to run.')
|
|
66
|
+
print()
|
|
67
|
+
print('Please upgrade your NodeJS engine')
|
|
68
|
+
print(`Current NodeJS version: ${process.version}`)
|
|
69
|
+
process.exit(1)
|
|
67
70
|
}
|
|
68
71
|
|
|
69
|
-
program.usage('<command> [options]')
|
|
70
|
-
program.version(version())
|
|
72
|
+
program.usage('<command> [options]')
|
|
73
|
+
program.version(Codecept.version())
|
|
74
|
+
|
|
75
|
+
program.command('init [path]').description('Creates dummy config in current dir or [path]').action(commandHandler('../lib/command/init.js'))
|
|
71
76
|
|
|
72
|
-
program
|
|
73
|
-
.
|
|
74
|
-
.
|
|
77
|
+
program
|
|
78
|
+
.command('check')
|
|
79
|
+
.option(commandFlags.config.flag, commandFlags.config.description)
|
|
80
|
+
.description('Checks configuration and environment before running tests')
|
|
81
|
+
.option('-t, --timeout [ms]', 'timeout for checks in ms, 50000 by default')
|
|
82
|
+
.action(commandHandler('../lib/command/check.js'))
|
|
75
83
|
|
|
76
|
-
program.command('migrate [path]')
|
|
77
|
-
.description('Migrate json config to js config in current dir or [path]')
|
|
78
|
-
.action(errorHandler(configMigrate));
|
|
84
|
+
program.command('migrate [path]').description('Migrate json config to js config in current dir or [path]').action(commandHandler('../lib/command/configMigrate.js'))
|
|
79
85
|
|
|
80
|
-
program
|
|
86
|
+
program
|
|
87
|
+
.command('shell [path]')
|
|
81
88
|
.alias('sh')
|
|
82
89
|
.description('Interactive shell')
|
|
83
90
|
.option(commandFlags.verbose.flag, commandFlags.verbose.description)
|
|
84
91
|
.option(commandFlags.profile.flag, commandFlags.profile.description)
|
|
85
92
|
.option(commandFlags.ai.flag, commandFlags.ai.description)
|
|
86
93
|
.option(commandFlags.config.flag, commandFlags.config.description)
|
|
87
|
-
.action(
|
|
94
|
+
.action(commandHandler('../lib/command/interactive.js'))
|
|
88
95
|
|
|
89
|
-
program.command('list [path]')
|
|
90
|
-
.alias('l')
|
|
91
|
-
.description('List all actions for I.')
|
|
92
|
-
.action(errorHandler(list));
|
|
96
|
+
program.command('list [path]').alias('l').description('List all actions for I.').action(commandHandler('../lib/command/list.js'))
|
|
93
97
|
|
|
94
|
-
program
|
|
98
|
+
program
|
|
99
|
+
.command('def [path]')
|
|
95
100
|
.description('Generates TypeScript definitions for all I actions.')
|
|
96
101
|
.option(commandFlags.config.flag, commandFlags.config.description)
|
|
97
102
|
.option('-o, --output [folder]', 'target folder to paste definitions')
|
|
98
|
-
.action(
|
|
103
|
+
.action(commandHandler('../lib/command/definitions.js'))
|
|
99
104
|
|
|
100
|
-
program
|
|
105
|
+
program
|
|
106
|
+
.command('gherkin:init [path]')
|
|
101
107
|
.alias('bdd:init')
|
|
102
108
|
.description('Prepare CodeceptJS to run feature files.')
|
|
103
109
|
.option(commandFlags.config.flag, commandFlags.config.description)
|
|
104
|
-
.action(
|
|
110
|
+
.action(commandHandler('../lib/command/gherkin/init.js'))
|
|
105
111
|
|
|
106
|
-
program
|
|
112
|
+
program
|
|
113
|
+
.command('gherkin:steps [path]')
|
|
107
114
|
.alias('bdd:steps')
|
|
108
115
|
.description('Prints all defined gherkin steps.')
|
|
109
116
|
.option(commandFlags.config.flag, commandFlags.config.description)
|
|
110
|
-
.action(
|
|
117
|
+
.action(commandHandler('../lib/command/gherkin/steps.js'))
|
|
111
118
|
|
|
112
|
-
program
|
|
119
|
+
program
|
|
120
|
+
.command('gherkin:snippets [path]')
|
|
113
121
|
.alias('bdd:snippets')
|
|
114
122
|
.description('Generate step definitions from steps.')
|
|
115
123
|
.option('--dry-run', "don't save snippets to file")
|
|
116
124
|
.option(commandFlags.config.flag, commandFlags.config.description)
|
|
117
125
|
.option('--feature [file]', 'feature files(s) to scan')
|
|
118
126
|
.option('--path [file]', 'file in which to place the new snippets')
|
|
119
|
-
.action(
|
|
127
|
+
.action(commandHandler('../lib/command/gherkin/snippets.js'))
|
|
120
128
|
|
|
121
|
-
program.command('generate:test [path]')
|
|
122
|
-
.alias('gt')
|
|
123
|
-
.description('Generates an empty test')
|
|
124
|
-
.action(errorHandler(generate.test));
|
|
129
|
+
program.command('generate:test [path]').alias('gt').description('Generates an empty test').action(commandHandlerWithProperty('../lib/command/generate.js', 'test'))
|
|
125
130
|
|
|
126
|
-
program.command('generate:pageobject [path]')
|
|
127
|
-
.alias('gpo')
|
|
128
|
-
.description('Generates an empty page object')
|
|
129
|
-
.action(errorHandler(generate.pageObject));
|
|
131
|
+
program.command('generate:pageobject [path]').alias('gpo').description('Generates an empty page object').action(commandHandlerWithProperty('../lib/command/generate.js', 'pageObject'))
|
|
130
132
|
|
|
131
|
-
program
|
|
133
|
+
program
|
|
134
|
+
.command('generate:object [path]')
|
|
132
135
|
.alias('go')
|
|
133
136
|
.option('--type, -t [kind]', 'type of object to be created')
|
|
134
137
|
.description('Generates an empty support object (page/step/fragment)')
|
|
135
|
-
.action(
|
|
138
|
+
.action(commandHandlerWithProperty('../lib/command/generate.js', 'pageObject'))
|
|
139
|
+
|
|
140
|
+
program.command('generate:helper [path]').alias('gh').description('Generates a new helper').action(commandHandlerWithProperty('../lib/command/generate.js', 'helper'))
|
|
136
141
|
|
|
137
|
-
program.command('generate:
|
|
138
|
-
.alias('gh')
|
|
139
|
-
.description('Generates a new helper')
|
|
140
|
-
.action(errorHandler(generate.helper));
|
|
142
|
+
program.command('generate:heal [path]').alias('gr').description('Generates basic heal recipes').action(commandHandlerWithProperty('../lib/command/generate.js', 'heal'))
|
|
141
143
|
|
|
142
|
-
program
|
|
143
|
-
.
|
|
144
|
-
.
|
|
145
|
-
.
|
|
144
|
+
program
|
|
145
|
+
.command('generate:prompt <promptName> [path]')
|
|
146
|
+
.alias('gp')
|
|
147
|
+
.description('Generates AI prompt template (writeStep, healStep, generatePageObject)')
|
|
148
|
+
.action(commandHandlerWithProperty('../lib/command/generate.js', 'prompt'))
|
|
146
149
|
|
|
147
|
-
program
|
|
150
|
+
program
|
|
151
|
+
.command('run [test]')
|
|
148
152
|
.description('Executes tests')
|
|
149
153
|
|
|
150
154
|
// codecept-only options
|
|
@@ -159,6 +163,8 @@ program.command('run [test]')
|
|
|
159
163
|
.option('--tests', 'run only JS test files and skip features')
|
|
160
164
|
.option('--no-timeouts', 'disable all timeouts')
|
|
161
165
|
.option('-p, --plugins <k=v,k2=v2,...>', 'enable plugins, comma-separated')
|
|
166
|
+
.option('--shuffle', 'Shuffle the order in which test files run')
|
|
167
|
+
.option('--shard <index/total>', 'run only a fraction of tests (e.g., --shard 1/4)')
|
|
162
168
|
|
|
163
169
|
// mocha options
|
|
164
170
|
.option('--colors', 'force enabling of colors')
|
|
@@ -180,15 +186,17 @@ program.command('run [test]')
|
|
|
180
186
|
.option('--recursive', 'include sub directories')
|
|
181
187
|
.option('--trace', 'trace function calls')
|
|
182
188
|
.option('--child <string>', 'option for child processes')
|
|
183
|
-
.action(
|
|
189
|
+
.action(commandHandler('../lib/command/run.js'))
|
|
184
190
|
|
|
185
|
-
program
|
|
191
|
+
program
|
|
192
|
+
.command('run-workers <workers> [selectedRuns...]')
|
|
186
193
|
.description('Executes tests in workers')
|
|
187
194
|
.option(commandFlags.config.flag, commandFlags.config.description)
|
|
188
195
|
.option('-g, --grep <pattern>', 'only run tests matching <pattern>')
|
|
189
196
|
.option('-i, --invert', 'inverts --grep matches')
|
|
190
197
|
.option('-o, --override [value]', 'override current config options')
|
|
191
198
|
.option('--suites', 'parallel execution of suites not single tests')
|
|
199
|
+
.option('--by <strategy>', 'test distribution strategy: "test" (pre-assign individual tests), "suite" (pre-assign test suites), or "pool" (dynamic distribution for optimal load balancing, recommended)')
|
|
192
200
|
.option(commandFlags.debug.flag, commandFlags.debug.description)
|
|
193
201
|
.option(commandFlags.verbose.flag, commandFlags.verbose.description)
|
|
194
202
|
.option('--features', 'run only *.feature files and skip tests')
|
|
@@ -198,9 +206,10 @@ program.command('run-workers <workers> [selectedRuns...]')
|
|
|
198
206
|
.option('-p, --plugins <k=v,k2=v2,...>', 'enable plugins, comma-separated')
|
|
199
207
|
.option('-O, --reporter-options <k=v,k2=v2,...>', 'reporter-specific options')
|
|
200
208
|
.option('-R, --reporter <name>', 'specify the reporter to use')
|
|
201
|
-
.action(
|
|
209
|
+
.action(commandHandler('../lib/command/run-workers.js'))
|
|
202
210
|
|
|
203
|
-
program
|
|
211
|
+
program
|
|
212
|
+
.command('run-multiple [suites...]')
|
|
204
213
|
.description('Executes tests multiple')
|
|
205
214
|
.option(commandFlags.config.flag, commandFlags.config.description)
|
|
206
215
|
.option(commandFlags.profile.flag, commandFlags.profile.description)
|
|
@@ -223,14 +232,12 @@ program.command('run-multiple [suites...]')
|
|
|
223
232
|
// mocha options
|
|
224
233
|
.option('--colors', 'force enabling of colors')
|
|
225
234
|
|
|
226
|
-
.action(
|
|
235
|
+
.action(commandHandler('../lib/command/run-multiple.js'))
|
|
227
236
|
|
|
228
|
-
program.command('info [path]')
|
|
229
|
-
.description('Print debugging information concerning the local environment')
|
|
230
|
-
.option('-c, --config', 'your config file path')
|
|
231
|
-
.action(errorHandler(info));
|
|
237
|
+
program.command('info [path]').description('Print debugging information concerning the local environment').option('-c, --config', 'your config file path').action(commandHandler('../lib/command/info.js'))
|
|
232
238
|
|
|
233
|
-
program
|
|
239
|
+
program
|
|
240
|
+
.command('dry-run [test]')
|
|
234
241
|
.description('Prints step-by-step scenario for a test without actually running it')
|
|
235
242
|
.option('-p, --plugins <k=v,k2=v2,...>', 'enable plugins, comma-separated')
|
|
236
243
|
.option('--bootstrap', 'enable bootstrap & teardown scripts for dry-run')
|
|
@@ -244,9 +251,10 @@ program.command('dry-run [test]')
|
|
|
244
251
|
.option(commandFlags.steps.flag, commandFlags.steps.description)
|
|
245
252
|
.option(commandFlags.verbose.flag, commandFlags.verbose.description)
|
|
246
253
|
.option(commandFlags.debug.flag, commandFlags.debug.description)
|
|
247
|
-
.action(
|
|
254
|
+
.action(commandHandler('../lib/command/dryRun.js'))
|
|
248
255
|
|
|
249
|
-
program
|
|
256
|
+
program
|
|
257
|
+
.command('run-rerun [test]')
|
|
250
258
|
.description('Executes tests in more than one test suite run')
|
|
251
259
|
|
|
252
260
|
// codecept-only options
|
|
@@ -281,15 +289,18 @@ program.command('run-rerun [test]')
|
|
|
281
289
|
.option('--trace', 'trace function calls')
|
|
282
290
|
.option('--child <string>', 'option for child processes')
|
|
283
291
|
|
|
284
|
-
.action(
|
|
292
|
+
.action(async (...args) => {
|
|
293
|
+
const runRerun = await dynamicImport('../lib/command/run-rerun.js')
|
|
294
|
+
return runRerun(...args)
|
|
295
|
+
})
|
|
285
296
|
|
|
286
|
-
program.on('command:*',
|
|
287
|
-
console.log(`\nUnknown command ${cmd}\n`)
|
|
288
|
-
program.outputHelp()
|
|
289
|
-
})
|
|
297
|
+
program.on('command:*', cmd => {
|
|
298
|
+
console.log(`\nUnknown command ${cmd}\n`)
|
|
299
|
+
program.outputHelp()
|
|
300
|
+
})
|
|
290
301
|
|
|
291
302
|
if (process.argv.length <= 2) {
|
|
292
|
-
program.outputHelp()
|
|
303
|
+
program.outputHelp()
|
|
293
304
|
} else {
|
|
294
|
-
program.parse(process.argv)
|
|
305
|
+
program.parse(process.argv)
|
|
295
306
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Standalone test server script to replace json-server
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import path from 'path'
|
|
8
|
+
import { fileURLToPath } from 'url'
|
|
9
|
+
import { dirname } from 'path'
|
|
10
|
+
import TestServer from '../lib/test-server.js'
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
13
|
+
const __dirname = dirname(__filename)
|
|
14
|
+
|
|
15
|
+
// Parse command line arguments
|
|
16
|
+
const args = process.argv.slice(2)
|
|
17
|
+
let dbFile = path.join(__dirname, '../test/data/rest/db.json')
|
|
18
|
+
let port = 8010
|
|
19
|
+
let host = '0.0.0.0'
|
|
20
|
+
let readOnly = false
|
|
21
|
+
|
|
22
|
+
// Simple argument parsing
|
|
23
|
+
for (let i = 0; i < args.length; i++) {
|
|
24
|
+
const arg = args[i]
|
|
25
|
+
|
|
26
|
+
if (arg === '-p' || arg === '--port') {
|
|
27
|
+
port = parseInt(args[++i])
|
|
28
|
+
} else if (arg === '--host') {
|
|
29
|
+
host = args[++i]
|
|
30
|
+
} else if (arg === '--read-only' || arg === '-r') {
|
|
31
|
+
readOnly = true
|
|
32
|
+
} else if (!arg.startsWith('-')) {
|
|
33
|
+
dbFile = path.resolve(arg)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Create and start server
|
|
38
|
+
const server = new TestServer({ port, host, dbFile, readOnly })
|
|
39
|
+
|
|
40
|
+
console.log(`Starting test server with db file: ${dbFile}`)
|
|
41
|
+
if (readOnly) {
|
|
42
|
+
console.log('Running in READ-ONLY mode - changes will not be persisted to disk')
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
server
|
|
46
|
+
.start()
|
|
47
|
+
.then(() => {
|
|
48
|
+
console.log(`Test server is ready and listening on http://${host}:${port}`)
|
|
49
|
+
})
|
|
50
|
+
.catch(err => {
|
|
51
|
+
console.error('Failed to start test server:', err)
|
|
52
|
+
process.exit(1)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// Graceful shutdown
|
|
56
|
+
process.on('SIGINT', () => {
|
|
57
|
+
console.log('\nShutting down test server...')
|
|
58
|
+
server.stop().then(() => process.exit(0))
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
process.on('SIGTERM', () => {
|
|
62
|
+
console.log('\nShutting down test server...')
|
|
63
|
+
server.stop().then(() => process.exit(0))
|
|
64
|
+
})
|
|
@@ -3,7 +3,7 @@ if none provided clears all cookies.
|
|
|
3
3
|
|
|
4
4
|
```js
|
|
5
5
|
I.clearCookie();
|
|
6
|
-
I.clearCookie('test');
|
|
6
|
+
I.clearCookie('test');
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
@param {?string} [cookie=null] (optional, `null` by default) cookie name
|
|
@@ -3,9 +3,13 @@ If a fuzzy locator is given, the page will be searched for a button, link, or im
|
|
|
3
3
|
For buttons, the "value" attribute, "name" attribute, and inner text are searched. For links, the link text is searched.
|
|
4
4
|
For images, the "alt" attribute and inner text of any parent links are searched.
|
|
5
5
|
|
|
6
|
+
If no locator is provided, defaults to clicking the body element (`'//body'`).
|
|
7
|
+
|
|
6
8
|
The second parameter is a context (CSS or XPath locator) to narrow the search.
|
|
7
9
|
|
|
8
10
|
```js
|
|
11
|
+
// click body element (default)
|
|
12
|
+
I.click();
|
|
9
13
|
// simple link
|
|
10
14
|
I.click('Logout');
|
|
11
15
|
// button of form
|
|
@@ -20,6 +24,6 @@ I.click('Logout', '#nav');
|
|
|
20
24
|
I.click({css: 'nav a.login'});
|
|
21
25
|
```
|
|
22
26
|
|
|
23
|
-
@param {CodeceptJS.LocatorOrString} locator clickable link or button located by text, or any element located by CSS|XPath|strict locator.
|
|
27
|
+
@param {CodeceptJS.LocatorOrString} [locator='//body'] (optional, `'//body'` by default) clickable link or button located by text, or any element located by CSS|XPath|strict locator.
|
|
24
28
|
@param {?CodeceptJS.LocatorOrString | null} [context=null] (optional, `null` by default) element to search in CSS|XPath|Strict locator.
|
|
25
29
|
@returns {void} automatically synchronized promise through #recorder
|
package/lib/actor.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
1
|
+
import Step, { MetaStep } from './step.js'
|
|
2
|
+
import recordStep from './step/record.js'
|
|
3
|
+
import retryStep from './step/retry.js'
|
|
4
|
+
import { methodsOfObject } from './utils.js'
|
|
5
|
+
import { TIMEOUT_ORDER } from './timeout.js'
|
|
6
|
+
import event from './event.js'
|
|
7
|
+
import store from './store.js'
|
|
8
|
+
import output from './output.js'
|
|
9
|
+
import Container from './container.js'
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* @interface
|
|
11
13
|
* @alias ActorStatic
|
|
12
14
|
*/
|
|
13
|
-
|
|
15
|
+
class Actor {
|
|
14
16
|
/**
|
|
15
17
|
* Print the comment on log. Also, adding a step in the `Test.steps` object
|
|
16
18
|
* @param {string} msg
|
|
@@ -20,13 +22,13 @@ export class Actor {
|
|
|
20
22
|
* ⚠️ returns a promise which is synchronized internally by recorder
|
|
21
23
|
*/
|
|
22
24
|
async say(msg, color = 'cyan') {
|
|
23
|
-
const step = new Step('say', 'say')
|
|
24
|
-
step.status = 'passed'
|
|
25
|
+
const step = new Step('say', 'say')
|
|
26
|
+
step.status = 'passed'
|
|
25
27
|
return recordStep(step, [msg]).then(() => {
|
|
26
28
|
// this is backward compatibility as this event may be used somewhere
|
|
27
|
-
event.emit(event.step.comment, msg)
|
|
28
|
-
output.say(msg, `${color}`)
|
|
29
|
-
})
|
|
29
|
+
event.emit(event.step.comment, msg)
|
|
30
|
+
output.say(msg, `${color}`)
|
|
31
|
+
})
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
/**
|
|
@@ -37,14 +39,16 @@ export class Actor {
|
|
|
37
39
|
* @inner
|
|
38
40
|
*/
|
|
39
41
|
limitTime(timeout) {
|
|
40
|
-
if (!store.timeouts) return this
|
|
42
|
+
if (!store.timeouts) return this
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
output.output.log(`Timeout to ${step}: ${timeout}s`);
|
|
44
|
-
step.setTimeout(timeout * 1000, Step.TIMEOUT_ORDER.codeLimitTime);
|
|
45
|
-
});
|
|
44
|
+
console.log('I.limitTime() is deprecated, use step.timeout() instead')
|
|
46
45
|
|
|
47
|
-
|
|
46
|
+
event.dispatcher.prependOnceListener(event.step.before, step => {
|
|
47
|
+
output.log(`Timeout to ${step}: ${timeout}s`)
|
|
48
|
+
step.setTimeout(timeout * 1000, TIMEOUT_ORDER.codeLimitTime)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
return this
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
/**
|
|
@@ -54,11 +58,9 @@ export class Actor {
|
|
|
54
58
|
* @inner
|
|
55
59
|
*/
|
|
56
60
|
retry(opts) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
recorder.add(() => event.dispatcher.once(event.step.finished, () => recorder.retries.pop()));
|
|
61
|
-
return this;
|
|
61
|
+
console.log('I.retry() is deprecated, use step.retry() instead')
|
|
62
|
+
retryStep(opts)
|
|
63
|
+
return this
|
|
62
64
|
}
|
|
63
65
|
}
|
|
64
66
|
|
|
@@ -68,94 +70,60 @@ export class Actor {
|
|
|
68
70
|
* Wraps helper methods into promises.
|
|
69
71
|
* @ignore
|
|
70
72
|
*/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (!
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
const actor = store.actor;
|
|
77
|
-
|
|
78
|
-
const translation = container.translation();
|
|
79
|
-
|
|
80
|
-
if (Object.keys(obj).length > 0) {
|
|
81
|
-
Object.keys(obj)
|
|
82
|
-
.forEach(action => {
|
|
83
|
-
const actionAlias = translation.actionAliasFor(action);
|
|
84
|
-
|
|
85
|
-
const currentMethod = obj[action];
|
|
86
|
-
const ms = new MetaStep('I', action);
|
|
87
|
-
if (translation.loaded) {
|
|
88
|
-
ms.name = actionAlias;
|
|
89
|
-
ms.actor = translation.I;
|
|
90
|
-
}
|
|
91
|
-
ms.setContext(actor);
|
|
92
|
-
actor[action] = actor[actionAlias] = ms.run.bind(ms, currentMethod);
|
|
93
|
-
});
|
|
73
|
+
export default function (obj = {}, container) {
|
|
74
|
+
// Use global container if none provided
|
|
75
|
+
if (!container) {
|
|
76
|
+
container = Container
|
|
94
77
|
}
|
|
78
|
+
|
|
79
|
+
const actor = container.actor() || new Actor()
|
|
95
80
|
|
|
96
|
-
|
|
81
|
+
// load all helpers once container initialized
|
|
82
|
+
container.started(() => {
|
|
83
|
+
const translation = container.translation()
|
|
84
|
+
const helpers = container.helpers()
|
|
97
85
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
.forEach((helper) => {
|
|
86
|
+
// add methods from enabled helpers
|
|
87
|
+
Object.values(helpers).forEach(helper => {
|
|
101
88
|
methodsOfObject(helper, 'Helper')
|
|
102
89
|
.filter(method => method !== 'constructor' && method[0] !== '_')
|
|
103
|
-
.forEach(
|
|
104
|
-
const actionAlias = translation.actionAliasFor(action)
|
|
90
|
+
.forEach(action => {
|
|
91
|
+
const actionAlias = translation.actionAliasFor(action)
|
|
105
92
|
if (!actor[action]) {
|
|
106
93
|
actor[action] = actor[actionAlias] = function () {
|
|
107
|
-
const step = new Step(helper, action)
|
|
94
|
+
const step = new Step(helper, action)
|
|
108
95
|
if (translation.loaded) {
|
|
109
|
-
step.name = actionAlias
|
|
110
|
-
step.actor = translation.I
|
|
96
|
+
step.name = actionAlias
|
|
97
|
+
step.actor = translation.I
|
|
111
98
|
}
|
|
112
99
|
// add methods to promise chain
|
|
113
|
-
return recordStep(step, Array.from(arguments))
|
|
114
|
-
}
|
|
100
|
+
return recordStep(step, Array.from(arguments))
|
|
101
|
+
}
|
|
115
102
|
}
|
|
116
|
-
})
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
recorder.add('step passed', () => {
|
|
144
|
-
step.endTime = Date.now();
|
|
145
|
-
event.emit(event.step.passed, step, val);
|
|
146
|
-
event.emit(event.step.finished, step);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
recorder.catchWithoutStop((err) => {
|
|
150
|
-
step.status = 'failed';
|
|
151
|
-
step.endTime = Date.now();
|
|
152
|
-
event.emit(event.step.failed, step);
|
|
153
|
-
event.emit(event.step.finished, step);
|
|
154
|
-
throw err;
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
recorder.add('return result', () => val);
|
|
158
|
-
// run async after step hooks
|
|
159
|
-
|
|
160
|
-
return recorder.promise();
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
// add translated custom steps from actor
|
|
107
|
+
Object.keys(obj).forEach(key => {
|
|
108
|
+
const actionAlias = translation.actionAliasFor(key)
|
|
109
|
+
if (!actor[actionAlias]) {
|
|
110
|
+
actor[actionAlias] = actor[key]
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
container.append({
|
|
115
|
+
support: {
|
|
116
|
+
I: actor,
|
|
117
|
+
},
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
// store.actor = actor;
|
|
121
|
+
// add custom steps from actor
|
|
122
|
+
Object.keys(obj).forEach(key => {
|
|
123
|
+
const ms = new MetaStep('I', key)
|
|
124
|
+
ms.setContext(actor)
|
|
125
|
+
actor[key] = ms.run.bind(ms, obj[key])
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
return actor
|
|
161
129
|
}
|