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.
Files changed (151) hide show
  1. package/bin/codecept.js +84 -81
  2. package/lib/actor.js +13 -13
  3. package/lib/ai.js +10 -13
  4. package/lib/assert/empty.js +20 -21
  5. package/lib/assert/equal.js +37 -39
  6. package/lib/assert/error.js +14 -14
  7. package/lib/assert/include.js +46 -47
  8. package/lib/assert/throws.js +13 -11
  9. package/lib/assert/truth.js +19 -22
  10. package/lib/assert.js +4 -2
  11. package/lib/cli.js +57 -49
  12. package/lib/codecept.js +142 -155
  13. package/lib/colorUtils.js +3 -3
  14. package/lib/command/configMigrate.js +58 -52
  15. package/lib/command/definitions.js +88 -89
  16. package/lib/command/dryRun.js +71 -68
  17. package/lib/command/generate.js +197 -188
  18. package/lib/command/gherkin/init.js +27 -16
  19. package/lib/command/gherkin/snippets.js +20 -20
  20. package/lib/command/gherkin/steps.js +8 -8
  21. package/lib/command/info.js +40 -38
  22. package/lib/command/init.js +290 -288
  23. package/lib/command/interactive.js +32 -32
  24. package/lib/command/list.js +26 -26
  25. package/lib/command/run-multiple/chunk.js +5 -5
  26. package/lib/command/run-multiple/collection.js +3 -3
  27. package/lib/command/run-multiple/run.js +6 -2
  28. package/lib/command/run-multiple.js +113 -93
  29. package/lib/command/run-rerun.js +20 -25
  30. package/lib/command/run-workers.js +64 -66
  31. package/lib/command/run.js +26 -29
  32. package/lib/command/utils.js +80 -65
  33. package/lib/command/workers/runTests.js +10 -10
  34. package/lib/config.js +10 -9
  35. package/lib/container.js +40 -48
  36. package/lib/data/context.js +60 -59
  37. package/lib/data/dataScenarioConfig.js +47 -47
  38. package/lib/data/dataTableArgument.js +29 -29
  39. package/lib/data/table.js +26 -20
  40. package/lib/event.js +163 -167
  41. package/lib/heal.js +13 -17
  42. package/lib/helper/AI.js +130 -41
  43. package/lib/helper/ApiDataFactory.js +73 -69
  44. package/lib/helper/Appium.js +413 -382
  45. package/lib/helper/ExpectHelper.js +40 -48
  46. package/lib/helper/FileSystem.js +80 -79
  47. package/lib/helper/GraphQL.js +44 -43
  48. package/lib/helper/GraphQLDataFactory.js +50 -50
  49. package/lib/helper/JSONResponse.js +65 -62
  50. package/lib/helper/Mochawesome.js +28 -28
  51. package/lib/helper/MockServer.js +12 -14
  52. package/lib/helper/Nightmare.js +662 -566
  53. package/lib/helper/Playwright.js +1361 -1216
  54. package/lib/helper/Protractor.js +663 -627
  55. package/lib/helper/Puppeteer.js +1231 -1128
  56. package/lib/helper/REST.js +159 -68
  57. package/lib/helper/SoftExpectHelper.js +2 -2
  58. package/lib/helper/TestCafe.js +490 -484
  59. package/lib/helper/WebDriver.js +1297 -1156
  60. package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
  61. package/lib/helper/errors/ConnectionRefused.js +1 -1
  62. package/lib/helper/errors/ElementAssertion.js +2 -2
  63. package/lib/helper/errors/ElementNotFound.js +2 -2
  64. package/lib/helper/errors/RemoteBrowserConnectionRefused.js +1 -1
  65. package/lib/helper/extras/Console.js +1 -1
  66. package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
  67. package/lib/helper/extras/PlaywrightReactVueLocator.js +1 -1
  68. package/lib/helper/extras/PlaywrightRestartOpts.js +21 -18
  69. package/lib/helper/extras/Popup.js +1 -1
  70. package/lib/helper/extras/React.js +3 -3
  71. package/lib/helper/network/actions.js +14 -7
  72. package/lib/helper/network/utils.js +3 -2
  73. package/lib/helper/scripts/blurElement.js +1 -1
  74. package/lib/helper/scripts/focusElement.js +1 -1
  75. package/lib/helper/scripts/highlightElement.js +1 -1
  76. package/lib/helper/scripts/isElementClickable.js +1 -1
  77. package/lib/helper/testcafe/testControllerHolder.js +1 -1
  78. package/lib/helper/testcafe/testcafe-utils.js +6 -7
  79. package/lib/helper.js +1 -3
  80. package/lib/history.js +6 -5
  81. package/lib/hooks.js +6 -6
  82. package/lib/html.js +7 -7
  83. package/lib/index.js +25 -41
  84. package/lib/interfaces/bdd.js +47 -64
  85. package/lib/interfaces/featureConfig.js +19 -19
  86. package/lib/interfaces/gherkin.js +124 -118
  87. package/lib/interfaces/scenarioConfig.js +29 -29
  88. package/lib/listener/artifacts.js +9 -9
  89. package/lib/listener/config.js +24 -24
  90. package/lib/listener/exit.js +12 -12
  91. package/lib/listener/helpers.js +42 -42
  92. package/lib/listener/mocha.js +11 -11
  93. package/lib/listener/retry.js +32 -30
  94. package/lib/listener/steps.js +50 -53
  95. package/lib/listener/timeout.js +54 -54
  96. package/lib/locator.js +6 -10
  97. package/lib/mochaFactory.js +18 -15
  98. package/lib/output.js +6 -10
  99. package/lib/parser.js +15 -12
  100. package/lib/pause.js +40 -33
  101. package/lib/plugin/allure.js +15 -15
  102. package/lib/plugin/autoDelay.js +29 -37
  103. package/lib/plugin/autoLogin.js +70 -65
  104. package/lib/plugin/commentStep.js +18 -18
  105. package/lib/plugin/coverage.js +115 -67
  106. package/lib/plugin/customLocator.js +21 -20
  107. package/lib/plugin/debugErrors.js +24 -24
  108. package/lib/plugin/eachElement.js +38 -38
  109. package/lib/plugin/fakerTransform.js +6 -6
  110. package/lib/plugin/heal.js +67 -108
  111. package/lib/plugin/pauseOnFail.js +11 -11
  112. package/lib/plugin/retryFailedStep.js +32 -39
  113. package/lib/plugin/retryTo.js +46 -40
  114. package/lib/plugin/screenshotOnFail.js +109 -87
  115. package/lib/plugin/selenoid.js +131 -118
  116. package/lib/plugin/standardActingHelpers.js +2 -8
  117. package/lib/plugin/stepByStepReport.js +110 -91
  118. package/lib/plugin/stepTimeout.js +24 -23
  119. package/lib/plugin/subtitles.js +34 -35
  120. package/lib/plugin/tryTo.js +40 -30
  121. package/lib/plugin/wdio.js +78 -75
  122. package/lib/recorder.js +14 -17
  123. package/lib/rerun.js +11 -10
  124. package/lib/scenario.js +25 -23
  125. package/lib/secret.js +4 -2
  126. package/lib/session.js +10 -10
  127. package/lib/step.js +12 -9
  128. package/lib/store.js +2 -3
  129. package/lib/transform.js +1 -1
  130. package/lib/translation.js +7 -8
  131. package/lib/ui.js +12 -14
  132. package/lib/utils.js +70 -72
  133. package/lib/within.js +10 -10
  134. package/lib/workerStorage.js +27 -25
  135. package/lib/workers.js +29 -32
  136. package/package.json +56 -57
  137. package/translations/de-DE.js +1 -1
  138. package/translations/fr-FR.js +1 -1
  139. package/translations/index.js +9 -13
  140. package/translations/it-IT.js +1 -1
  141. package/translations/ja-JP.js +1 -1
  142. package/translations/pl-PL.js +1 -1
  143. package/translations/pt-BR.js +1 -1
  144. package/translations/ru-RU.js +1 -1
  145. package/translations/zh-CN.js +1 -1
  146. package/translations/zh-TW.js +1 -1
  147. package/typings/index.d.ts +415 -65
  148. package/typings/promiseBasedTypes.d.ts +32 -0
  149. package/typings/types.d.ts +32 -0
  150. package/lib/dirname.js +0 -5
  151. package/lib/helper/Expect.js +0 -425
@@ -1,79 +1,78 @@
1
- import Assertion from '../assert.js';
2
- import AssertionFailedError from './error.js';
3
- import { template } from '../utils.js';
4
- import * as output from '../output.js';
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.output.colors.bold('{{jar}}'))
33
- .replace('{{needle}}', output.output.colors.bold('{{needle}}'));
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.output.colors.bold(this.params.needle));
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
- export { InclusionAssertion as Assertion };
68
- export function includes(needleType) {
69
- needleType = needleType || 'string';
70
- return new InclusionAssertion({ jar: needleType });
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
  }
@@ -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) throw new Error(`Expected ${expected} error to be thrown but ${actual} was caught`);
15
- if (expected.message && expected.message !== msg) throw new Error(`Expected error to be thrown with message ${expected.message} while '${msg}' caught`);
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
- export default errorThrown;
22
+ module.exports = errorThrown
@@ -1,39 +1,36 @@
1
- import Assertion from '../assert.js';
2
- import AssertionFailedError from './error.js';
3
- import { template } from '../utils.js';
4
- import * as output from '../output.js';
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
- .replace('{{subject}}', output.colors.bold('{{subject}}'));
22
- return template(msg, this.params);
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
- export function truth(subject, type) {
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
- import AssertionFailedError from './assert/error.js';
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
- export default class Assertion {
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
- import mocha from 'mocha';
2
- import ms from 'ms';
3
- import * as event from './event.js';
4
- import * as output from './output.js';
5
- import AssertionFailedError from './assert/error.js';
6
- import * as Codecept from './codecept.js';
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.output.level(level);
25
- const version = Codecept.version();
26
- output.output.print(`CodeceptJS v${version} ${output.output.standWithUkraine()}`);
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
- output.output.print(output.output.styles.debug(`Helpers: ${Object.keys(container.helpers()).join(', ')}`));
33
- output.output.print(output.output.styles.debug(`Plugins: ${Object.keys(container.plugins()).join(', ')}`));
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.output.suite.started(suite);
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.output.scenario.failed(test);
46
+ return output.scenario.failed(test);
50
47
  }
51
48
  cursor.CR();
52
- output.output.test.failed(test);
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.output.test.skipped(test);
62
+ output.test.skipped(test);
66
63
  });
67
64
 
68
65
  runner.on('pass', (test) => {
69
66
  if (showSteps && test.steps) {
70
- return output.output.scenario.passed(test);
67
+ return output.scenario.passed(test);
71
68
  }
72
69
  cursor.CR();
73
- output.output.test.passed(test);
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.output.test.started(test);
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.output.stepShift = 2;
89
- output.output.step(step);
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.output.stepShift = 3 + 2 * i;
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.output.step(metaSteps[i]);
104
+ output.step(metaSteps[i]);
108
105
  }
109
106
  }
110
107
  currentMetaStep = metaSteps;
111
- output.output.stepShift = 3 + 2 * shift;
108
+ output.stepShift = 3 + 2 * shift;
112
109
  if (step.helper.constructor.name !== 'ExpectHelper') {
113
- output.output.step(step);
110
+ output.step(step);
114
111
  }
115
112
  });
116
113
 
117
114
  event.dispatcher.on(event.step.finished, () => {
118
- output.output.stepShift = 0;
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.output.test.skipped(test);
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.output.print(output.output.styles.bold('-- FAILURES:'));
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.output.styles.bold('Scenario Steps')}:${scenarioTrace}\n`;
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.output.styles.bold('Artifacts:')}`;
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
- let stack = err.stack ? err.stack.split('\n') : [];
193
- if (stack[0] && stack[0].includes(err.message)) {
194
- stack.shift();
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
- if (output.output.level() < 3) {
198
- stack = stack.slice(0, 3);
199
- }
196
+ if (output.level() < 3) {
197
+ stack = stack.slice(0, 3);
198
+ }
200
199
 
201
- err.stack = `${stack.join('\n')}\n\n${output.output.colors.blue(log)}`;
200
+ err.stack = `${stack.join('\n')}\n\n${output.colors.blue(log)}`;
202
201
 
203
- // clone err object so stack trace adjustments won't affect test other reports
204
- test.err = err;
205
- return test;
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.output.result(stats.passes, stats.failures, stats.pending, ms(stats.duration));
227
+ output.result(stats.passes, stats.failures, stats.pending, ms(stats.duration), stats.failedHooks);
220
228
 
221
- if (stats.failures && output.output.level() < 3) {
222
- output.output.print(output.output.styles.debug('Run with --verbose flag to see complete NodeJS stacktrace'));
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
- export default function cli(runner, opts) {
255
+ module.exports = function (runner, opts) {
248
256
  return new Cli(runner, opts);
249
- }
257
+ };