codeceptjs 4.0.0-beta.1 → 4.0.0-beta.3
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/bin/codecept.js +84 -81
- package/lib/actor.js +13 -13
- package/lib/ai.js +10 -13
- package/lib/assert/empty.js +20 -21
- package/lib/assert/equal.js +37 -39
- package/lib/assert/error.js +14 -14
- package/lib/assert/include.js +46 -47
- package/lib/assert/throws.js +13 -11
- package/lib/assert/truth.js +19 -22
- package/lib/assert.js +4 -2
- package/lib/cli.js +57 -49
- package/lib/codecept.js +142 -155
- package/lib/colorUtils.js +3 -3
- package/lib/command/configMigrate.js +58 -52
- package/lib/command/definitions.js +88 -89
- package/lib/command/dryRun.js +71 -68
- package/lib/command/generate.js +197 -188
- package/lib/command/gherkin/init.js +27 -16
- package/lib/command/gherkin/snippets.js +20 -20
- package/lib/command/gherkin/steps.js +8 -8
- package/lib/command/info.js +40 -38
- package/lib/command/init.js +290 -288
- package/lib/command/interactive.js +32 -32
- package/lib/command/list.js +26 -26
- package/lib/command/run-multiple/chunk.js +5 -5
- package/lib/command/run-multiple/collection.js +3 -3
- package/lib/command/run-multiple/run.js +6 -2
- package/lib/command/run-multiple.js +113 -93
- package/lib/command/run-rerun.js +20 -25
- package/lib/command/run-workers.js +64 -66
- package/lib/command/run.js +26 -29
- package/lib/command/utils.js +80 -65
- package/lib/command/workers/runTests.js +10 -10
- package/lib/config.js +10 -9
- package/lib/container.js +40 -48
- package/lib/data/context.js +60 -59
- package/lib/data/dataScenarioConfig.js +47 -47
- package/lib/data/dataTableArgument.js +29 -29
- package/lib/data/table.js +26 -20
- package/lib/event.js +163 -167
- package/lib/heal.js +13 -17
- package/lib/helper/AI.js +130 -41
- package/lib/helper/ApiDataFactory.js +73 -69
- package/lib/helper/Appium.js +413 -382
- package/lib/helper/ExpectHelper.js +40 -48
- package/lib/helper/FileSystem.js +80 -79
- package/lib/helper/GraphQL.js +44 -43
- package/lib/helper/GraphQLDataFactory.js +50 -50
- package/lib/helper/JSONResponse.js +65 -62
- package/lib/helper/Mochawesome.js +28 -28
- package/lib/helper/MockServer.js +12 -14
- package/lib/helper/Nightmare.js +662 -566
- package/lib/helper/Playwright.js +1361 -1216
- package/lib/helper/Protractor.js +663 -627
- package/lib/helper/Puppeteer.js +1231 -1128
- package/lib/helper/REST.js +159 -68
- package/lib/helper/SoftExpectHelper.js +2 -2
- package/lib/helper/TestCafe.js +490 -484
- package/lib/helper/WebDriver.js +1297 -1156
- package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
- package/lib/helper/errors/ConnectionRefused.js +1 -1
- package/lib/helper/errors/ElementAssertion.js +2 -2
- package/lib/helper/errors/ElementNotFound.js +2 -2
- package/lib/helper/errors/RemoteBrowserConnectionRefused.js +1 -1
- package/lib/helper/extras/Console.js +1 -1
- package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
- package/lib/helper/extras/PlaywrightReactVueLocator.js +1 -1
- package/lib/helper/extras/PlaywrightRestartOpts.js +21 -18
- package/lib/helper/extras/Popup.js +1 -1
- package/lib/helper/extras/React.js +3 -3
- package/lib/helper/network/actions.js +14 -7
- package/lib/helper/network/utils.js +3 -2
- package/lib/helper/scripts/blurElement.js +1 -1
- package/lib/helper/scripts/focusElement.js +1 -1
- package/lib/helper/scripts/highlightElement.js +1 -1
- package/lib/helper/scripts/isElementClickable.js +1 -1
- package/lib/helper/testcafe/testControllerHolder.js +1 -1
- package/lib/helper/testcafe/testcafe-utils.js +6 -7
- package/lib/helper.js +1 -3
- package/lib/history.js +6 -5
- package/lib/hooks.js +6 -6
- package/lib/html.js +7 -7
- package/lib/index.js +25 -41
- package/lib/interfaces/bdd.js +47 -64
- package/lib/interfaces/featureConfig.js +19 -19
- package/lib/interfaces/gherkin.js +124 -118
- package/lib/interfaces/scenarioConfig.js +29 -29
- package/lib/listener/artifacts.js +9 -9
- package/lib/listener/config.js +24 -24
- package/lib/listener/exit.js +12 -12
- package/lib/listener/helpers.js +42 -42
- package/lib/listener/mocha.js +11 -11
- package/lib/listener/retry.js +32 -30
- package/lib/listener/steps.js +50 -53
- package/lib/listener/timeout.js +54 -54
- package/lib/locator.js +6 -10
- package/lib/mochaFactory.js +18 -15
- package/lib/output.js +6 -10
- package/lib/parser.js +15 -12
- package/lib/pause.js +40 -33
- package/lib/plugin/allure.js +15 -15
- package/lib/plugin/autoDelay.js +29 -37
- package/lib/plugin/autoLogin.js +70 -65
- package/lib/plugin/commentStep.js +18 -18
- package/lib/plugin/coverage.js +115 -67
- package/lib/plugin/customLocator.js +21 -20
- package/lib/plugin/debugErrors.js +24 -24
- package/lib/plugin/eachElement.js +38 -38
- package/lib/plugin/fakerTransform.js +6 -6
- package/lib/plugin/heal.js +67 -108
- package/lib/plugin/pauseOnFail.js +11 -11
- package/lib/plugin/retryFailedStep.js +32 -39
- package/lib/plugin/retryTo.js +46 -40
- package/lib/plugin/screenshotOnFail.js +109 -87
- package/lib/plugin/selenoid.js +131 -118
- package/lib/plugin/standardActingHelpers.js +2 -8
- package/lib/plugin/stepByStepReport.js +110 -91
- package/lib/plugin/stepTimeout.js +24 -23
- package/lib/plugin/subtitles.js +34 -35
- package/lib/plugin/tryTo.js +40 -30
- package/lib/plugin/wdio.js +78 -75
- package/lib/recorder.js +14 -17
- package/lib/rerun.js +11 -10
- package/lib/scenario.js +25 -23
- package/lib/secret.js +4 -2
- package/lib/session.js +10 -10
- package/lib/step.js +12 -9
- package/lib/store.js +2 -3
- package/lib/transform.js +1 -1
- package/lib/translation.js +7 -8
- package/lib/ui.js +12 -14
- package/lib/utils.js +70 -72
- package/lib/within.js +10 -10
- package/lib/workerStorage.js +27 -25
- package/lib/workers.js +29 -32
- package/package.json +56 -57
- package/translations/de-DE.js +1 -1
- package/translations/fr-FR.js +1 -1
- package/translations/index.js +9 -13
- package/translations/it-IT.js +1 -1
- package/translations/ja-JP.js +1 -1
- package/translations/pl-PL.js +1 -1
- package/translations/pt-BR.js +1 -1
- package/translations/ru-RU.js +1 -1
- package/translations/zh-CN.js +1 -1
- package/translations/zh-TW.js +1 -1
- package/typings/index.d.ts +415 -65
- package/typings/promiseBasedTypes.d.ts +32 -0
- package/typings/types.d.ts +32 -0
- package/lib/dirname.js +0 -5
- package/lib/helper/Expect.js +0 -425
package/lib/assert/include.js
CHANGED
|
@@ -1,79 +1,78 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
const Assertion = require('../assert')
|
|
2
|
+
const AssertionFailedError = require('./error')
|
|
3
|
+
const { template } = require('../utils')
|
|
4
|
+
const output = require('../output')
|
|
5
5
|
|
|
6
|
-
const MAX_LINES = 10
|
|
6
|
+
const MAX_LINES = 10
|
|
7
7
|
|
|
8
8
|
class InclusionAssertion extends Assertion {
|
|
9
9
|
constructor(params) {
|
|
10
|
-
params.jar = params.jar || 'string'
|
|
10
|
+
params.jar = params.jar || 'string'
|
|
11
11
|
const comparator = function (needle, haystack) {
|
|
12
12
|
if (Array.isArray(haystack)) {
|
|
13
|
-
return haystack.filter(part => part.indexOf(needle) >= 0).length > 0
|
|
13
|
+
return haystack.filter((part) => part.indexOf(needle) >= 0).length > 0
|
|
14
14
|
}
|
|
15
|
-
return haystack.indexOf(needle) >= 0
|
|
16
|
-
}
|
|
17
|
-
super(comparator, params)
|
|
18
|
-
this.params.type = 'to include'
|
|
15
|
+
return haystack.indexOf(needle) >= 0
|
|
16
|
+
}
|
|
17
|
+
super(comparator, params)
|
|
18
|
+
this.params.type = 'to include'
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
getException() {
|
|
22
|
-
const params = this.params
|
|
23
|
-
params.jar = template(params.jar, params)
|
|
24
|
-
const err = new AssertionFailedError(params, '{{customMessage}}expected {{jar}} {{type}} "{{needle}}"')
|
|
25
|
-
err.expected = params.needle
|
|
26
|
-
err.actual = params.haystack
|
|
22
|
+
const params = this.params
|
|
23
|
+
params.jar = template(params.jar, params)
|
|
24
|
+
const err = new AssertionFailedError(params, '{{customMessage}}expected {{jar}} {{type}} "{{needle}}"')
|
|
25
|
+
err.expected = params.needle
|
|
26
|
+
err.actual = params.haystack
|
|
27
27
|
if (Array.isArray(this.params.haystack)) {
|
|
28
|
-
this.params.haystack = this.params.haystack.join('\n___(next element)___\n')
|
|
28
|
+
this.params.haystack = this.params.haystack.join('\n___(next element)___\n')
|
|
29
29
|
}
|
|
30
30
|
err.cliMessage = function () {
|
|
31
31
|
const msg = this.template
|
|
32
|
-
.replace('{{jar}}', output.
|
|
33
|
-
.replace('{{needle}}', output.
|
|
34
|
-
return template(msg, this.params)
|
|
35
|
-
}
|
|
36
|
-
return err
|
|
32
|
+
.replace('{{jar}}', output.colors.bold('{{jar}}'))
|
|
33
|
+
.replace('{{needle}}', output.colors.bold('{{needle}}'))
|
|
34
|
+
return template(msg, this.params)
|
|
35
|
+
}
|
|
36
|
+
return err
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
getFailedAssertion() {
|
|
40
|
-
const err = this.getException()
|
|
41
|
-
const lines = this.params.haystack.split('\n')
|
|
40
|
+
const err = this.getException()
|
|
41
|
+
const lines = this.params.haystack.split('\n')
|
|
42
42
|
if (lines.length > MAX_LINES) {
|
|
43
|
-
const more = lines.length - MAX_LINES
|
|
44
|
-
err.actual = `${lines.slice(0, MAX_LINES).join('\n')}\n--( ${more} lines more )
|
|
43
|
+
const more = lines.length - MAX_LINES
|
|
44
|
+
err.actual = `${lines.slice(0, MAX_LINES).join('\n')}\n--( ${more} lines more )---`
|
|
45
45
|
}
|
|
46
|
-
return err
|
|
46
|
+
return err
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
getFailedNegation() {
|
|
50
|
-
this.params.type = 'not to include'
|
|
51
|
-
const err = this.getException()
|
|
52
|
-
const pattern = new RegExp(`^.*?\n?^.*?\n?^.*?${escapeRegExp(this.params.needle)}.*?$\n?.*$\n?.*$`, 'm')
|
|
53
|
-
const matched = this.params.haystack.match(pattern)
|
|
54
|
-
if (!matched) return err
|
|
55
|
-
err.actual = matched[0].replace(this.params.needle, output.
|
|
56
|
-
err.actual = `------\n${err.actual}\n
|
|
57
|
-
return err
|
|
50
|
+
this.params.type = 'not to include'
|
|
51
|
+
const err = this.getException()
|
|
52
|
+
const pattern = new RegExp(`^.*?\n?^.*?\n?^.*?${escapeRegExp(this.params.needle)}.*?$\n?.*$\n?.*$`, 'm')
|
|
53
|
+
const matched = this.params.haystack.match(pattern)
|
|
54
|
+
if (!matched) return err
|
|
55
|
+
err.actual = matched[0].replace(this.params.needle, output.colors.bold(this.params.needle))
|
|
56
|
+
err.actual = `------\n${err.actual}\n------`
|
|
57
|
+
return err
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
addAssertParams() {
|
|
61
|
-
this.params.needle = arguments[0]
|
|
62
|
-
this.params.haystack = arguments[1]
|
|
63
|
-
this.params.customMessage = arguments[2] ? `${arguments[2]}\n\n` : ''
|
|
61
|
+
this.params.needle = arguments[0]
|
|
62
|
+
this.params.haystack = arguments[1]
|
|
63
|
+
this.params.customMessage = arguments[2] ? `${arguments[2]}\n\n` : ''
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
module.exports = {
|
|
68
|
+
Assertion: InclusionAssertion,
|
|
69
|
+
includes: (needleType) => {
|
|
70
|
+
needleType = needleType || 'string'
|
|
71
|
+
return new InclusionAssertion({ jar: needleType })
|
|
72
|
+
},
|
|
73
|
+
fileIncludes: (file) => new InclusionAssertion({ file, jar: 'file {{file}}' }),
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
function escapeRegExp(str) {
|
|
74
|
-
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&')
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export function fileIncludes(file) {
|
|
78
|
-
return new InclusionAssertion({ file, jar: 'file {{file}}' });
|
|
77
|
+
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&')
|
|
79
78
|
}
|
package/lib/assert/throws.js
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
function errorThrown(actual, expected) {
|
|
2
|
-
if (!expected) return null
|
|
3
|
-
if (!actual) throw new Error(`Expected ${expected} error to be thrown`)
|
|
4
|
-
const msg = actual.inspect ? actual.inspect() : actual.toString()
|
|
2
|
+
if (!expected) return null
|
|
3
|
+
if (!actual) throw new Error(`Expected ${expected} error to be thrown`)
|
|
4
|
+
const msg = actual.inspect ? actual.inspect() : actual.toString()
|
|
5
5
|
if (expected instanceof RegExp) {
|
|
6
|
-
if (msg.match(expected)) return null
|
|
7
|
-
throw new Error(`Expected error to be thrown with message matching ${expected} while '${msg}' caught`)
|
|
6
|
+
if (msg.match(expected)) return null
|
|
7
|
+
throw new Error(`Expected error to be thrown with message matching ${expected} while '${msg}' caught`)
|
|
8
8
|
}
|
|
9
9
|
if (typeof expected === 'string') {
|
|
10
|
-
if (msg === expected) return null
|
|
11
|
-
throw new Error(`Expected error to be thrown with message ${expected} while '${msg}' caught`)
|
|
10
|
+
if (msg === expected) return null
|
|
11
|
+
throw new Error(`Expected error to be thrown with message ${expected} while '${msg}' caught`)
|
|
12
12
|
}
|
|
13
13
|
if (typeof expected === 'object') {
|
|
14
|
-
if (actual.constructor.name !== expected.constructor.name)
|
|
15
|
-
|
|
14
|
+
if (actual.constructor.name !== expected.constructor.name)
|
|
15
|
+
throw new Error(`Expected ${expected} error to be thrown but ${actual} was caught`)
|
|
16
|
+
if (expected.message && expected.message !== msg)
|
|
17
|
+
throw new Error(`Expected error to be thrown with message ${expected.message} while '${msg}' caught`)
|
|
16
18
|
}
|
|
17
|
-
return null
|
|
19
|
+
return null
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
module.exports = errorThrown
|
package/lib/assert/truth.js
CHANGED
|
@@ -1,39 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
const Assertion = require('../assert')
|
|
2
|
+
const AssertionFailedError = require('./error')
|
|
3
|
+
const { template } = require('../utils')
|
|
4
|
+
const output = require('../output')
|
|
5
5
|
|
|
6
6
|
class TruthAssertion extends Assertion {
|
|
7
7
|
constructor(params) {
|
|
8
8
|
super((value) => {
|
|
9
9
|
if (Array.isArray(value)) {
|
|
10
|
-
return value.filter(val => !!val).length > 0
|
|
10
|
+
return value.filter((val) => !!val).length > 0
|
|
11
11
|
}
|
|
12
|
-
return !!value
|
|
13
|
-
}, params)
|
|
14
|
-
this.params.type = this.params.type || 'to be true'
|
|
12
|
+
return !!value
|
|
13
|
+
}, params)
|
|
14
|
+
this.params.type = this.params.type || 'to be true'
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
getException() {
|
|
18
|
-
const err = new AssertionFailedError(this.params, '{{customMessage}}expected {{subject}} {{type}}')
|
|
18
|
+
const err = new AssertionFailedError(this.params, '{{customMessage}}expected {{subject}} {{type}}')
|
|
19
19
|
err.cliMessage = () => {
|
|
20
|
-
const msg = err.template
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return err;
|
|
20
|
+
const msg = err.template.replace('{{subject}}', output.colors.bold('{{subject}}'))
|
|
21
|
+
return template(msg, this.params)
|
|
22
|
+
}
|
|
23
|
+
return err
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
addAssertParams() {
|
|
28
|
-
this.params.value = this.params.actual = arguments[0]
|
|
29
|
-
this.params.expected = true
|
|
30
|
-
this.params.customMessage = arguments[1] ? `${arguments[1]}\n\n` : ''
|
|
27
|
+
this.params.value = this.params.actual = arguments[0]
|
|
28
|
+
this.params.expected = true
|
|
29
|
+
this.params.customMessage = arguments[1] ? `${arguments[1]}\n\n` : ''
|
|
31
30
|
}
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
return new TruthAssertion({ subject, type });
|
|
36
|
-
}
|
|
37
|
-
export default {
|
|
33
|
+
module.exports = {
|
|
38
34
|
Assertion: TruthAssertion,
|
|
39
|
-
}
|
|
35
|
+
truth: (subject, type) => new TruthAssertion({ subject, type }),
|
|
36
|
+
}
|
package/lib/assert.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
const AssertionFailedError = require('./assert/error');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Abstract assertion class introduced for more verbose and customizable messages.
|
|
@@ -20,7 +20,7 @@ import AssertionFailedError from './assert/error.js';
|
|
|
20
20
|
* to get more customizable exception messages.
|
|
21
21
|
*
|
|
22
22
|
*/
|
|
23
|
-
|
|
23
|
+
class Assertion {
|
|
24
24
|
constructor(comparator, params) {
|
|
25
25
|
this.comparator = comparator;
|
|
26
26
|
this.params = params || {};
|
|
@@ -68,3 +68,5 @@ export default class Assertion {
|
|
|
68
68
|
return this.getException();
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
+
|
|
72
|
+
module.exports = Assertion;
|
package/lib/cli.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import container from './container.js';
|
|
8
|
-
|
|
9
|
-
const { reporters: { Base } } = mocha;
|
|
1
|
+
const { reporters: { Base } } = require('mocha');
|
|
2
|
+
const ms = require('ms');
|
|
3
|
+
const event = require('./event');
|
|
4
|
+
const AssertionFailedError = require('./assert/error');
|
|
5
|
+
const output = require('./output');
|
|
6
|
+
const { MetaStep } = require('./step');
|
|
10
7
|
|
|
11
8
|
const cursor = Base.cursor;
|
|
12
9
|
let currentMetaStep = [];
|
|
@@ -21,16 +18,16 @@ class Cli extends Base {
|
|
|
21
18
|
if (opts.steps) level = 1;
|
|
22
19
|
if (opts.debug) level = 2;
|
|
23
20
|
if (opts.verbose) level = 3;
|
|
24
|
-
output.
|
|
25
|
-
|
|
26
|
-
output.
|
|
27
|
-
output.output.print(`Using test root "${global.codecept_dir}"`);
|
|
21
|
+
output.level(level);
|
|
22
|
+
output.print(`CodeceptJS v${require('./codecept').version()} ${output.standWithUkraine()}`);
|
|
23
|
+
output.print(`Using test root "${global.codecept_dir}"`);
|
|
28
24
|
|
|
29
25
|
const showSteps = level >= 1;
|
|
30
26
|
|
|
31
27
|
if (level >= 2) {
|
|
32
|
-
|
|
33
|
-
output.
|
|
28
|
+
const Containter = require('./container');
|
|
29
|
+
output.print(output.styles.debug(`Helpers: ${Object.keys(Containter.helpers()).join(', ')}`));
|
|
30
|
+
output.print(output.styles.debug(`Plugins: ${Object.keys(Containter.plugins()).join(', ')}`));
|
|
34
31
|
}
|
|
35
32
|
|
|
36
33
|
runner.on('start', () => {
|
|
@@ -38,7 +35,7 @@ class Cli extends Base {
|
|
|
38
35
|
});
|
|
39
36
|
|
|
40
37
|
runner.on('suite', (suite) => {
|
|
41
|
-
output.
|
|
38
|
+
output.suite.started(suite);
|
|
42
39
|
});
|
|
43
40
|
|
|
44
41
|
runner.on('fail', (test) => {
|
|
@@ -46,10 +43,10 @@ class Cli extends Base {
|
|
|
46
43
|
this.loadedTests.push(test.ctx.currentTest.uid);
|
|
47
44
|
}
|
|
48
45
|
if (showSteps && test.steps) {
|
|
49
|
-
return output.
|
|
46
|
+
return output.scenario.failed(test);
|
|
50
47
|
}
|
|
51
48
|
cursor.CR();
|
|
52
|
-
output.
|
|
49
|
+
output.test.failed(test);
|
|
53
50
|
});
|
|
54
51
|
|
|
55
52
|
runner.on('pending', (test) => {
|
|
@@ -62,22 +59,22 @@ class Cli extends Base {
|
|
|
62
59
|
}
|
|
63
60
|
this.loadedTests.push(test.uid);
|
|
64
61
|
cursor.CR();
|
|
65
|
-
output.
|
|
62
|
+
output.test.skipped(test);
|
|
66
63
|
});
|
|
67
64
|
|
|
68
65
|
runner.on('pass', (test) => {
|
|
69
66
|
if (showSteps && test.steps) {
|
|
70
|
-
return output.
|
|
67
|
+
return output.scenario.passed(test);
|
|
71
68
|
}
|
|
72
69
|
cursor.CR();
|
|
73
|
-
output.
|
|
70
|
+
output.test.passed(test);
|
|
74
71
|
});
|
|
75
72
|
|
|
76
73
|
if (showSteps) {
|
|
77
74
|
runner.on('test', (test) => {
|
|
78
75
|
currentMetaStep = [];
|
|
79
76
|
if (test.steps) {
|
|
80
|
-
output.
|
|
77
|
+
output.test.started(test);
|
|
81
78
|
}
|
|
82
79
|
});
|
|
83
80
|
|
|
@@ -85,8 +82,8 @@ class Cli extends Base {
|
|
|
85
82
|
codeceptjsEventDispatchersRegistered = true;
|
|
86
83
|
|
|
87
84
|
event.dispatcher.on(event.bddStep.started, (step) => {
|
|
88
|
-
output.
|
|
89
|
-
output.
|
|
85
|
+
output.stepShift = 2;
|
|
86
|
+
output.step(step);
|
|
90
87
|
});
|
|
91
88
|
|
|
92
89
|
event.dispatcher.on(event.step.started, (step) => {
|
|
@@ -100,22 +97,22 @@ class Cli extends Base {
|
|
|
100
97
|
|
|
101
98
|
for (let i = 0; i < Math.max(currentMetaStep.length, metaSteps.length); i++) {
|
|
102
99
|
if (currentMetaStep[i] !== metaSteps[i]) {
|
|
103
|
-
output.
|
|
100
|
+
output.stepShift = 3 + 2 * i;
|
|
104
101
|
if (!metaSteps[i]) continue;
|
|
105
102
|
// bdd steps are handled by bddStep.started
|
|
106
103
|
if (metaSteps[i].isBDD()) continue;
|
|
107
|
-
output.
|
|
104
|
+
output.step(metaSteps[i]);
|
|
108
105
|
}
|
|
109
106
|
}
|
|
110
107
|
currentMetaStep = metaSteps;
|
|
111
|
-
output.
|
|
108
|
+
output.stepShift = 3 + 2 * shift;
|
|
112
109
|
if (step.helper.constructor.name !== 'ExpectHelper') {
|
|
113
|
-
output.
|
|
110
|
+
output.step(step);
|
|
114
111
|
}
|
|
115
112
|
});
|
|
116
113
|
|
|
117
114
|
event.dispatcher.on(event.step.finished, () => {
|
|
118
|
-
output.
|
|
115
|
+
output.stepShift = 0;
|
|
119
116
|
});
|
|
120
117
|
}
|
|
121
118
|
}
|
|
@@ -133,7 +130,7 @@ class Cli extends Base {
|
|
|
133
130
|
test.opts.skipInfo = {};
|
|
134
131
|
}
|
|
135
132
|
skipTestConfig(test, 'Skipped due to failure in \'before\' hook');
|
|
136
|
-
output.
|
|
133
|
+
output.test.skipped(test);
|
|
137
134
|
skippedCount += 1;
|
|
138
135
|
}
|
|
139
136
|
}
|
|
@@ -148,11 +145,12 @@ class Cli extends Base {
|
|
|
148
145
|
|
|
149
146
|
result() {
|
|
150
147
|
const stats = this.stats;
|
|
148
|
+
stats.failedHooks = 0;
|
|
151
149
|
console.log();
|
|
152
150
|
|
|
153
151
|
// passes
|
|
154
152
|
if (stats.failures) {
|
|
155
|
-
output.
|
|
153
|
+
output.print(output.styles.bold('-- FAILURES:'));
|
|
156
154
|
}
|
|
157
155
|
|
|
158
156
|
const failuresLog = [];
|
|
@@ -178,31 +176,35 @@ class Cli extends Base {
|
|
|
178
176
|
// if (step.status === 'failed') line = '' + line;
|
|
179
177
|
scenarioTrace += `\n${line}`;
|
|
180
178
|
});
|
|
181
|
-
log += `${output.
|
|
179
|
+
log += `${output.styles.bold('Scenario Steps')}:${scenarioTrace}\n`;
|
|
182
180
|
}
|
|
183
181
|
|
|
184
182
|
// display artifacts in debug mode
|
|
185
183
|
if (test?.artifacts && Object.keys(test.artifacts).length) {
|
|
186
|
-
log += `\n${output.
|
|
184
|
+
log += `\n${output.styles.bold('Artifacts:')}`;
|
|
187
185
|
for (const artifact of Object.keys(test.artifacts)) {
|
|
188
186
|
log += `\n- ${artifact}: ${test.artifacts[artifact]}`;
|
|
189
187
|
}
|
|
190
188
|
}
|
|
191
189
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
stack.
|
|
195
|
-
|
|
190
|
+
try {
|
|
191
|
+
let stack = err.stack ? err.stack.split('\n') : [];
|
|
192
|
+
if (stack[0] && stack[0].includes(err.message)) {
|
|
193
|
+
stack.shift();
|
|
194
|
+
}
|
|
196
195
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
196
|
+
if (output.level() < 3) {
|
|
197
|
+
stack = stack.slice(0, 3);
|
|
198
|
+
}
|
|
200
199
|
|
|
201
|
-
|
|
200
|
+
err.stack = `${stack.join('\n')}\n\n${output.colors.blue(log)}`;
|
|
202
201
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
202
|
+
// clone err object so stack trace adjustments won't affect test other reports
|
|
203
|
+
test.err = err;
|
|
204
|
+
return test;
|
|
205
|
+
} catch (e) {
|
|
206
|
+
throw Error(e);
|
|
207
|
+
}
|
|
206
208
|
});
|
|
207
209
|
|
|
208
210
|
const originalLog = Base.consoleLog;
|
|
@@ -215,11 +217,17 @@ class Cli extends Base {
|
|
|
215
217
|
console.log();
|
|
216
218
|
}
|
|
217
219
|
|
|
220
|
+
this.failures.forEach((failure) => {
|
|
221
|
+
if (failure.constructor.name === 'Hook') {
|
|
222
|
+
stats.failures -= stats.failures
|
|
223
|
+
stats.failedHooks += 1
|
|
224
|
+
}
|
|
225
|
+
})
|
|
218
226
|
event.emit(event.all.failures, { failuresLog, stats });
|
|
219
|
-
output.
|
|
227
|
+
output.result(stats.passes, stats.failures, stats.pending, ms(stats.duration), stats.failedHooks);
|
|
220
228
|
|
|
221
|
-
if (stats.failures && output.
|
|
222
|
-
output.
|
|
229
|
+
if (stats.failures && output.level() < 3) {
|
|
230
|
+
output.print(output.styles.debug('Run with --verbose flag to see complete NodeJS stacktrace'));
|
|
223
231
|
}
|
|
224
232
|
}
|
|
225
233
|
}
|
|
@@ -244,6 +252,6 @@ function skipTestConfig(test, message) {
|
|
|
244
252
|
test.state = 'skipped';
|
|
245
253
|
}
|
|
246
254
|
|
|
247
|
-
|
|
255
|
+
module.exports = function (runner, opts) {
|
|
248
256
|
return new Cli(runner, opts);
|
|
249
|
-
}
|
|
257
|
+
};
|