codeceptjs 3.6.10 → 3.7.0-beta.10

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 (127) hide show
  1. package/README.md +89 -119
  2. package/bin/codecept.js +9 -2
  3. package/docs/webapi/clearCookie.mustache +1 -1
  4. package/lib/actor.js +66 -102
  5. package/lib/ai.js +130 -121
  6. package/lib/assert/empty.js +3 -5
  7. package/lib/assert/equal.js +4 -7
  8. package/lib/assert/include.js +4 -6
  9. package/lib/assert/throws.js +2 -4
  10. package/lib/assert/truth.js +2 -2
  11. package/lib/codecept.js +87 -83
  12. package/lib/command/check.js +186 -0
  13. package/lib/command/configMigrate.js +2 -4
  14. package/lib/command/definitions.js +8 -26
  15. package/lib/command/generate.js +10 -14
  16. package/lib/command/gherkin/snippets.js +10 -8
  17. package/lib/command/gherkin/steps.js +1 -1
  18. package/lib/command/info.js +1 -3
  19. package/lib/command/init.js +8 -12
  20. package/lib/command/interactive.js +2 -2
  21. package/lib/command/list.js +1 -1
  22. package/lib/command/run-multiple.js +12 -35
  23. package/lib/command/run-workers.js +5 -57
  24. package/lib/command/utils.js +5 -6
  25. package/lib/command/workers/runTests.js +68 -232
  26. package/lib/container.js +354 -237
  27. package/lib/data/context.js +10 -13
  28. package/lib/data/dataScenarioConfig.js +8 -8
  29. package/lib/data/dataTableArgument.js +6 -6
  30. package/lib/data/table.js +5 -11
  31. package/lib/effects.js +218 -0
  32. package/lib/els.js +158 -0
  33. package/lib/event.js +19 -17
  34. package/lib/heal.js +88 -80
  35. package/lib/helper/AI.js +2 -1
  36. package/lib/helper/ApiDataFactory.js +3 -6
  37. package/lib/helper/Appium.js +45 -51
  38. package/lib/helper/FileSystem.js +3 -3
  39. package/lib/helper/GraphQLDataFactory.js +3 -3
  40. package/lib/helper/JSONResponse.js +57 -37
  41. package/lib/helper/Nightmare.js +35 -53
  42. package/lib/helper/Playwright.js +211 -252
  43. package/lib/helper/Protractor.js +54 -77
  44. package/lib/helper/Puppeteer.js +139 -232
  45. package/lib/helper/REST.js +5 -17
  46. package/lib/helper/TestCafe.js +21 -44
  47. package/lib/helper/WebDriver.js +131 -169
  48. package/lib/helper/testcafe/testcafe-utils.js +26 -27
  49. package/lib/listener/emptyRun.js +55 -0
  50. package/lib/listener/exit.js +7 -10
  51. package/lib/listener/{retry.js → globalRetry.js} +5 -5
  52. package/lib/listener/globalTimeout.js +165 -0
  53. package/lib/listener/helpers.js +15 -15
  54. package/lib/listener/mocha.js +1 -1
  55. package/lib/listener/result.js +12 -0
  56. package/lib/listener/steps.js +20 -18
  57. package/lib/listener/store.js +20 -0
  58. package/lib/mocha/asyncWrapper.js +216 -0
  59. package/lib/{interfaces → mocha}/bdd.js +3 -3
  60. package/lib/mocha/cli.js +308 -0
  61. package/lib/mocha/factory.js +104 -0
  62. package/lib/{interfaces → mocha}/featureConfig.js +24 -12
  63. package/lib/{interfaces → mocha}/gherkin.js +26 -28
  64. package/lib/mocha/hooks.js +112 -0
  65. package/lib/mocha/index.js +12 -0
  66. package/lib/mocha/inject.js +29 -0
  67. package/lib/{interfaces → mocha}/scenarioConfig.js +21 -6
  68. package/lib/mocha/suite.js +81 -0
  69. package/lib/mocha/test.js +159 -0
  70. package/lib/mocha/types.d.ts +42 -0
  71. package/lib/mocha/ui.js +219 -0
  72. package/lib/output.js +82 -62
  73. package/lib/pause.js +155 -138
  74. package/lib/plugin/analyze.js +349 -0
  75. package/lib/plugin/autoDelay.js +6 -6
  76. package/lib/plugin/autoLogin.js +6 -7
  77. package/lib/plugin/commentStep.js +6 -1
  78. package/lib/plugin/coverage.js +10 -19
  79. package/lib/plugin/customLocator.js +3 -3
  80. package/lib/plugin/customReporter.js +52 -0
  81. package/lib/plugin/eachElement.js +1 -1
  82. package/lib/plugin/fakerTransform.js +1 -1
  83. package/lib/plugin/heal.js +36 -9
  84. package/lib/plugin/pageInfo.js +140 -0
  85. package/lib/plugin/retryFailedStep.js +4 -4
  86. package/lib/plugin/retryTo.js +18 -118
  87. package/lib/plugin/screenshotOnFail.js +17 -49
  88. package/lib/plugin/selenoid.js +15 -35
  89. package/lib/plugin/standardActingHelpers.js +4 -1
  90. package/lib/plugin/stepByStepReport.js +56 -17
  91. package/lib/plugin/stepTimeout.js +5 -12
  92. package/lib/plugin/subtitles.js +4 -4
  93. package/lib/plugin/tryTo.js +17 -107
  94. package/lib/plugin/wdio.js +8 -10
  95. package/lib/recorder.js +146 -125
  96. package/lib/rerun.js +43 -42
  97. package/lib/result.js +161 -0
  98. package/lib/secret.js +1 -1
  99. package/lib/step/base.js +228 -0
  100. package/lib/step/config.js +50 -0
  101. package/lib/step/func.js +46 -0
  102. package/lib/step/helper.js +50 -0
  103. package/lib/step/meta.js +99 -0
  104. package/lib/step/record.js +74 -0
  105. package/lib/step/retry.js +11 -0
  106. package/lib/step/section.js +55 -0
  107. package/lib/step.js +21 -332
  108. package/lib/steps.js +50 -0
  109. package/lib/store.js +10 -2
  110. package/lib/template/heal.js +2 -11
  111. package/lib/timeout.js +66 -0
  112. package/lib/utils.js +317 -216
  113. package/lib/within.js +73 -55
  114. package/lib/workers.js +259 -275
  115. package/package.json +56 -54
  116. package/typings/index.d.ts +175 -186
  117. package/typings/promiseBasedTypes.d.ts +164 -17
  118. package/typings/types.d.ts +284 -115
  119. package/lib/cli.js +0 -256
  120. package/lib/helper/ExpectHelper.js +0 -391
  121. package/lib/helper/SoftExpectHelper.js +0 -381
  122. package/lib/listener/artifacts.js +0 -19
  123. package/lib/listener/timeout.js +0 -109
  124. package/lib/mochaFactory.js +0 -113
  125. package/lib/plugin/debugErrors.js +0 -67
  126. package/lib/scenario.js +0 -224
  127. package/lib/ui.js +0 -236
@@ -1,15 +1,15 @@
1
- const { ClientFunction } = require('testcafe');
1
+ const { ClientFunction } = require('testcafe')
2
2
 
3
- const assert = require('assert');
4
- const fs = require('fs');
5
- const path = require('path');
6
- const { getParamNames } = require('../../utils');
3
+ const assert = require('assert')
4
+ const fs = require('fs')
5
+ const path = require('path')
6
+ const { getParamNames } = require('../../utils')
7
7
 
8
8
  const createTestFile = () => {
9
- assert(global.output_dir, 'global.output_dir must be set');
9
+ assert(global.output_dir, 'global.output_dir must be set')
10
10
 
11
- const testFile = path.join(global.output_dir, `${Date.now()}_test.js`);
12
- const testControllerHolderDir = __dirname.replace(/\\/g, '/');
11
+ const testFile = path.join(global.output_dir, `${Date.now()}_test.js`)
12
+ const testControllerHolderDir = __dirname.replace(/\\/g, '/')
13
13
 
14
14
  fs.writeFileSync(
15
15
  testFile,
@@ -17,40 +17,39 @@ const createTestFile = () => {
17
17
  fixture("fixture")\n
18
18
  test\n
19
19
  ("test", testControllerHolder.capture)`,
20
- );
20
+ )
21
21
 
22
- return testFile;
23
- };
22
+ return testFile
23
+ }
24
24
 
25
25
  // TODO Better error mapping (actual, expected)
26
- const mapError = (testcafeError) => {
26
+ const mapError = testcafeError => {
27
27
  // console.log('TODO map error better', JSON.stringify(testcafeError, null, 2));
28
28
  if (testcafeError.errMsg) {
29
- throw new Error(testcafeError.errMsg);
29
+ throw new Error(testcafeError.errMsg)
30
30
  }
31
- const errorInfo = `${testcafeError.callsite ? JSON.stringify(testcafeError.callsite) : ''} ${testcafeError.apiFnChain || JSON.stringify(testcafeError)}`;
32
- throw new Error(`TestCafe Error: ${errorInfo}`);
33
- };
31
+ const errorInfo = `${testcafeError.callsite ? JSON.stringify(testcafeError.callsite) : ''} ${testcafeError.apiFnChain || JSON.stringify(testcafeError)}`
32
+ throw new Error(`TestCafe Error: ${errorInfo}`)
33
+ }
34
34
 
35
35
  function createClientFunction(func, args) {
36
36
  if (!args || !args.length) {
37
- return ClientFunction(func);
37
+ return ClientFunction(func)
38
38
  }
39
- const paramNames = getParamNames(func);
40
- const dependencies = {};
41
- paramNames.forEach((param, i) => dependencies[param] = args[i]);
39
+ const paramNames = getParamNames(func)
40
+ const dependencies = {}
41
+ paramNames.forEach((param, i) => (dependencies[param] = args[i]))
42
42
 
43
- return ClientFunction(getFuncBody(func), { dependencies });
43
+ return ClientFunction(getFuncBody(func), { dependencies })
44
44
  }
45
45
 
46
46
  function getFuncBody(func) {
47
- let fnStr = func.toString();
48
- const arrowIndex = fnStr.indexOf('=>');
47
+ let fnStr = func.toString()
48
+ const arrowIndex = fnStr.indexOf('=>')
49
49
  if (arrowIndex >= 0) {
50
- fnStr = fnStr.slice(arrowIndex + 2);
50
+ fnStr = fnStr.slice(arrowIndex + 2)
51
51
 
52
- // eslint-disable-next-line no-eval
53
- return eval(`() => ${fnStr}`);
52
+ return eval(`() => ${fnStr}`)
54
53
  }
55
54
  // TODO: support general functions
56
55
  }
@@ -59,4 +58,4 @@ module.exports = {
59
58
  createTestFile,
60
59
  mapError,
61
60
  createClientFunction,
62
- };
61
+ }
@@ -0,0 +1,55 @@
1
+ const figures = require('figures')
2
+ const Container = require('../container')
3
+ const event = require('../event')
4
+ const output = require('../output')
5
+ const { searchWithFusejs } = require('../utils')
6
+
7
+ module.exports = function () {
8
+ let isEmptyRun = true
9
+
10
+ event.dispatcher.on(event.test.before, test => {
11
+ isEmptyRun = false
12
+ })
13
+
14
+ event.dispatcher.on(event.all.result, () => {
15
+ if (isEmptyRun) {
16
+ const mocha = Container.mocha()
17
+
18
+ if (mocha.options.grep) {
19
+ output.print()
20
+ output.print('No tests found by pattern: ' + mocha.options.grep)
21
+
22
+ const allTests = []
23
+ mocha.suite.suites.forEach(suite => {
24
+ suite.tests.forEach(test => {
25
+ allTests.push(test.fullTitle())
26
+ })
27
+ })
28
+
29
+ const results = searchWithFusejs(allTests, mocha.options.grep.toString(), {
30
+ includeScore: true,
31
+ threshold: 0.6,
32
+ caseSensitive: false,
33
+ })
34
+
35
+ if (results.length > 0) {
36
+ output.print()
37
+ output.print('Maybe you wanted to run one of these tests?')
38
+ results.forEach(result => {
39
+ output.print(figures.checkboxOff, output.styles.log(result.item))
40
+ })
41
+
42
+ output.print()
43
+ output.print(output.styles.debug('To run the first test use the following command:'))
44
+ output.print(output.styles.bold('npx codeceptjs run --debug --grep "' + results[0].item + '"'))
45
+ }
46
+ }
47
+ if (process.env.CI && !process.env.DONT_FAIL_ON_EMPTY_RUN) {
48
+ output.print()
49
+ output.error('No tests were executed. Failing on CI to avoid false positives')
50
+ output.error('To disable this check, set `DONT_FAIL_ON_EMPTY_RUN` environment variable to true in CI config')
51
+ process.exitCode = 1
52
+ }
53
+ }
54
+ })
55
+ }
@@ -1,24 +1,21 @@
1
1
  const event = require('../event')
2
+ const debug = require('debug')('codeceptjs:exit')
2
3
 
3
4
  module.exports = function () {
4
5
  let failedTests = []
5
6
 
6
- event.dispatcher.on(event.test.failed, (testOrSuite) => {
7
- // NOTE When an error happens in one of the hooks (BeforeAll/BeforeEach...) the event object
8
- // is a suite and not a test
9
- const id = testOrSuite.uid || (testOrSuite.ctx && testOrSuite.ctx.test.uid) || 'empty'
7
+ event.dispatcher.on(event.test.failed, test => {
8
+ const id = test.uid || (test.ctx && test.ctx.test.uid) || 'empty'
10
9
  failedTests.push(id)
11
10
  })
12
11
 
13
12
  // if test was successful after retries
14
- event.dispatcher.on(event.test.passed, (testOrSuite) => {
15
- // NOTE When an error happens in one of the hooks (BeforeAll/BeforeEach...) the event object
16
- // is a suite and not a test
17
- const id = testOrSuite.uid || (testOrSuite.ctx && testOrSuite.ctx.test.uid) || 'empty'
18
- failedTests = failedTests.filter((failed) => id !== failed)
13
+ event.dispatcher.on(event.test.passed, test => {
14
+ const id = test.uid || (test.ctx && test.ctx.test.uid) || 'empty'
15
+ failedTests = failedTests.filter(failed => id !== failed)
19
16
  })
20
17
 
21
- process.on('beforeExit', (code) => {
18
+ process.on('beforeExit', code => {
22
19
  if (failedTests.length) {
23
20
  code = 1
24
21
  }
@@ -6,7 +6,7 @@ const { isNotSet } = require('../utils')
6
6
  const hooks = ['Before', 'After', 'BeforeSuite', 'AfterSuite']
7
7
 
8
8
  module.exports = function () {
9
- event.dispatcher.on(event.suite.before, (suite) => {
9
+ event.dispatcher.on(event.suite.before, suite => {
10
10
  let retryConfig = Config.get('retry')
11
11
  if (!retryConfig) return
12
12
 
@@ -28,8 +28,8 @@ module.exports = function () {
28
28
  }
29
29
 
30
30
  hooks
31
- .filter((hook) => !!config[hook])
32
- .forEach((hook) => {
31
+ .filter(hook => !!config[hook])
32
+ .forEach(hook => {
33
33
  if (isNotSet(suite.opts[`retry${hook}`])) suite.opts[`retry${hook}`] = config[hook]
34
34
  })
35
35
 
@@ -41,7 +41,7 @@ module.exports = function () {
41
41
  }
42
42
  })
43
43
 
44
- event.dispatcher.on(event.test.before, (test) => {
44
+ event.dispatcher.on(event.test.before, test => {
45
45
  let retryConfig = Config.get('retry')
46
46
  if (!retryConfig) return
47
47
 
@@ -54,7 +54,7 @@ module.exports = function () {
54
54
  retryConfig = [retryConfig]
55
55
  }
56
56
 
57
- retryConfig = retryConfig.filter((config) => !!config.Scenario)
57
+ retryConfig = retryConfig.filter(config => !!config.Scenario)
58
58
 
59
59
  for (const config of retryConfig) {
60
60
  if (config.grep) {
@@ -0,0 +1,165 @@
1
+ const event = require('../event')
2
+ const output = require('../output')
3
+ const recorder = require('../recorder')
4
+ const Config = require('../config')
5
+ const store = require('../store')
6
+ const debug = require('debug')('codeceptjs:timeout')
7
+ const { TIMEOUT_ORDER, TimeoutError, TestTimeoutError, StepTimeoutError } = require('../timeout')
8
+ const { BeforeSuiteHook, AfterSuiteHook } = require('../mocha/hooks')
9
+
10
+ module.exports = function () {
11
+ let timeout
12
+ let suiteTimeout = []
13
+ let currentTest
14
+ let currentTimeout
15
+
16
+ if (!store.timeouts) {
17
+ console.log('Timeouts were disabled')
18
+ return
19
+ }
20
+
21
+ // disable timeout for BeforeSuite/AfterSuite hooks
22
+ // add separate configs to them?
23
+ event.dispatcher.on(event.hook.started, hook => {
24
+ if (hook instanceof BeforeSuiteHook) {
25
+ timeout = null
26
+ suiteTimeout = []
27
+ }
28
+ if (hook instanceof AfterSuiteHook) {
29
+ timeout = null
30
+ suiteTimeout = []
31
+ }
32
+ })
33
+
34
+ event.dispatcher.on(event.suite.before, suite => {
35
+ suiteTimeout = []
36
+ let timeoutConfig = Config.get('timeout')
37
+
38
+ if (timeoutConfig) {
39
+ debug('config:', timeoutConfig)
40
+ if (!Number.isNaN(+timeoutConfig)) {
41
+ checkForSeconds(timeoutConfig)
42
+ suiteTimeout.push(timeoutConfig)
43
+ }
44
+
45
+ if (!Array.isArray(timeoutConfig)) {
46
+ timeoutConfig = [timeoutConfig]
47
+ }
48
+
49
+ for (const config of timeoutConfig.filter(c => !!c.Feature)) {
50
+ if (config.grep) {
51
+ if (!suite.title.includes(config.grep)) continue
52
+ }
53
+ suiteTimeout.push(config.Feature)
54
+ }
55
+ }
56
+
57
+ if (suite.totalTimeout) suiteTimeout.push(suite.totalTimeout)
58
+ output.log(`Timeouts: ${suiteTimeout}`)
59
+
60
+ if (suiteTimeout.length > 0) debug(suite.title, 'timeout', suiteTimeout)
61
+ })
62
+
63
+ event.dispatcher.on(event.test.before, test => {
64
+ currentTest = test
65
+ let testTimeout = null
66
+
67
+ let timeoutConfig = Config.get('timeout')
68
+
69
+ if (typeof timeoutConfig === 'object' || Array.isArray(timeoutConfig)) {
70
+ if (!Array.isArray(timeoutConfig)) {
71
+ timeoutConfig = [timeoutConfig]
72
+ }
73
+
74
+ for (const config of timeoutConfig.filter(c => !!c.Scenario)) {
75
+ console.log('Test Timeout', config, test.title.includes(config.grep))
76
+ if (config.grep) {
77
+ if (!test.title.includes(config.grep)) continue
78
+ }
79
+ testTimeout = config.Scenario
80
+ }
81
+ }
82
+
83
+ timeout = test.totalTimeout || testTimeout || suiteTimeout[suiteTimeout.length - 1]
84
+ if (!timeout) return
85
+
86
+ debug(test.title, 'timeout', {
87
+ 'config from file': testTimeout,
88
+ 'suite timeout': suiteTimeout,
89
+ 'dynamic config': test.totalTimeout,
90
+ })
91
+
92
+ currentTimeout = timeout
93
+ output.debug(`Test Timeout: ${timeout}s`)
94
+ timeout *= 1000
95
+ })
96
+
97
+ event.dispatcher.on(event.test.passed, test => {
98
+ currentTest = null
99
+ })
100
+
101
+ event.dispatcher.on(event.test.failed, test => {
102
+ currentTest = null
103
+ })
104
+
105
+ event.dispatcher.on(event.step.before, step => {
106
+ if (typeof timeout !== 'number') return
107
+
108
+ if (!store.timeouts) {
109
+ debug('step', step.toCode().trim(), 'timeout disabled')
110
+ return
111
+ }
112
+
113
+ if (timeout < 0) {
114
+ debug('Previous steps timed out, setting timeout to 0.01s')
115
+ step.setTimeout(0.01, TIMEOUT_ORDER.testOrSuite)
116
+ } else {
117
+ debug(`Setting timeout ${timeout}ms for step ${step.toCode().trim()}`)
118
+ step.setTimeout(timeout, TIMEOUT_ORDER.testOrSuite)
119
+ }
120
+ })
121
+
122
+ event.dispatcher.on(event.step.after, step => {
123
+ if (typeof timeout !== 'number') return
124
+ if (!store.timeouts) return
125
+
126
+ recorder.catchWithoutStop(err => {
127
+ // we wrap timeout errors in a StepTimeoutError
128
+ // but only if global timeout is set
129
+ // should we wrap all timeout errors?
130
+ if (err instanceof TimeoutError) {
131
+ const testTimeoutExceeded = timeout && +Date.now() - step.startTime >= timeout
132
+ debug('Step failed due to global test or suite timeout')
133
+ if (testTimeoutExceeded) {
134
+ debug('Test failed due to global test or suite timeout')
135
+ throw new TestTimeoutError(currentTimeout)
136
+ }
137
+ throw new StepTimeoutError(currentTimeout, step)
138
+ }
139
+ throw err
140
+ })
141
+ })
142
+
143
+ event.dispatcher.on(event.step.finished, step => {
144
+ if (!store.timeouts) {
145
+ debug('step', step.toCode().trim(), 'timeout disabled')
146
+ return
147
+ }
148
+
149
+ if (typeof timeout === 'number') debug('Timeout', timeout)
150
+
151
+ debug(`step ${step.toCode().trim()}:${step.status} duration`, step.duration)
152
+ if (typeof timeout === 'number' && !Number.isNaN(timeout)) timeout -= step.duration
153
+
154
+ if (typeof timeout === 'number' && timeout <= 0 && recorder.isRunning()) {
155
+ debug(`step ${step.toCode().trim()} timed out`)
156
+ recorder.throw(new TestTimeoutError(currentTimeout))
157
+ }
158
+ })
159
+ }
160
+
161
+ function checkForSeconds(timeout) {
162
+ if (timeout >= 1000) {
163
+ console.log(`Warning: Timeout was set to ${timeout}secs.\nGlobal timeout should be specified in seconds.`)
164
+ }
165
+ }
@@ -12,7 +12,7 @@ module.exports = function () {
12
12
 
13
13
  const runHelpersHook = (hook, param) => {
14
14
  if (store.dryRun) return
15
- Object.values(helpers).forEach((helper) => {
15
+ Object.values(helpers).forEach(helper => {
16
16
  if (helper[hook]) {
17
17
  helper[hook](param)
18
18
  }
@@ -21,55 +21,55 @@ module.exports = function () {
21
21
 
22
22
  const runAsyncHelpersHook = (hook, param, force) => {
23
23
  if (store.dryRun) return
24
- Object.keys(helpers).forEach((key) => {
24
+ Object.keys(helpers).forEach(key => {
25
25
  if (!helpers[key][hook]) return
26
26
  recorder.add(`hook ${key}.${hook}()`, () => helpers[key][hook](param), force, false)
27
27
  })
28
28
  }
29
29
 
30
- event.dispatcher.on(event.suite.before, (suite) => {
30
+ event.dispatcher.on(event.suite.before, suite => {
31
31
  // if (suite.parent) return; // only for root suite
32
32
  runAsyncHelpersHook('_beforeSuite', suite, true)
33
33
  })
34
34
 
35
- event.dispatcher.on(event.suite.after, (suite) => {
35
+ event.dispatcher.on(event.suite.after, suite => {
36
36
  // if (suite.parent) return; // only for root suite
37
37
  runAsyncHelpersHook('_afterSuite', suite, true)
38
38
  })
39
39
 
40
- event.dispatcher.on(event.test.started, (test) => {
40
+ event.dispatcher.on(event.test.started, test => {
41
41
  runHelpersHook('_test', test)
42
- recorder.catch((e) => error(e))
42
+ recorder.catch(e => error(e))
43
43
  })
44
44
 
45
- event.dispatcher.on(event.test.before, (test) => {
45
+ event.dispatcher.on(event.test.before, test => {
46
46
  // schedule config to revert changes
47
47
  runAsyncHelpersHook('_before', test, true)
48
- recorder.catchWithoutStop((e) => error(e))
48
+ recorder.catchWithoutStop(e => error(e))
49
49
  })
50
50
 
51
- event.dispatcher.on(event.test.passed, (test) => {
51
+ event.dispatcher.on(event.test.passed, test => {
52
52
  runAsyncHelpersHook('_passed', test, true)
53
53
  // should not fail test execution, so errors should be caught
54
- recorder.catchWithoutStop((e) => error(e))
54
+ recorder.catchWithoutStop(e => error(e))
55
55
  })
56
56
 
57
- event.dispatcher.on(event.test.failed, (test) => {
57
+ event.dispatcher.on(event.test.failed, test => {
58
58
  runAsyncHelpersHook('_failed', test, true)
59
59
  // should not fail test execution, so errors should be caught
60
- recorder.catchWithoutStop((e) => error(e))
60
+ recorder.catchWithoutStop(e => error(e))
61
61
  })
62
62
 
63
63
  event.dispatcher.on(event.test.after, () => {
64
64
  runAsyncHelpersHook('_after', {}, true)
65
- recorder.catchWithoutStop((e) => error(e))
65
+ recorder.catchWithoutStop(e => error(e))
66
66
  })
67
67
 
68
- event.dispatcher.on(event.step.before, (step) => {
68
+ event.dispatcher.on(event.step.before, step => {
69
69
  runAsyncHelpersHook('_beforeStep', step)
70
70
  })
71
71
 
72
- event.dispatcher.on(event.step.after, (step) => {
72
+ event.dispatcher.on(event.step.after, step => {
73
73
  runAsyncHelpersHook('_afterStep', step)
74
74
  })
75
75
 
@@ -8,7 +8,7 @@ module.exports = function () {
8
8
  mocha = container.mocha()
9
9
  })
10
10
 
11
- event.dispatcher.on(event.test.passed, (test) => {
11
+ event.dispatcher.on(event.test.passed, test => {
12
12
  mocha.Runner.emit('pass', test)
13
13
  })
14
14
 
@@ -0,0 +1,12 @@
1
+ const event = require('../event')
2
+ const container = require('../container')
3
+
4
+ module.exports = function () {
5
+ event.dispatcher.on(event.hook.failed, err => {
6
+ container.result().addStats({ failedHooks: 1 })
7
+ })
8
+
9
+ event.dispatcher.on(event.test.before, test => {
10
+ container.result().addTest(test)
11
+ })
12
+ }
@@ -2,6 +2,7 @@ const debug = require('debug')('codeceptjs:steps')
2
2
  const event = require('../event')
3
3
  const store = require('../store')
4
4
  const output = require('../output')
5
+ const { BeforeHook, AfterHook, BeforeSuiteHook, AfterSuiteHook } = require('../mocha/hooks')
5
6
 
6
7
  let currentTest
7
8
  let currentHook
@@ -10,39 +11,42 @@ let currentHook
10
11
  * Register steps inside tests
11
12
  */
12
13
  module.exports = function () {
13
- event.dispatcher.on(event.test.before, (test) => {
14
+ event.dispatcher.on(event.test.before, test => {
14
15
  test.startedAt = +new Date()
15
- test.artifacts = {}
16
16
  })
17
17
 
18
- event.dispatcher.on(event.test.started, (test) => {
18
+ event.dispatcher.on(event.test.started, test => {
19
19
  currentTest = test
20
20
  currentTest.steps = []
21
21
  if (!('retryNum' in currentTest)) currentTest.retryNum = 0
22
22
  else currentTest.retryNum += 1
23
+ output.scenario.started(test)
23
24
  })
24
25
 
25
- event.dispatcher.on(event.test.after, (test) => {
26
+ event.dispatcher.on(event.test.after, test => {
26
27
  currentTest = null
27
28
  })
28
29
 
29
- event.dispatcher.on(event.test.finished, (test) => {})
30
+ event.dispatcher.on(event.test.finished, test => {})
30
31
 
31
- event.dispatcher.on(event.hook.started, (suite) => {
32
- currentHook = suite.ctx.test
32
+ event.dispatcher.on(event.hook.started, hook => {
33
+ currentHook = hook.ctx.test
33
34
  currentHook.steps = []
34
35
 
35
- if (suite.ctx && suite.ctx.test) output.log(`--- STARTED ${suite.ctx.test.title} ---`)
36
+ output.hook.started(hook)
37
+
38
+ if (hook.ctx && hook.ctx.test) debug(`--- STARTED ${hook.ctx.test.title} ---`)
36
39
  })
37
40
 
38
- event.dispatcher.on(event.hook.passed, (suite) => {
41
+ event.dispatcher.on(event.hook.passed, hook => {
39
42
  currentHook = null
40
- if (suite.ctx && suite.ctx.test) output.log(`--- ENDED ${suite.ctx.test.title} ---`)
43
+ output.hook.passed(hook)
44
+ if (hook.ctx && hook.ctx.test) debug(`--- ENDED ${hook.ctx.test.title} ---`)
41
45
  })
42
46
 
43
47
  event.dispatcher.on(event.test.failed, () => {
44
48
  const cutSteps = function (current) {
45
- const failureIndex = current.steps.findIndex((el) => el.status === 'failed')
49
+ const failureIndex = current.steps.findIndex(el => el.status === 'failed')
46
50
  // To be sure that failed test will be failed in report
47
51
  current.state = 'failed'
48
52
  current.steps.length = failureIndex + 1
@@ -65,9 +69,8 @@ module.exports = function () {
65
69
  currentTest.state = 'passed'
66
70
  })
67
71
 
68
- event.dispatcher.on(event.step.started, (step) => {
69
- step.startedAt = +new Date()
70
- step.test = currentTest
72
+ event.dispatcher.on(event.step.started, step => {
73
+ store.currentStep = step
71
74
  if (currentHook && Array.isArray(currentHook.steps)) {
72
75
  return currentHook.steps.push(step)
73
76
  }
@@ -75,9 +78,8 @@ module.exports = function () {
75
78
  currentTest.steps.push(step)
76
79
  })
77
80
 
78
- event.dispatcher.on(event.step.finished, (step) => {
79
- step.finishedAt = +new Date()
80
- if (step.startedAt) step.duration = step.finishedAt - step.startedAt
81
- debug(`Step '${step}' finished; Duration: ${step.duration || 0}ms`)
81
+ event.dispatcher.on(event.step.finished, step => {
82
+ store.currentStep = null
83
+ store.stepOptions = null
82
84
  })
83
85
  }
@@ -0,0 +1,20 @@
1
+ const event = require('../event')
2
+ const store = require('../store')
3
+
4
+ module.exports = function () {
5
+ event.dispatcher.on(event.suite.before, suite => {
6
+ store.currentSuite = suite
7
+ })
8
+
9
+ event.dispatcher.on(event.suite.after, () => {
10
+ store.currentSuite = null
11
+ })
12
+
13
+ event.dispatcher.on(event.test.before, test => {
14
+ store.currentTest = test
15
+ })
16
+
17
+ event.dispatcher.on(event.test.finished, () => {
18
+ store.currentTest = null
19
+ })
20
+ }