codeceptjs 3.6.4 → 3.6.5-beta.1
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 -63
- package/lib/assert/empty.js +19 -19
- package/lib/assert/equal.js +32 -30
- package/lib/assert/error.js +14 -14
- package/lib/assert/include.js +42 -42
- package/lib/assert/throws.js +13 -11
- package/lib/assert/truth.js +17 -18
- package/lib/command/configMigrate.js +57 -52
- package/lib/command/definitions.js +88 -88
- package/lib/command/dryRun.js +65 -63
- package/lib/command/generate.js +191 -181
- package/lib/command/info.js +39 -37
- package/lib/command/init.js +289 -286
- package/lib/command/interactive.js +32 -32
- package/lib/command/list.js +26 -26
- package/lib/command/run-multiple.js +113 -93
- package/lib/command/run-rerun.js +22 -22
- package/lib/command/run-workers.js +63 -63
- package/lib/command/run.js +24 -26
- package/lib/command/utils.js +64 -63
- package/lib/data/context.js +60 -60
- package/lib/data/dataScenarioConfig.js +47 -47
- package/lib/data/dataTableArgument.js +29 -29
- package/lib/data/table.js +26 -20
- package/lib/helper/AI.js +67 -65
- package/lib/helper/ApiDataFactory.js +72 -69
- package/lib/helper/Appium.js +409 -379
- package/lib/helper/ExpectHelper.js +214 -248
- package/lib/helper/FileSystem.js +77 -78
- package/lib/helper/GraphQL.js +44 -43
- package/lib/helper/GraphQLDataFactory.js +49 -50
- package/lib/helper/JSONResponse.js +64 -62
- package/lib/helper/Mochawesome.js +28 -28
- package/lib/helper/MockServer.js +12 -12
- package/lib/helper/Nightmare.js +664 -572
- package/lib/helper/Playwright.js +1320 -1211
- package/lib/helper/Protractor.js +663 -629
- package/lib/helper/Puppeteer.js +1232 -1124
- package/lib/helper/REST.js +87 -72
- package/lib/helper/TestCafe.js +490 -491
- package/lib/helper/WebDriver.js +1294 -1156
- package/lib/interfaces/bdd.js +38 -51
- package/lib/interfaces/featureConfig.js +19 -19
- package/lib/interfaces/gherkin.js +122 -111
- package/lib/interfaces/scenarioConfig.js +29 -29
- package/lib/listener/artifacts.js +9 -9
- package/lib/listener/config.js +24 -23
- 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 -51
- package/lib/listener/timeout.js +53 -53
- package/lib/plugin/allure.js +14 -14
- package/lib/plugin/autoDelay.js +29 -36
- package/lib/plugin/autoLogin.js +70 -66
- package/lib/plugin/commentStep.js +18 -18
- package/lib/plugin/coverage.js +92 -77
- package/lib/plugin/customLocator.js +20 -19
- package/lib/plugin/debugErrors.js +24 -24
- package/lib/plugin/eachElement.js +37 -37
- package/lib/plugin/fakerTransform.js +6 -6
- package/lib/plugin/heal.js +66 -63
- package/lib/plugin/pauseOnFail.js +10 -10
- package/lib/plugin/retryFailedStep.js +31 -38
- package/lib/plugin/retryTo.js +28 -28
- package/lib/plugin/screenshotOnFail.js +107 -86
- package/lib/plugin/selenoid.js +131 -117
- package/lib/plugin/standardActingHelpers.js +2 -8
- package/lib/plugin/stepByStepReport.js +102 -92
- package/lib/plugin/stepTimeout.js +23 -22
- package/lib/plugin/subtitles.js +34 -34
- package/lib/plugin/tryTo.js +39 -29
- package/lib/plugin/wdio.js +77 -72
- package/lib/template/heal.js +11 -14
- package/package.json +4 -2
- package/translations/de-DE.js +1 -1
- package/translations/fr-FR.js +1 -1
- package/translations/index.js +9 -9
- 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/promiseBasedTypes.d.ts +238 -0
- package/typings/types.d.ts +32 -0
package/lib/listener/config.js
CHANGED
|
@@ -1,45 +1,46 @@
|
|
|
1
|
-
const event = require('../event')
|
|
2
|
-
const container = require('../container')
|
|
3
|
-
const recorder = require('../recorder')
|
|
4
|
-
const { deepMerge, deepClone, ucfirst } = require('../utils')
|
|
5
|
-
const { debug } = require('../output')
|
|
1
|
+
const event = require('../event')
|
|
2
|
+
const container = require('../container')
|
|
3
|
+
const recorder = require('../recorder')
|
|
4
|
+
const { deepMerge, deepClone, ucfirst } = require('../utils')
|
|
5
|
+
const { debug } = require('../output')
|
|
6
6
|
/**
|
|
7
7
|
* Enable Helpers to listen to test events
|
|
8
8
|
*/
|
|
9
9
|
module.exports = function () {
|
|
10
|
-
const helpers = container.helpers()
|
|
10
|
+
const helpers = container.helpers()
|
|
11
11
|
|
|
12
|
-
enableDynamicConfigFor('suite')
|
|
13
|
-
enableDynamicConfigFor('test')
|
|
12
|
+
enableDynamicConfigFor('suite')
|
|
13
|
+
enableDynamicConfigFor('test')
|
|
14
14
|
|
|
15
15
|
function enableDynamicConfigFor(type) {
|
|
16
16
|
event.dispatcher.on(event[type].before, (context = {}) => {
|
|
17
17
|
function updateHelperConfig(helper, config) {
|
|
18
|
-
const oldConfig = { ...helper.options }
|
|
18
|
+
const oldConfig = { ...helper.options }
|
|
19
19
|
try {
|
|
20
|
-
helper._setConfig(deepMerge(deepClone(oldConfig), config))
|
|
21
|
-
debug(`[${ucfirst(type)} Config] ${helper.constructor.name} ${JSON.stringify(config)}`)
|
|
20
|
+
helper._setConfig(deepMerge(deepClone(oldConfig), config))
|
|
21
|
+
debug(`[${ucfirst(type)} Config] ${helper.constructor.name} ${JSON.stringify(config)}`)
|
|
22
22
|
} catch (err) {
|
|
23
|
-
recorder.throw(err)
|
|
24
|
-
return
|
|
23
|
+
recorder.throw(err)
|
|
24
|
+
return
|
|
25
25
|
}
|
|
26
26
|
event.dispatcher.once(event[type].after, () => {
|
|
27
|
-
helper._setConfig(oldConfig)
|
|
28
|
-
debug(`[${ucfirst(type)} Config] Reverted for ${helper.constructor.name}`)
|
|
29
|
-
})
|
|
27
|
+
helper._setConfig(oldConfig)
|
|
28
|
+
debug(`[${ucfirst(type)} Config] Reverted for ${helper.constructor.name}`)
|
|
29
|
+
})
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// change config
|
|
33
33
|
if (context.config) {
|
|
34
34
|
for (let name in context.config) {
|
|
35
|
-
const config = context.config[name]
|
|
36
|
-
if (name === '0') {
|
|
37
|
-
|
|
35
|
+
const config = context.config[name]
|
|
36
|
+
if (name === '0') {
|
|
37
|
+
// first helper
|
|
38
|
+
name = Object.keys(helpers)[0]
|
|
38
39
|
}
|
|
39
|
-
const helper = helpers[name]
|
|
40
|
-
updateHelperConfig(helper, config)
|
|
40
|
+
const helper = helpers[name]
|
|
41
|
+
updateHelperConfig(helper, config)
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
|
-
})
|
|
44
|
+
})
|
|
44
45
|
}
|
|
45
|
-
}
|
|
46
|
+
}
|
package/lib/listener/exit.js
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
const event = require('../event')
|
|
1
|
+
const event = require('../event')
|
|
2
2
|
|
|
3
3
|
module.exports = function () {
|
|
4
|
-
let failedTests = []
|
|
4
|
+
let failedTests = []
|
|
5
5
|
|
|
6
6
|
event.dispatcher.on(event.test.failed, (testOrSuite) => {
|
|
7
7
|
// NOTE When an error happens in one of the hooks (BeforeAll/BeforeEach...) the event object
|
|
8
8
|
// is a suite and not a test
|
|
9
|
-
const id = testOrSuite.uid || (testOrSuite.ctx && testOrSuite.ctx.test.uid) || 'empty'
|
|
10
|
-
failedTests.push(id)
|
|
11
|
-
})
|
|
9
|
+
const id = testOrSuite.uid || (testOrSuite.ctx && testOrSuite.ctx.test.uid) || 'empty'
|
|
10
|
+
failedTests.push(id)
|
|
11
|
+
})
|
|
12
12
|
|
|
13
13
|
// if test was successful after retries
|
|
14
14
|
event.dispatcher.on(event.test.passed, (testOrSuite) => {
|
|
15
15
|
// NOTE When an error happens in one of the hooks (BeforeAll/BeforeEach...) the event object
|
|
16
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)
|
|
19
|
-
})
|
|
17
|
+
const id = testOrSuite.uid || (testOrSuite.ctx && testOrSuite.ctx.test.uid) || 'empty'
|
|
18
|
+
failedTests = failedTests.filter((failed) => id !== failed)
|
|
19
|
+
})
|
|
20
20
|
|
|
21
21
|
process.on('beforeExit', (code) => {
|
|
22
22
|
if (failedTests.length) {
|
|
23
|
-
code = 1
|
|
23
|
+
code = 1
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
if (code) {
|
|
27
|
-
process.exit(code)
|
|
27
|
+
process.exit(code)
|
|
28
28
|
}
|
|
29
|
-
})
|
|
30
|
-
}
|
|
29
|
+
})
|
|
30
|
+
}
|
package/lib/listener/helpers.js
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
const path = require('path')
|
|
2
|
-
const event = require('../event')
|
|
3
|
-
const container = require('../container')
|
|
4
|
-
const recorder = require('../recorder')
|
|
5
|
-
const store = require('../store')
|
|
6
|
-
const { error } = require('../output')
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const event = require('../event')
|
|
3
|
+
const container = require('../container')
|
|
4
|
+
const recorder = require('../recorder')
|
|
5
|
+
const store = require('../store')
|
|
6
|
+
const { error } = require('../output')
|
|
7
7
|
/**
|
|
8
8
|
* Enable Helpers to listen to test events
|
|
9
9
|
*/
|
|
10
10
|
module.exports = function () {
|
|
11
|
-
const helpers = container.helpers()
|
|
11
|
+
const helpers = container.helpers()
|
|
12
12
|
|
|
13
13
|
const runHelpersHook = (hook, param) => {
|
|
14
|
-
if (store.dryRun) return
|
|
14
|
+
if (store.dryRun) return
|
|
15
15
|
Object.values(helpers).forEach((helper) => {
|
|
16
16
|
if (helper[hook]) {
|
|
17
|
-
helper[hook](param)
|
|
17
|
+
helper[hook](param)
|
|
18
18
|
}
|
|
19
|
-
})
|
|
20
|
-
}
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
21
|
|
|
22
22
|
const runAsyncHelpersHook = (hook, param, force) => {
|
|
23
|
-
if (store.dryRun) return
|
|
23
|
+
if (store.dryRun) return
|
|
24
24
|
Object.keys(helpers).forEach((key) => {
|
|
25
|
-
if (!helpers[key][hook]) return
|
|
26
|
-
recorder.add(`hook ${key}.${hook}()`, () => helpers[key][hook](param), force, false)
|
|
27
|
-
})
|
|
28
|
-
}
|
|
25
|
+
if (!helpers[key][hook]) return
|
|
26
|
+
recorder.add(`hook ${key}.${hook}()`, () => helpers[key][hook](param), force, false)
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
29
|
|
|
30
30
|
event.dispatcher.on(event.suite.before, (suite) => {
|
|
31
31
|
// if (suite.parent) return; // only for root suite
|
|
32
|
-
runAsyncHelpersHook('_beforeSuite', suite, true)
|
|
33
|
-
})
|
|
32
|
+
runAsyncHelpersHook('_beforeSuite', suite, true)
|
|
33
|
+
})
|
|
34
34
|
|
|
35
35
|
event.dispatcher.on(event.suite.after, (suite) => {
|
|
36
36
|
// if (suite.parent) return; // only for root suite
|
|
37
|
-
runAsyncHelpersHook('_afterSuite', suite, true)
|
|
38
|
-
})
|
|
37
|
+
runAsyncHelpersHook('_afterSuite', suite, true)
|
|
38
|
+
})
|
|
39
39
|
|
|
40
40
|
event.dispatcher.on(event.test.started, (test) => {
|
|
41
|
-
runHelpersHook('_test', test)
|
|
42
|
-
recorder.catch(e => error(e))
|
|
43
|
-
})
|
|
41
|
+
runHelpersHook('_test', test)
|
|
42
|
+
recorder.catch((e) => error(e))
|
|
43
|
+
})
|
|
44
44
|
|
|
45
45
|
event.dispatcher.on(event.test.before, (test) => {
|
|
46
46
|
// schedule config to revert changes
|
|
47
|
-
runAsyncHelpersHook('_before', test, true)
|
|
48
|
-
recorder.catchWithoutStop(e => error(e))
|
|
49
|
-
})
|
|
47
|
+
runAsyncHelpersHook('_before', test, true)
|
|
48
|
+
recorder.catchWithoutStop((e) => error(e))
|
|
49
|
+
})
|
|
50
50
|
|
|
51
51
|
event.dispatcher.on(event.test.passed, (test) => {
|
|
52
|
-
runAsyncHelpersHook('_passed', test, true)
|
|
52
|
+
runAsyncHelpersHook('_passed', test, true)
|
|
53
53
|
// should not fail test execution, so errors should be caught
|
|
54
|
-
recorder.catchWithoutStop(e => error(e))
|
|
55
|
-
})
|
|
54
|
+
recorder.catchWithoutStop((e) => error(e))
|
|
55
|
+
})
|
|
56
56
|
|
|
57
57
|
event.dispatcher.on(event.test.failed, (test) => {
|
|
58
|
-
runAsyncHelpersHook('_failed', test, true)
|
|
58
|
+
runAsyncHelpersHook('_failed', test, true)
|
|
59
59
|
// should not fail test execution, so errors should be caught
|
|
60
|
-
recorder.catchWithoutStop(e => error(e))
|
|
61
|
-
})
|
|
60
|
+
recorder.catchWithoutStop((e) => error(e))
|
|
61
|
+
})
|
|
62
62
|
|
|
63
63
|
event.dispatcher.on(event.test.after, () => {
|
|
64
|
-
runAsyncHelpersHook('_after', {}, true)
|
|
65
|
-
recorder.catchWithoutStop(e => error(e))
|
|
66
|
-
})
|
|
64
|
+
runAsyncHelpersHook('_after', {}, true)
|
|
65
|
+
recorder.catchWithoutStop((e) => error(e))
|
|
66
|
+
})
|
|
67
67
|
|
|
68
68
|
event.dispatcher.on(event.step.before, (step) => {
|
|
69
|
-
runAsyncHelpersHook('_beforeStep', step)
|
|
70
|
-
})
|
|
69
|
+
runAsyncHelpersHook('_beforeStep', step)
|
|
70
|
+
})
|
|
71
71
|
|
|
72
72
|
event.dispatcher.on(event.step.after, (step) => {
|
|
73
|
-
runAsyncHelpersHook('_afterStep', step)
|
|
74
|
-
})
|
|
73
|
+
runAsyncHelpersHook('_afterStep', step)
|
|
74
|
+
})
|
|
75
75
|
|
|
76
76
|
event.dispatcher.on(event.all.result, () => {
|
|
77
|
-
runAsyncHelpersHook('_finishTest', {}, true)
|
|
78
|
-
})
|
|
79
|
-
}
|
|
77
|
+
runAsyncHelpersHook('_finishTest', {}, true)
|
|
78
|
+
})
|
|
79
|
+
}
|
package/lib/listener/mocha.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
const event = require('../event')
|
|
2
|
-
const container = require('../container')
|
|
1
|
+
const event = require('../event')
|
|
2
|
+
const container = require('../container')
|
|
3
3
|
|
|
4
4
|
module.exports = function () {
|
|
5
|
-
let mocha
|
|
5
|
+
let mocha
|
|
6
6
|
|
|
7
7
|
event.dispatcher.on(event.all.before, () => {
|
|
8
|
-
mocha = container.mocha()
|
|
9
|
-
})
|
|
8
|
+
mocha = container.mocha()
|
|
9
|
+
})
|
|
10
10
|
|
|
11
11
|
event.dispatcher.on(event.test.passed, (test) => {
|
|
12
|
-
mocha.Runner.emit('pass', test)
|
|
13
|
-
})
|
|
12
|
+
mocha.Runner.emit('pass', test)
|
|
13
|
+
})
|
|
14
14
|
|
|
15
15
|
event.dispatcher.on(event.test.failed, (test, err) => {
|
|
16
|
-
test.state = 'failed'
|
|
17
|
-
mocha.Runner.emit('fail', test, err)
|
|
18
|
-
})
|
|
19
|
-
}
|
|
16
|
+
test.state = 'failed'
|
|
17
|
+
mocha.Runner.emit('fail', test, err)
|
|
18
|
+
})
|
|
19
|
+
}
|
package/lib/listener/retry.js
CHANGED
|
@@ -1,68 +1,70 @@
|
|
|
1
|
-
const event = require('../event')
|
|
2
|
-
const output = require('../output')
|
|
3
|
-
const Config = require('../config')
|
|
4
|
-
const { isNotSet } = require('../utils')
|
|
1
|
+
const event = require('../event')
|
|
2
|
+
const output = require('../output')
|
|
3
|
+
const Config = require('../config')
|
|
4
|
+
const { isNotSet } = require('../utils')
|
|
5
5
|
|
|
6
|
-
const hooks = ['Before', 'After', 'BeforeSuite', 'AfterSuite']
|
|
6
|
+
const hooks = ['Before', 'After', 'BeforeSuite', 'AfterSuite']
|
|
7
7
|
|
|
8
8
|
module.exports = function () {
|
|
9
9
|
event.dispatcher.on(event.suite.before, (suite) => {
|
|
10
|
-
let retryConfig = Config.get('retry')
|
|
11
|
-
if (!retryConfig) return
|
|
10
|
+
let retryConfig = Config.get('retry')
|
|
11
|
+
if (!retryConfig) return
|
|
12
12
|
|
|
13
13
|
if (Number.isInteger(+retryConfig)) {
|
|
14
14
|
// is number
|
|
15
|
-
const retryNum = +retryConfig
|
|
16
|
-
output.log(`Retries: ${retryNum}`)
|
|
17
|
-
suite.retries(retryNum)
|
|
18
|
-
return
|
|
15
|
+
const retryNum = +retryConfig
|
|
16
|
+
output.log(`Retries: ${retryNum}`)
|
|
17
|
+
suite.retries(retryNum)
|
|
18
|
+
return
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
if (!Array.isArray(retryConfig)) {
|
|
22
|
-
retryConfig = [retryConfig]
|
|
22
|
+
retryConfig = [retryConfig]
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
for (const config of retryConfig) {
|
|
26
26
|
if (config.grep) {
|
|
27
|
-
if (!suite.title.includes(config.grep)) continue
|
|
27
|
+
if (!suite.title.includes(config.grep)) continue
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
hooks
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
hooks
|
|
31
|
+
.filter((hook) => !!config[hook])
|
|
32
|
+
.forEach((hook) => {
|
|
33
|
+
if (isNotSet(suite.opts[`retry${hook}`])) suite.opts[`retry${hook}`] = config[hook]
|
|
34
|
+
})
|
|
33
35
|
|
|
34
36
|
if (config.Feature) {
|
|
35
|
-
if (isNotSet(suite.retries())) suite.retries(config.Feature)
|
|
37
|
+
if (isNotSet(suite.retries())) suite.retries(config.Feature)
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
output.log(`Retries: ${JSON.stringify(config)}`)
|
|
40
|
+
output.log(`Retries: ${JSON.stringify(config)}`)
|
|
39
41
|
}
|
|
40
|
-
})
|
|
42
|
+
})
|
|
41
43
|
|
|
42
44
|
event.dispatcher.on(event.test.before, (test) => {
|
|
43
|
-
let retryConfig = Config.get('retry')
|
|
44
|
-
if (!retryConfig) return
|
|
45
|
+
let retryConfig = Config.get('retry')
|
|
46
|
+
if (!retryConfig) return
|
|
45
47
|
|
|
46
48
|
if (Number.isInteger(+retryConfig)) {
|
|
47
|
-
if (test.retries() === -1) test.retries(retryConfig)
|
|
48
|
-
return
|
|
49
|
+
if (test.retries() === -1) test.retries(retryConfig)
|
|
50
|
+
return
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
if (!Array.isArray(retryConfig)) {
|
|
52
|
-
retryConfig = [retryConfig]
|
|
54
|
+
retryConfig = [retryConfig]
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
retryConfig = retryConfig.filter(config => !!config.Scenario)
|
|
57
|
+
retryConfig = retryConfig.filter((config) => !!config.Scenario)
|
|
56
58
|
|
|
57
59
|
for (const config of retryConfig) {
|
|
58
60
|
if (config.grep) {
|
|
59
|
-
if (!test.fullTitle().includes(config.grep)) continue
|
|
61
|
+
if (!test.fullTitle().includes(config.grep)) continue
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
if (config.Scenario) {
|
|
63
|
-
if (test.retries() === -1) test.retries(config.Scenario)
|
|
64
|
-
output.log(`Retries: ${config.Scenario}`)
|
|
65
|
+
if (test.retries() === -1) test.retries(config.Scenario)
|
|
66
|
+
output.log(`Retries: ${config.Scenario}`)
|
|
65
67
|
}
|
|
66
68
|
}
|
|
67
|
-
})
|
|
68
|
-
}
|
|
69
|
+
})
|
|
70
|
+
}
|
package/lib/listener/steps.js
CHANGED
|
@@ -1,84 +1,83 @@
|
|
|
1
|
-
const debug = require('debug')('codeceptjs:steps')
|
|
2
|
-
const event = require('../event')
|
|
3
|
-
const store = require('../store')
|
|
4
|
-
const output = require('../output')
|
|
1
|
+
const debug = require('debug')('codeceptjs:steps')
|
|
2
|
+
const event = require('../event')
|
|
3
|
+
const store = require('../store')
|
|
4
|
+
const output = require('../output')
|
|
5
5
|
|
|
6
|
-
let currentTest
|
|
7
|
-
let currentHook
|
|
6
|
+
let currentTest
|
|
7
|
+
let currentHook
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Register steps inside tests
|
|
11
11
|
*/
|
|
12
12
|
module.exports = function () {
|
|
13
13
|
event.dispatcher.on(event.test.before, (test) => {
|
|
14
|
-
test.startedAt = +new Date()
|
|
15
|
-
test.artifacts = {}
|
|
16
|
-
})
|
|
14
|
+
test.startedAt = +new Date()
|
|
15
|
+
test.artifacts = {}
|
|
16
|
+
})
|
|
17
17
|
|
|
18
18
|
event.dispatcher.on(event.test.started, (test) => {
|
|
19
|
-
currentTest = test
|
|
20
|
-
currentTest.steps = []
|
|
21
|
-
if (!('retryNum' in currentTest)) currentTest.retryNum = 0
|
|
22
|
-
else currentTest.retryNum += 1
|
|
23
|
-
})
|
|
19
|
+
currentTest = test
|
|
20
|
+
currentTest.steps = []
|
|
21
|
+
if (!('retryNum' in currentTest)) currentTest.retryNum = 0
|
|
22
|
+
else currentTest.retryNum += 1
|
|
23
|
+
})
|
|
24
24
|
|
|
25
25
|
event.dispatcher.on(event.test.after, (test) => {
|
|
26
|
-
currentTest = null
|
|
27
|
-
})
|
|
26
|
+
currentTest = null
|
|
27
|
+
})
|
|
28
28
|
|
|
29
|
-
event.dispatcher.on(event.test.finished, (test) => {
|
|
30
|
-
});
|
|
29
|
+
event.dispatcher.on(event.test.finished, (test) => {})
|
|
31
30
|
|
|
32
31
|
event.dispatcher.on(event.hook.started, (suite) => {
|
|
33
|
-
currentHook = suite.ctx.test
|
|
34
|
-
currentHook.steps = []
|
|
32
|
+
currentHook = suite.ctx.test
|
|
33
|
+
currentHook.steps = []
|
|
35
34
|
|
|
36
|
-
if (suite.ctx && suite.ctx.test) output.log(`--- STARTED ${suite.ctx.test.title} ---`)
|
|
37
|
-
})
|
|
35
|
+
if (suite.ctx && suite.ctx.test) output.log(`--- STARTED ${suite.ctx.test.title} ---`)
|
|
36
|
+
})
|
|
38
37
|
|
|
39
38
|
event.dispatcher.on(event.hook.passed, (suite) => {
|
|
40
|
-
currentHook = null
|
|
41
|
-
if (suite.ctx && suite.ctx.test) output.log(`--- ENDED ${suite.ctx.test.title} ---`)
|
|
42
|
-
})
|
|
39
|
+
currentHook = null
|
|
40
|
+
if (suite.ctx && suite.ctx.test) output.log(`--- ENDED ${suite.ctx.test.title} ---`)
|
|
41
|
+
})
|
|
43
42
|
|
|
44
43
|
event.dispatcher.on(event.test.failed, () => {
|
|
45
44
|
const cutSteps = function (current) {
|
|
46
|
-
const failureIndex = current.steps.findIndex(el => el.status === 'failed')
|
|
45
|
+
const failureIndex = current.steps.findIndex((el) => el.status === 'failed')
|
|
47
46
|
// To be sure that failed test will be failed in report
|
|
48
|
-
current.state = 'failed'
|
|
49
|
-
current.steps.length = failureIndex + 1
|
|
50
|
-
return current
|
|
51
|
-
}
|
|
47
|
+
current.state = 'failed'
|
|
48
|
+
current.steps.length = failureIndex + 1
|
|
49
|
+
return current
|
|
50
|
+
}
|
|
52
51
|
if (currentHook && Array.isArray(currentHook.steps) && currentHook.steps.length) {
|
|
53
|
-
currentHook = cutSteps(currentHook)
|
|
54
|
-
return currentHook = null
|
|
52
|
+
currentHook = cutSteps(currentHook)
|
|
53
|
+
return (currentHook = null)
|
|
55
54
|
}
|
|
56
|
-
if (!currentTest) return
|
|
55
|
+
if (!currentTest) return
|
|
57
56
|
// last step is failing step
|
|
58
|
-
if (!currentTest.steps.length) return
|
|
59
|
-
return currentTest = cutSteps(currentTest)
|
|
60
|
-
})
|
|
57
|
+
if (!currentTest.steps.length) return
|
|
58
|
+
return (currentTest = cutSteps(currentTest))
|
|
59
|
+
})
|
|
61
60
|
|
|
62
61
|
event.dispatcher.on(event.test.passed, () => {
|
|
63
|
-
if (!currentTest) return
|
|
62
|
+
if (!currentTest) return
|
|
64
63
|
// To be sure that passed test will be passed in report
|
|
65
|
-
delete currentTest.err
|
|
66
|
-
currentTest.state = 'passed'
|
|
67
|
-
})
|
|
64
|
+
delete currentTest.err
|
|
65
|
+
currentTest.state = 'passed'
|
|
66
|
+
})
|
|
68
67
|
|
|
69
68
|
event.dispatcher.on(event.step.started, (step) => {
|
|
70
|
-
step.startedAt = +new Date()
|
|
71
|
-
step.test = currentTest
|
|
69
|
+
step.startedAt = +new Date()
|
|
70
|
+
step.test = currentTest
|
|
72
71
|
if (currentHook && Array.isArray(currentHook.steps)) {
|
|
73
|
-
return currentHook.steps.push(step)
|
|
72
|
+
return currentHook.steps.push(step)
|
|
74
73
|
}
|
|
75
|
-
if (!currentTest || !currentTest.steps) return
|
|
76
|
-
currentTest.steps.push(step)
|
|
77
|
-
})
|
|
74
|
+
if (!currentTest || !currentTest.steps) return
|
|
75
|
+
currentTest.steps.push(step)
|
|
76
|
+
})
|
|
78
77
|
|
|
79
78
|
event.dispatcher.on(event.step.finished, (step) => {
|
|
80
|
-
step.finishedAt = +new Date()
|
|
81
|
-
if (step.startedAt) step.duration = step.finishedAt - step.startedAt
|
|
82
|
-
debug(`Step '${step}' finished; Duration: ${step.duration || 0}ms`)
|
|
83
|
-
})
|
|
84
|
-
}
|
|
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`)
|
|
82
|
+
})
|
|
83
|
+
}
|
package/lib/listener/timeout.js
CHANGED
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
const event = require('../event')
|
|
2
|
-
const output = require('../output')
|
|
3
|
-
const recorder = require('../recorder')
|
|
4
|
-
const Config = require('../config')
|
|
5
|
-
const { timeouts } = require('../store')
|
|
6
|
-
const TIMEOUT_ORDER = require('../step').TIMEOUT_ORDER
|
|
1
|
+
const event = require('../event')
|
|
2
|
+
const output = require('../output')
|
|
3
|
+
const recorder = require('../recorder')
|
|
4
|
+
const Config = require('../config')
|
|
5
|
+
const { timeouts } = require('../store')
|
|
6
|
+
const TIMEOUT_ORDER = require('../step').TIMEOUT_ORDER
|
|
7
7
|
|
|
8
8
|
module.exports = function () {
|
|
9
|
-
let timeout
|
|
10
|
-
let suiteTimeout = []
|
|
11
|
-
let currentTest
|
|
12
|
-
let currentTimeout
|
|
9
|
+
let timeout
|
|
10
|
+
let suiteTimeout = []
|
|
11
|
+
let currentTest
|
|
12
|
+
let currentTimeout
|
|
13
13
|
|
|
14
14
|
if (!timeouts) {
|
|
15
|
-
console.log('Timeouts were disabled')
|
|
16
|
-
return
|
|
15
|
+
console.log('Timeouts were disabled')
|
|
16
|
+
return
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
event.dispatcher.on(event.suite.before, (suite) => {
|
|
20
|
-
suiteTimeout = []
|
|
21
|
-
let timeoutConfig = Config.get('timeout')
|
|
20
|
+
suiteTimeout = []
|
|
21
|
+
let timeoutConfig = Config.get('timeout')
|
|
22
22
|
|
|
23
23
|
if (timeoutConfig) {
|
|
24
24
|
if (!Number.isNaN(+timeoutConfig)) {
|
|
25
|
-
checkForSeconds(timeoutConfig)
|
|
26
|
-
suiteTimeout.push(timeoutConfig)
|
|
25
|
+
checkForSeconds(timeoutConfig)
|
|
26
|
+
suiteTimeout.push(timeoutConfig)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
if (!Array.isArray(timeoutConfig)) {
|
|
30
|
-
timeoutConfig = [timeoutConfig]
|
|
30
|
+
timeoutConfig = [timeoutConfig]
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
for (const config of timeoutConfig.filter(c => !!c.Feature)) {
|
|
33
|
+
for (const config of timeoutConfig.filter((c) => !!c.Feature)) {
|
|
34
34
|
if (config.grep) {
|
|
35
|
-
if (!suite.title.includes(config.grep)) continue
|
|
35
|
+
if (!suite.title.includes(config.grep)) continue
|
|
36
36
|
}
|
|
37
|
-
suiteTimeout.push(config.Feature)
|
|
37
|
+
suiteTimeout.push(config.Feature)
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
if (suite.totalTimeout) suiteTimeout.push(suite.totalTimeout)
|
|
42
|
-
output.log(`Timeouts: ${suiteTimeout}`)
|
|
43
|
-
})
|
|
41
|
+
if (suite.totalTimeout) suiteTimeout.push(suite.totalTimeout)
|
|
42
|
+
output.log(`Timeouts: ${suiteTimeout}`)
|
|
43
|
+
})
|
|
44
44
|
|
|
45
45
|
event.dispatcher.on(event.test.before, (test) => {
|
|
46
|
-
currentTest = test
|
|
47
|
-
let testTimeout = null
|
|
46
|
+
currentTest = test
|
|
47
|
+
let testTimeout = null
|
|
48
48
|
|
|
49
|
-
let timeoutConfig = Config.get('timeout')
|
|
49
|
+
let timeoutConfig = Config.get('timeout')
|
|
50
50
|
|
|
51
51
|
if (typeof timeoutConfig === 'object' || Array.isArray(timeoutConfig)) {
|
|
52
52
|
if (!Array.isArray(timeoutConfig)) {
|
|
53
|
-
timeoutConfig = [timeoutConfig]
|
|
53
|
+
timeoutConfig = [timeoutConfig]
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
for (const config of timeoutConfig.filter(c => !!c.Scenario)) {
|
|
57
|
-
console.log('Test Timeout', config, test.title.includes(config.grep))
|
|
56
|
+
for (const config of timeoutConfig.filter((c) => !!c.Scenario)) {
|
|
57
|
+
console.log('Test Timeout', config, test.title.includes(config.grep))
|
|
58
58
|
if (config.grep) {
|
|
59
|
-
if (!test.title.includes(config.grep)) continue
|
|
59
|
+
if (!test.title.includes(config.grep)) continue
|
|
60
60
|
}
|
|
61
|
-
testTimeout = config.Scenario
|
|
61
|
+
testTimeout = config.Scenario
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
timeout = test.totalTimeout || testTimeout || suiteTimeout[suiteTimeout.length - 1]
|
|
66
|
-
if (!timeout) return
|
|
67
|
-
currentTimeout = timeout
|
|
68
|
-
output.debug(`Test Timeout: ${timeout}s`)
|
|
69
|
-
timeout *= 1000
|
|
70
|
-
})
|
|
65
|
+
timeout = test.totalTimeout || testTimeout || suiteTimeout[suiteTimeout.length - 1]
|
|
66
|
+
if (!timeout) return
|
|
67
|
+
currentTimeout = timeout
|
|
68
|
+
output.debug(`Test Timeout: ${timeout}s`)
|
|
69
|
+
timeout *= 1000
|
|
70
|
+
})
|
|
71
71
|
|
|
72
72
|
event.dispatcher.on(event.test.passed, (test) => {
|
|
73
|
-
currentTest = null
|
|
74
|
-
})
|
|
73
|
+
currentTest = null
|
|
74
|
+
})
|
|
75
75
|
|
|
76
76
|
event.dispatcher.on(event.test.failed, (test) => {
|
|
77
|
-
currentTest = null
|
|
78
|
-
})
|
|
77
|
+
currentTest = null
|
|
78
|
+
})
|
|
79
79
|
|
|
80
80
|
event.dispatcher.on(event.step.before, (step) => {
|
|
81
|
-
if (typeof timeout !== 'number') return
|
|
81
|
+
if (typeof timeout !== 'number') return
|
|
82
82
|
|
|
83
83
|
if (timeout < 0) {
|
|
84
|
-
step.setTimeout(0.01, TIMEOUT_ORDER.testOrSuite)
|
|
84
|
+
step.setTimeout(0.01, TIMEOUT_ORDER.testOrSuite)
|
|
85
85
|
} else {
|
|
86
|
-
step.setTimeout(timeout, TIMEOUT_ORDER.testOrSuite)
|
|
86
|
+
step.setTimeout(timeout, TIMEOUT_ORDER.testOrSuite)
|
|
87
87
|
}
|
|
88
|
-
})
|
|
88
|
+
})
|
|
89
89
|
|
|
90
90
|
event.dispatcher.on(event.step.finished, (step) => {
|
|
91
|
-
if (typeof timeout === 'number' && !Number.isNaN(timeout)) timeout -= step.duration
|
|
91
|
+
if (typeof timeout === 'number' && !Number.isNaN(timeout)) timeout -= step.duration
|
|
92
92
|
|
|
93
93
|
if (typeof timeout === 'number' && timeout <= 0 && recorder.isRunning()) {
|
|
94
94
|
if (currentTest && currentTest.callback) {
|
|
95
|
-
recorder.reset()
|
|
95
|
+
recorder.reset()
|
|
96
96
|
// replace mocha timeout with custom timeout
|
|
97
|
-
currentTest.timeout(0)
|
|
98
|
-
currentTest.callback(new Error(`Timeout ${currentTimeout}s exceeded (with Before hook)`))
|
|
99
|
-
currentTest.timedOut = true
|
|
97
|
+
currentTest.timeout(0)
|
|
98
|
+
currentTest.callback(new Error(`Timeout ${currentTimeout}s exceeded (with Before hook)`))
|
|
99
|
+
currentTest.timedOut = true
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
|
-
})
|
|
103
|
-
}
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
104
|
|
|
105
105
|
function checkForSeconds(timeout) {
|
|
106
106
|
if (timeout >= 1000) {
|
|
107
|
-
console.log(`Warning: Timeout was set to ${timeout}secs.\nGlobal timeout should be specified in seconds.`)
|
|
107
|
+
console.log(`Warning: Timeout was set to ${timeout}secs.\nGlobal timeout should be specified in seconds.`)
|
|
108
108
|
}
|
|
109
109
|
}
|