codeceptjs 4.0.0-beta.3 → 4.0.0-beta.5

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 (155) hide show
  1. package/README.md +134 -119
  2. package/bin/codecept.js +12 -2
  3. package/bin/test-server.js +53 -0
  4. package/docs/webapi/clearCookie.mustache +1 -1
  5. package/lib/actor.js +66 -102
  6. package/lib/ai.js +130 -121
  7. package/lib/assert/empty.js +3 -5
  8. package/lib/assert/equal.js +4 -7
  9. package/lib/assert/include.js +4 -6
  10. package/lib/assert/throws.js +2 -4
  11. package/lib/assert/truth.js +2 -2
  12. package/lib/codecept.js +141 -86
  13. package/lib/command/check.js +201 -0
  14. package/lib/command/configMigrate.js +2 -4
  15. package/lib/command/definitions.js +8 -26
  16. package/lib/command/dryRun.js +30 -35
  17. package/lib/command/generate.js +10 -14
  18. package/lib/command/gherkin/snippets.js +75 -73
  19. package/lib/command/gherkin/steps.js +1 -1
  20. package/lib/command/info.js +42 -8
  21. package/lib/command/init.js +13 -12
  22. package/lib/command/interactive.js +10 -2
  23. package/lib/command/list.js +1 -1
  24. package/lib/command/run-multiple/chunk.js +48 -45
  25. package/lib/command/run-multiple.js +12 -35
  26. package/lib/command/run-workers.js +21 -58
  27. package/lib/command/utils.js +5 -6
  28. package/lib/command/workers/runTests.js +263 -222
  29. package/lib/container.js +386 -238
  30. package/lib/data/context.js +10 -13
  31. package/lib/data/dataScenarioConfig.js +8 -8
  32. package/lib/data/dataTableArgument.js +6 -6
  33. package/lib/data/table.js +5 -11
  34. package/lib/effects.js +223 -0
  35. package/lib/element/WebElement.js +327 -0
  36. package/lib/els.js +158 -0
  37. package/lib/event.js +21 -17
  38. package/lib/heal.js +88 -80
  39. package/lib/helper/AI.js +2 -1
  40. package/lib/helper/ApiDataFactory.js +4 -7
  41. package/lib/helper/Appium.js +50 -57
  42. package/lib/helper/FileSystem.js +3 -3
  43. package/lib/helper/GraphQLDataFactory.js +4 -4
  44. package/lib/helper/JSONResponse.js +75 -37
  45. package/lib/helper/Mochawesome.js +31 -9
  46. package/lib/helper/Nightmare.js +37 -58
  47. package/lib/helper/Playwright.js +267 -272
  48. package/lib/helper/Protractor.js +56 -87
  49. package/lib/helper/Puppeteer.js +247 -264
  50. package/lib/helper/REST.js +29 -17
  51. package/lib/helper/TestCafe.js +22 -47
  52. package/lib/helper/WebDriver.js +157 -368
  53. package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
  54. package/lib/helper/extras/Popup.js +22 -22
  55. package/lib/helper/network/utils.js +1 -1
  56. package/lib/helper/testcafe/testcafe-utils.js +27 -28
  57. package/lib/listener/emptyRun.js +55 -0
  58. package/lib/listener/exit.js +7 -10
  59. package/lib/listener/{retry.js → globalRetry.js} +5 -5
  60. package/lib/listener/globalTimeout.js +165 -0
  61. package/lib/listener/helpers.js +15 -15
  62. package/lib/listener/mocha.js +1 -1
  63. package/lib/listener/result.js +12 -0
  64. package/lib/listener/retryEnhancer.js +85 -0
  65. package/lib/listener/steps.js +32 -18
  66. package/lib/listener/store.js +20 -0
  67. package/lib/locator.js +1 -1
  68. package/lib/mocha/asyncWrapper.js +231 -0
  69. package/lib/{interfaces → mocha}/bdd.js +3 -3
  70. package/lib/mocha/cli.js +308 -0
  71. package/lib/mocha/factory.js +104 -0
  72. package/lib/{interfaces → mocha}/featureConfig.js +32 -12
  73. package/lib/{interfaces → mocha}/gherkin.js +26 -28
  74. package/lib/mocha/hooks.js +112 -0
  75. package/lib/mocha/index.js +12 -0
  76. package/lib/mocha/inject.js +29 -0
  77. package/lib/{interfaces → mocha}/scenarioConfig.js +31 -7
  78. package/lib/mocha/suite.js +82 -0
  79. package/lib/mocha/test.js +181 -0
  80. package/lib/mocha/types.d.ts +42 -0
  81. package/lib/mocha/ui.js +232 -0
  82. package/lib/output.js +93 -65
  83. package/lib/pause.js +160 -138
  84. package/lib/plugin/analyze.js +396 -0
  85. package/lib/plugin/auth.js +435 -0
  86. package/lib/plugin/autoDelay.js +8 -8
  87. package/lib/plugin/autoLogin.js +3 -338
  88. package/lib/plugin/commentStep.js +6 -1
  89. package/lib/plugin/coverage.js +10 -22
  90. package/lib/plugin/customLocator.js +3 -3
  91. package/lib/plugin/customReporter.js +52 -0
  92. package/lib/plugin/eachElement.js +1 -1
  93. package/lib/plugin/fakerTransform.js +1 -1
  94. package/lib/plugin/heal.js +36 -9
  95. package/lib/plugin/htmlReporter.js +1947 -0
  96. package/lib/plugin/pageInfo.js +140 -0
  97. package/lib/plugin/retryFailedStep.js +17 -18
  98. package/lib/plugin/retryTo.js +2 -113
  99. package/lib/plugin/screenshotOnFail.js +17 -58
  100. package/lib/plugin/selenoid.js +15 -35
  101. package/lib/plugin/standardActingHelpers.js +4 -1
  102. package/lib/plugin/stepByStepReport.js +56 -17
  103. package/lib/plugin/stepTimeout.js +5 -12
  104. package/lib/plugin/subtitles.js +4 -4
  105. package/lib/plugin/tryTo.js +3 -102
  106. package/lib/plugin/wdio.js +8 -10
  107. package/lib/recorder.js +155 -124
  108. package/lib/rerun.js +43 -42
  109. package/lib/result.js +161 -0
  110. package/lib/secret.js +1 -2
  111. package/lib/step/base.js +239 -0
  112. package/lib/step/comment.js +10 -0
  113. package/lib/step/config.js +50 -0
  114. package/lib/step/func.js +46 -0
  115. package/lib/step/helper.js +50 -0
  116. package/lib/step/meta.js +99 -0
  117. package/lib/step/record.js +74 -0
  118. package/lib/step/retry.js +11 -0
  119. package/lib/step/section.js +55 -0
  120. package/lib/step.js +21 -332
  121. package/lib/steps.js +50 -0
  122. package/lib/store.js +37 -5
  123. package/lib/template/heal.js +2 -11
  124. package/lib/test-server.js +323 -0
  125. package/lib/timeout.js +66 -0
  126. package/lib/utils.js +351 -218
  127. package/lib/within.js +75 -55
  128. package/lib/workerStorage.js +2 -1
  129. package/lib/workers.js +386 -277
  130. package/package.json +81 -75
  131. package/translations/de-DE.js +5 -3
  132. package/translations/fr-FR.js +5 -4
  133. package/translations/index.js +1 -0
  134. package/translations/it-IT.js +4 -3
  135. package/translations/ja-JP.js +4 -3
  136. package/translations/nl-NL.js +76 -0
  137. package/translations/pl-PL.js +4 -3
  138. package/translations/pt-BR.js +4 -3
  139. package/translations/ru-RU.js +4 -3
  140. package/translations/utils.js +9 -0
  141. package/translations/zh-CN.js +4 -3
  142. package/translations/zh-TW.js +4 -3
  143. package/typings/index.d.ts +197 -187
  144. package/typings/promiseBasedTypes.d.ts +53 -903
  145. package/typings/types.d.ts +372 -1042
  146. package/lib/cli.js +0 -257
  147. package/lib/helper/ExpectHelper.js +0 -391
  148. package/lib/helper/MockServer.js +0 -221
  149. package/lib/helper/SoftExpectHelper.js +0 -381
  150. package/lib/listener/artifacts.js +0 -19
  151. package/lib/listener/timeout.js +0 -109
  152. package/lib/mochaFactory.js +0 -113
  153. package/lib/plugin/debugErrors.js +0 -67
  154. package/lib/scenario.js +0 -224
  155. package/lib/ui.js +0 -236
@@ -0,0 +1,232 @@
1
+ const escapeRe = require('escape-string-regexp')
2
+ const { test, setup, teardown, suiteSetup, suiteTeardown, injected } = require('./asyncWrapper')
3
+ const ScenarioConfig = require('./scenarioConfig')
4
+ const FeatureConfig = require('./featureConfig')
5
+ const addDataContext = require('../data/context')
6
+ const { createTest } = require('./test')
7
+ const { createSuite } = require('./suite')
8
+ const { HookConfig, AfterSuiteHook, AfterHook, BeforeSuiteHook, BeforeHook } = require('./hooks')
9
+
10
+ const setContextTranslation = context => {
11
+ const container = require('../container')
12
+ const contexts = container.translation().value('contexts')
13
+
14
+ if (contexts) {
15
+ for (const key of Object.keys(contexts)) {
16
+ if (context[key]) {
17
+ context[contexts[key]] = context[key]
18
+ }
19
+ }
20
+ }
21
+ }
22
+
23
+ /**
24
+ * Codecept-style interface:
25
+ *
26
+ * Feature('login');
27
+ *
28
+ * Scenario('login as regular user', ({I}) {
29
+ * I.fillField();
30
+ * I.click();
31
+ * I.see('Hello, '+data.login);
32
+ * });
33
+ *
34
+ * @param {Mocha.Suite} suite Root suite.
35
+ * @ignore
36
+ */
37
+ module.exports = function (suite) {
38
+ const suites = [suite]
39
+ suite.timeout(0)
40
+ let afterAllHooks
41
+ let afterEachHooks
42
+ let afterAllHooksAreLoaded
43
+ let afterEachHooksAreLoaded
44
+
45
+ suite.on('pre-require', (context, file, mocha) => {
46
+ const common = require('mocha/lib/interfaces/common')(suites, context, mocha)
47
+
48
+ const addScenario = function (title, opts = {}, fn) {
49
+ const suite = suites[0]
50
+
51
+ if (typeof opts === 'function' && !fn) {
52
+ fn = opts
53
+ opts = {}
54
+ }
55
+ if (suite.pending) {
56
+ fn = null
57
+ }
58
+ const test = createTest(title, fn)
59
+ test.file = file
60
+ test.addToSuite(suite)
61
+ test.applyOptions(opts)
62
+
63
+ return new ScenarioConfig(test)
64
+ }
65
+
66
+ // create dispatcher
67
+
68
+ context.BeforeAll = common.before
69
+ context.AfterAll = common.after
70
+
71
+ context.run = mocha.options.delay && common.runWithSuite(suite)
72
+ /**
73
+ * Describe a "suite" with the given `title`
74
+ * and callback `fn` containing nested suites
75
+ * and/or tests.
76
+ * @global
77
+ * @param {string} title
78
+ * @param {Object<string, *>} [opts]
79
+ * @returns {FeatureConfig}
80
+ */
81
+
82
+ context.Feature = function (title, opts) {
83
+ if (suites.length > 1) {
84
+ suites.shift()
85
+ }
86
+
87
+ afterAllHooks = []
88
+ afterEachHooks = []
89
+ afterAllHooksAreLoaded = false
90
+ afterEachHooksAreLoaded = false
91
+
92
+ const suite = createSuite(suites[0], title)
93
+ suite.applyOptions(opts)
94
+
95
+ suite.file = file
96
+ suites.unshift(suite)
97
+ suite.beforeEach('codeceptjs.before', () => setup(suite))
98
+ afterEachHooks.push(['finalize codeceptjs', () => teardown(suite)])
99
+
100
+ suite.beforeAll('codeceptjs.beforeSuite', () => suiteSetup(suite))
101
+ afterAllHooks.push(['codeceptjs.afterSuite', () => suiteTeardown(suite)])
102
+
103
+ return new FeatureConfig(suite)
104
+ }
105
+
106
+ /**
107
+ * Exclusive test suite - runs only this feature.
108
+ * @global
109
+ * @kind constant
110
+ * @type {CodeceptJS.IFeature}
111
+ */
112
+ context.Feature.only = function (title, opts) {
113
+ const reString = `^${escapeRe(`${title}:`)}`
114
+ mocha.grep(new RegExp(reString))
115
+ process.env.FEATURE_ONLY = true
116
+ return context.Feature(title, opts)
117
+ }
118
+
119
+ /**
120
+ * Pending test suite.
121
+ * @global
122
+ * @kind constant
123
+ * @type {CodeceptJS.IFeature}
124
+ */
125
+ context.xFeature = context.Feature.skip = function (title, opts) {
126
+ const skipInfo = {
127
+ skipped: true,
128
+ message: 'Skipped due to "skip" on Feature.',
129
+ }
130
+ return context.Feature(title, { ...opts, skipInfo })
131
+ }
132
+
133
+ context.BeforeSuite = function (fn) {
134
+ suites[0].beforeAll('BeforeSuite', injected(fn, suites[0], 'beforeSuite'))
135
+ return new HookConfig(new BeforeSuiteHook({ suite: suites[0] }))
136
+ }
137
+
138
+ context.AfterSuite = function (fn) {
139
+ afterAllHooks.unshift(['AfterSuite', injected(fn, suites[0], 'afterSuite')])
140
+ return new HookConfig(new AfterSuiteHook({ suite: suites[0] }))
141
+ }
142
+
143
+ context.Background = context.Before = function (fn) {
144
+ suites[0].beforeEach('Before', injected(fn, suites[0], 'before'))
145
+ return new HookConfig(new BeforeHook({ suite: suites[0] }))
146
+ }
147
+
148
+ context.After = function (fn) {
149
+ afterEachHooks.unshift(['After', injected(fn, suites[0], 'after')])
150
+ return new HookConfig(new AfterHook({ suite: suites[0] }))
151
+ }
152
+
153
+ /**
154
+ * Describe a specification or test-case
155
+ * with the given `title` and callback `fn`
156
+ * acting as a thunk.
157
+ * @ignore
158
+ */
159
+ context.Scenario = addScenario
160
+ /**
161
+ * Exclusive test-case.
162
+ * @ignore
163
+ */
164
+ context.Scenario.only = function (title, opts, fn) {
165
+ const reString = `^${escapeRe(`${suites[0].title}: ${title}`.replace(/( \| {.+})?$/g, ''))}`
166
+ mocha.grep(new RegExp(reString))
167
+ process.env.SCENARIO_ONLY = true
168
+ return addScenario(title, opts, fn)
169
+ }
170
+
171
+ /**
172
+ * Pending test case.
173
+ * @global
174
+ * @kind constant
175
+ * @type {CodeceptJS.IScenario}
176
+ */
177
+ context.xScenario = context.Scenario.skip = function (title, opts = {}, fn) {
178
+ if (typeof opts === 'function' && !fn) {
179
+ opts = {}
180
+ }
181
+
182
+ return context.Scenario(title, opts)
183
+ }
184
+
185
+ /**
186
+ * Pending test case with message: 'Test not implemented!'.
187
+ * @global
188
+ * @kind constant
189
+ * @type {CodeceptJS.IScenario}
190
+ */
191
+ context.Scenario.todo = function (title, opts = {}, fn) {
192
+ if (typeof opts === 'function' && !fn) {
193
+ fn = opts
194
+ opts = {}
195
+ }
196
+
197
+ const skipInfo = {
198
+ message: 'Test not implemented!',
199
+ description: fn ? fn.toString() : '',
200
+ }
201
+
202
+ return context.Scenario(title, { ...opts, skipInfo })
203
+ }
204
+
205
+ /**
206
+ * For translation
207
+ */
208
+
209
+ setContextTranslation(context)
210
+
211
+ addDataContext(context)
212
+ })
213
+
214
+ suite.on('post-require', () => {
215
+ /**
216
+ * load hooks from arrays to suite to prevent reordering
217
+ */
218
+ if (!afterEachHooksAreLoaded && Array.isArray(afterEachHooks)) {
219
+ afterEachHooks.forEach(hook => {
220
+ suites[0].afterEach(hook[0], hook[1])
221
+ })
222
+ afterEachHooksAreLoaded = true
223
+ }
224
+
225
+ if (!afterAllHooksAreLoaded && Array.isArray(afterAllHooks)) {
226
+ afterAllHooks.forEach(hook => {
227
+ suites[0].afterAll(hook[0], hook[1])
228
+ })
229
+ afterAllHooksAreLoaded = true
230
+ }
231
+ })
232
+ }
package/lib/output.js CHANGED
@@ -1,5 +1,6 @@
1
- const colors = require('chalk');
2
- const figures = require('figures');
1
+ const colors = require('chalk')
2
+ const figures = require('figures')
3
+ const { maskSensitiveData } = require('invisi-data')
3
4
 
4
5
  const styles = {
5
6
  error: colors.bgRed.white.bold,
@@ -9,11 +10,12 @@ const styles = {
9
10
  debug: colors.cyan,
10
11
  log: colors.grey,
11
12
  bold: colors.bold,
12
- };
13
+ section: colors.white.dim.bold,
14
+ }
13
15
 
14
- let outputLevel = 0;
15
- let outputProcess = '';
16
- let newline = true;
16
+ let outputLevel = 0
17
+ let outputProcess = ''
18
+ let newline = true
17
19
 
18
20
  /**
19
21
  * @alias output
@@ -27,7 +29,7 @@ module.exports = {
27
29
  stepShift: 0,
28
30
 
29
31
  standWithUkraine() {
30
- return `#${colors.bold.yellow('StandWith')}${colors.bold.cyan('Ukraine')}`;
32
+ return `#${colors.bold.yellow('StandWith')}${colors.bold.cyan('Ukraine')}`
31
33
  },
32
34
 
33
35
  /**
@@ -36,8 +38,8 @@ module.exports = {
36
38
  * @returns {number}
37
39
  */
38
40
  level(level) {
39
- if (level !== undefined) outputLevel = level;
40
- return outputLevel;
41
+ if (level !== undefined) outputLevel = level
42
+ return outputLevel
41
43
  },
42
44
 
43
45
  /**
@@ -47,9 +49,9 @@ module.exports = {
47
49
  * @returns {string}
48
50
  */
49
51
  process(process) {
50
- if (process === null) return outputProcess = '';
51
- if (process) outputProcess = String(process).length === 1 ? `[0${process}]` : `[${process}]`;
52
- return outputProcess;
52
+ if (process === null) return (outputProcess = '')
53
+ if (process) outputProcess = String(process).length === 1 ? `[0${process}]` : `[${process}]`
54
+ return outputProcess
53
55
  },
54
56
 
55
57
  /**
@@ -57,8 +59,9 @@ module.exports = {
57
59
  * @param {string} msg
58
60
  */
59
61
  debug(msg) {
62
+ const _msg = isMaskedData() ? maskSensitiveData(msg) : msg
60
63
  if (outputLevel >= 2) {
61
- print(' '.repeat(this.stepShift), styles.debug(`${figures.pointerSmall} ${msg}`));
64
+ print(' '.repeat(this.stepShift), styles.debug(`${figures.pointerSmall} ${_msg}`))
62
65
  }
63
66
  },
64
67
 
@@ -67,8 +70,9 @@ module.exports = {
67
70
  * @param {string} msg
68
71
  */
69
72
  log(msg) {
73
+ const _msg = isMaskedData() ? maskSensitiveData(msg) : msg
70
74
  if (outputLevel >= 3) {
71
- print(' '.repeat(this.stepShift), styles.log(truncate(` ${msg}`, this.spaceShift)));
75
+ print(' '.repeat(this.stepShift), styles.log(truncate(` ${_msg}`, this.spaceShift)))
72
76
  }
73
77
  },
74
78
 
@@ -77,7 +81,7 @@ module.exports = {
77
81
  * @param {string} msg
78
82
  */
79
83
  error(msg) {
80
- print(styles.error(msg));
84
+ print(styles.error(msg))
81
85
  },
82
86
 
83
87
  /**
@@ -85,7 +89,7 @@ module.exports = {
85
89
  * @param {string} msg
86
90
  */
87
91
  success(msg) {
88
- print(styles.success(msg));
92
+ print(styles.success(msg))
89
93
  },
90
94
 
91
95
  /**
@@ -94,7 +98,7 @@ module.exports = {
94
98
  * @param {string} msg
95
99
  */
96
100
  plugin(pluginName, msg = '') {
97
- this.debug(`<${pluginName}> ${msg}`);
101
+ this.debug(`<${pluginName}> ${msg}`)
98
102
  },
99
103
 
100
104
  /**
@@ -102,25 +106,26 @@ module.exports = {
102
106
  * @param {CodeceptJS.Step} step
103
107
  */
104
108
  step(step) {
105
- if (outputLevel === 0) return;
106
- if (!step) return;
109
+ if (outputLevel === 0) return
110
+ if (!step) return
107
111
  // Avoid to print non-gherkin steps, when gherkin is running for --steps mode
108
112
  if (outputLevel === 1) {
109
113
  if (typeof step === 'object' && step.hasBDDAncestor()) {
110
- return;
114
+ return
111
115
  }
112
116
  }
113
117
 
114
- let stepLine = step.toString();
118
+ let stepLine = step.toCliStyled ? step.toCliStyled() : step.toString()
115
119
  if (step.metaStep && outputLevel >= 1) {
116
120
  // this.stepShift += 2;
117
- stepLine = colors.green(truncate(stepLine, this.spaceShift));
121
+ stepLine = colors.dim(truncate(stepLine, this.spaceShift))
118
122
  }
119
123
  if (step.comment) {
120
- stepLine += colors.grey(step.comment.split('\n').join('\n' + ' '.repeat(4))); // eslint-disable-line
124
+ stepLine += colors.grey(step.comment.split('\n').join('\n' + ' '.repeat(4)))
121
125
  }
122
126
 
123
- print(' '.repeat(this.stepShift), truncate(stepLine, this.spaceShift));
127
+ const _stepLine = isMaskedData() ? maskSensitiveData(stepLine) : stepLine
128
+ print(' '.repeat(this.stepShift), truncate(_stepLine, this.spaceShift))
124
129
  },
125
130
 
126
131
  /** @namespace */
@@ -128,10 +133,11 @@ module.exports = {
128
133
  /**
129
134
  * @param {Mocha.Suite} suite
130
135
  */
131
- started: (suite) => {
132
- if (!suite.title) return;
133
- print(`${colors.bold(suite.title)} --`);
134
- if (suite.comment) print(suite.comment);
136
+ started: suite => {
137
+ if (!suite.title) return
138
+ print(`${colors.bold(suite.title)} --`)
139
+ if (suite.file && outputLevel >= 1) print(colors.underline.grey(suite.file))
140
+ if (suite.comment) print(suite.comment)
135
141
  },
136
142
  },
137
143
 
@@ -141,25 +147,25 @@ module.exports = {
141
147
  * @param {Mocha.Test} test
142
148
  */
143
149
  started(test) {
144
- print(` ${colors.magenta.bold(test.title)}`);
150
+ print(` ${colors.magenta.bold(test.title)}`)
145
151
  },
146
152
  /**
147
153
  * @param {Mocha.Test} test
148
154
  */
149
155
  passed(test) {
150
- print(` ${colors.green.bold(figures.tick)} ${test.title} ${colors.grey(`in ${test.duration}ms`)}`);
156
+ print(` ${colors.green.bold(figures.tick)} ${test.title} ${colors.grey(`in ${test.duration}ms`)}`)
151
157
  },
152
158
  /**
153
159
  * @param {Mocha.Test} test
154
160
  */
155
161
  failed(test) {
156
- print(` ${colors.red.bold(figures.cross)} ${test.title} ${colors.grey(`in ${test.duration}ms`)}`);
162
+ print(` ${colors.red.bold(figures.cross)} ${test.title} ${colors.grey(`in ${test.duration}ms`)}`)
157
163
  },
158
164
  /**
159
165
  * @param {Mocha.Test} test
160
166
  */
161
167
  skipped(test) {
162
- print(` ${colors.yellow.bold('S')} ${test.title}`);
168
+ print(` ${colors.yellow.bold('S')} ${test.title}`)
163
169
  },
164
170
  },
165
171
 
@@ -167,23 +173,41 @@ module.exports = {
167
173
  scenario: {
168
174
  /**
169
175
  * @param {Mocha.Test} test
170
- */
171
- /* eslint-disable */
172
- started(test) {},
173
- /* eslint-enable */
176
+ */
177
+
178
+ started(test) {
179
+ if (outputLevel < 1) return
180
+ print(` ${colors.dim.bold('Scenario()')}`)
181
+ },
182
+
174
183
  /**
175
184
  * @param {Mocha.Test} test
176
185
  */
177
186
  passed(test) {
178
- print(` ${colors.green.bold(`${figures.tick} OK`)} ${colors.grey(`in ${test.duration}ms`)}`);
179
- print();
187
+ print(` ${colors.green.bold(`${figures.tick} OK`)} ${colors.grey(`in ${test.duration}ms`)}`)
188
+ print()
180
189
  },
181
190
  /**
182
191
  * @param {Mocha.Test} test
183
192
  */
184
193
  failed(test) {
185
- print(` ${colors.red.bold(`${figures.cross} FAILED`)} ${colors.grey(`in ${test.duration}ms`)}`);
186
- print();
194
+ print(` ${colors.red.bold(`${figures.cross} FAILED`)} ${colors.grey(`in ${test.duration}ms`)}`)
195
+ print()
196
+ },
197
+ },
198
+
199
+ hook: {
200
+ started(hook) {
201
+ if (outputLevel < 1) return
202
+ print(` ${colors.dim.bold(hook.toCode())}`)
203
+ },
204
+ passed(hook) {
205
+ if (outputLevel < 1) return
206
+ print()
207
+ },
208
+ failed(hook) {
209
+ if (outputLevel < 1) return
210
+ print(` ${colors.red.bold(hook.toCode())}`)
187
211
  },
188
212
  },
189
213
 
@@ -195,9 +219,9 @@ module.exports = {
195
219
  */
196
220
  say(message, color = 'cyan') {
197
221
  if (colors[color] === undefined) {
198
- color = 'cyan';
222
+ color = 'cyan'
199
223
  }
200
- if (outputLevel >= 1) print(` ${colors[color].bold(message)}`);
224
+ if (outputLevel >= 1) print(` ${colors[color].bold(message)}`)
201
225
  },
202
226
 
203
227
  /**
@@ -207,50 +231,54 @@ module.exports = {
207
231
  * @param {number|string} duration
208
232
  */
209
233
  result(passed, failed, skipped, duration, failedHooks = 0) {
210
- let style = colors.bgGreen;
211
- let msg = ` ${passed || 0} passed`;
212
- let status = style.bold(' OK ');
234
+ let style = colors.bgGreen
235
+ let msg = ` ${passed || 0} passed`
236
+ let status = style.bold(' OK ')
213
237
  if (failed) {
214
- style = style.bgRed;
215
- status = style.bold(' FAIL ');
216
- msg += `, ${failed} failed`;
238
+ style = style.bgRed
239
+ status = style.bold(' FAIL ')
240
+ msg += `, ${failed} failed`
217
241
  }
218
242
 
219
243
  if (failedHooks > 0) {
220
- style = style.bgRed;
221
- status = style.bold(' FAIL ');
222
- msg += `, ${failedHooks} failedHooks`;
244
+ style = style.bgRed
245
+ status = style.bold(' FAIL ')
246
+ msg += `, ${failedHooks} failedHooks`
223
247
  }
224
- status += style.grey(' |');
248
+ status += style.grey(' |')
225
249
 
226
250
  if (skipped) {
227
- if (!failed) style = style.bgYellow;
228
- msg += `, ${skipped} skipped`;
251
+ if (!failed) style = style.bgYellow
252
+ msg += `, ${skipped} skipped`
229
253
  }
230
- msg += ' ';
231
- print(status + style(msg) + colors.grey(` // ${duration}`));
254
+ msg += ' '
255
+ print(status + style(msg) + colors.grey(` // ${duration}`))
232
256
  },
233
- };
257
+ }
234
258
 
235
259
  function print(...msg) {
236
260
  if (outputProcess) {
237
- msg.unshift(outputProcess);
261
+ msg.unshift(outputProcess)
238
262
  }
239
263
  if (!newline) {
240
- console.log();
241
- newline = true;
264
+ console.log()
265
+ newline = true
242
266
  }
243
267
 
244
- console.log.apply(this, msg);
268
+ console.log.apply(this, msg)
245
269
  }
246
270
 
247
271
  function truncate(msg, gap = 0) {
248
272
  if (msg.indexOf('\n') > 0 || outputLevel >= 3) {
249
- return msg; // don't cut multi line steps or on verbose log level
273
+ return msg // don't cut multi line steps or on verbose log level
250
274
  }
251
- const width = (process.stdout.columns || 200) - gap - 4;
275
+ const width = (process.stdout.columns || 200) - gap - 4
252
276
  if (msg.length > width) {
253
- msg = msg.substr(0, width - 1) + figures.ellipsis;
277
+ msg = msg.substr(0, width - 1) + figures.ellipsis
254
278
  }
255
- return msg;
279
+ return msg
280
+ }
281
+
282
+ function isMaskedData() {
283
+ return global.maskSensitiveData === true || false
256
284
  }