codeceptjs 3.7.0-beta.1 → 3.7.0-beta.11
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/README.md +9 -10
- package/bin/codecept.js +7 -0
- package/lib/actor.js +46 -92
- package/lib/ai.js +130 -121
- package/lib/codecept.js +2 -2
- package/lib/command/check.js +186 -0
- package/lib/command/definitions.js +3 -1
- package/lib/command/interactive.js +1 -1
- package/lib/command/run-workers.js +2 -54
- package/lib/command/workers/runTests.js +64 -225
- package/lib/container.js +32 -0
- package/lib/effects.js +218 -0
- package/lib/els.js +87 -106
- package/lib/event.js +18 -17
- package/lib/heal.js +10 -0
- package/lib/helper/AI.js +2 -1
- package/lib/helper/Appium.js +31 -22
- package/lib/helper/Playwright.js +22 -1
- package/lib/helper/Puppeteer.js +5 -0
- package/lib/helper/WebDriver.js +29 -8
- package/lib/listener/emptyRun.js +2 -5
- package/lib/listener/exit.js +5 -8
- package/lib/listener/globalTimeout.js +66 -10
- package/lib/listener/result.js +12 -0
- package/lib/listener/steps.js +3 -6
- package/lib/listener/store.js +9 -1
- package/lib/mocha/asyncWrapper.js +15 -3
- package/lib/mocha/cli.js +79 -28
- package/lib/mocha/featureConfig.js +13 -0
- package/lib/mocha/hooks.js +32 -3
- package/lib/mocha/inject.js +5 -0
- package/lib/mocha/scenarioConfig.js +11 -0
- package/lib/mocha/suite.js +27 -1
- package/lib/mocha/test.js +102 -3
- package/lib/mocha/types.d.ts +11 -0
- package/lib/output.js +75 -73
- package/lib/pause.js +3 -10
- package/lib/plugin/analyze.js +349 -0
- package/lib/plugin/autoDelay.js +2 -2
- package/lib/plugin/commentStep.js +5 -0
- package/lib/plugin/customReporter.js +52 -0
- package/lib/plugin/heal.js +30 -0
- package/lib/plugin/pageInfo.js +140 -0
- package/lib/plugin/retryTo.js +18 -118
- package/lib/plugin/screenshotOnFail.js +12 -17
- package/lib/plugin/standardActingHelpers.js +4 -1
- package/lib/plugin/stepByStepReport.js +6 -5
- package/lib/plugin/stepTimeout.js +1 -1
- package/lib/plugin/tryTo.js +17 -107
- package/lib/recorder.js +5 -5
- package/lib/rerun.js +43 -42
- package/lib/result.js +161 -0
- package/lib/step/base.js +228 -0
- package/lib/step/config.js +50 -0
- package/lib/step/func.js +46 -0
- package/lib/step/helper.js +50 -0
- package/lib/step/meta.js +99 -0
- package/lib/step/record.js +74 -0
- package/lib/step/retry.js +11 -0
- package/lib/step/section.js +55 -0
- package/lib/step.js +20 -347
- package/lib/steps.js +50 -0
- package/lib/store.js +4 -0
- package/lib/timeout.js +66 -0
- package/lib/utils.js +93 -0
- package/lib/within.js +2 -2
- package/lib/workers.js +29 -49
- package/package.json +23 -20
- package/typings/index.d.ts +5 -4
- package/typings/promiseBasedTypes.d.ts +507 -49
- package/typings/types.d.ts +623 -73
- package/lib/listener/artifacts.js +0 -19
- package/lib/plugin/debugErrors.js +0 -67
package/lib/plugin/retryTo.js
CHANGED
|
@@ -1,123 +1,23 @@
|
|
|
1
|
-
const
|
|
2
|
-
const { debug } = require('../output')
|
|
1
|
+
const { retryTo } = require('../effects')
|
|
3
2
|
|
|
4
|
-
const defaultConfig = {
|
|
5
|
-
registerGlobal: true,
|
|
6
|
-
pollInterval: 200,
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* Adds global `retryTo` which retries steps a few times before failing.
|
|
13
|
-
*
|
|
14
|
-
* Enable this plugin in `codecept.conf.js` (enabled by default for new setups):
|
|
15
|
-
*
|
|
16
|
-
* ```js
|
|
17
|
-
* plugins: {
|
|
18
|
-
* retryTo: {
|
|
19
|
-
* enabled: true
|
|
20
|
-
* }
|
|
21
|
-
* }
|
|
22
|
-
* ```
|
|
23
|
-
*
|
|
24
|
-
* Use it in your tests:
|
|
25
|
-
*
|
|
26
|
-
* ```js
|
|
27
|
-
* // retry these steps 5 times before failing
|
|
28
|
-
* await retryTo((tryNum) => {
|
|
29
|
-
* I.switchTo('#editor frame');
|
|
30
|
-
* I.click('Open');
|
|
31
|
-
* I.see('Opened')
|
|
32
|
-
* }, 5);
|
|
33
|
-
* ```
|
|
34
|
-
* Set polling interval as 3rd argument (200ms by default):
|
|
35
|
-
*
|
|
36
|
-
* ```js
|
|
37
|
-
* // retry these steps 5 times before failing
|
|
38
|
-
* await retryTo((tryNum) => {
|
|
39
|
-
* I.switchTo('#editor frame');
|
|
40
|
-
* I.click('Open');
|
|
41
|
-
* I.see('Opened')
|
|
42
|
-
* }, 5, 100);
|
|
43
|
-
* ```
|
|
44
|
-
*
|
|
45
|
-
* Default polling interval can be changed in a config:
|
|
46
|
-
*
|
|
47
|
-
* ```js
|
|
48
|
-
* plugins: {
|
|
49
|
-
* retryTo: {
|
|
50
|
-
* enabled: true,
|
|
51
|
-
* pollInterval: 500,
|
|
52
|
-
* }
|
|
53
|
-
* }
|
|
54
|
-
* ```
|
|
55
|
-
*
|
|
56
|
-
* Disables retryFailedStep plugin for steps inside a block;
|
|
57
|
-
*
|
|
58
|
-
* Use this plugin if:
|
|
59
|
-
*
|
|
60
|
-
* * you need repeat a set of actions in flaky tests
|
|
61
|
-
* * iframe was not rendered and you need to retry switching to it
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* #### Configuration
|
|
65
|
-
*
|
|
66
|
-
* * `pollInterval` - default interval between retries in ms. 200 by default.
|
|
67
|
-
* * `registerGlobal` - to register `retryTo` function globally, true by default
|
|
68
|
-
*
|
|
69
|
-
* If `registerGlobal` is false you can use retryTo from the plugin:
|
|
70
|
-
*
|
|
71
|
-
* ```js
|
|
72
|
-
* const retryTo = codeceptjs.container.plugins('retryTo');
|
|
73
|
-
* ```
|
|
74
|
-
*
|
|
75
|
-
*/
|
|
76
3
|
module.exports = function (config) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Call done if no errors
|
|
97
|
-
recorder.add(() => {
|
|
98
|
-
recorder.session.restore(`retryTo ${tries}`)
|
|
99
|
-
done(null)
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
// Catch errors and retry
|
|
103
|
-
recorder.session.catch(err => {
|
|
104
|
-
recorder.session.restore(`retryTo ${tries}`)
|
|
105
|
-
if (tries <= maxTries) {
|
|
106
|
-
debug(`Error ${err}... Retrying`)
|
|
107
|
-
recorder.add(`retryTo ${tries}`, () => setTimeout(tryBlock, pollInterval))
|
|
108
|
-
} else {
|
|
109
|
-
// if maxTries reached
|
|
110
|
-
handleRetryException(err)
|
|
111
|
-
}
|
|
112
|
-
})
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
recorder.add('retryTo', tryBlock).catch(err => {
|
|
116
|
-
console.error('An error occurred:', err)
|
|
117
|
-
done(null)
|
|
118
|
-
})
|
|
119
|
-
})
|
|
120
|
-
}
|
|
4
|
+
console.log(`
|
|
5
|
+
Deprecation Warning: 'retryTo' has been moved to the effects module.
|
|
6
|
+
You should update your tests to use it as follows:
|
|
7
|
+
|
|
8
|
+
\`\`\`javascript
|
|
9
|
+
const { retryTo } = require('codeceptjs/effects');
|
|
10
|
+
|
|
11
|
+
// Example: Retry these steps 5 times before failing
|
|
12
|
+
await retryTo((tryNum) => {
|
|
13
|
+
I.switchTo('#editor frame');
|
|
14
|
+
I.click('Open');
|
|
15
|
+
I.see('Opened');
|
|
16
|
+
}, 5);
|
|
17
|
+
\`\`\`
|
|
18
|
+
|
|
19
|
+
For more details, refer to the documentation.
|
|
20
|
+
`)
|
|
121
21
|
|
|
122
22
|
if (config.registerGlobal) {
|
|
123
23
|
global.retryTo = retryTo
|
|
@@ -5,8 +5,9 @@ const Container = require('../container')
|
|
|
5
5
|
const recorder = require('../recorder')
|
|
6
6
|
const event = require('../event')
|
|
7
7
|
const output = require('../output')
|
|
8
|
-
const { fileExists
|
|
8
|
+
const { fileExists } = require('../utils')
|
|
9
9
|
const Codeceptjs = require('../index')
|
|
10
|
+
const { testToFileName } = require('../mocha/test')
|
|
10
11
|
|
|
11
12
|
const defaultConfig = {
|
|
12
13
|
uniqueScreenshotNames: false,
|
|
@@ -14,7 +15,7 @@ const defaultConfig = {
|
|
|
14
15
|
fullPageScreenshots: false,
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
const supportedHelpers =
|
|
18
|
+
const supportedHelpers = Container.STANDARD_ACTING_HELPERS
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Creates screenshot on failure. Screenshot is saved into `output` directory.
|
|
@@ -63,7 +64,7 @@ module.exports = function (config) {
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
if (Codeceptjs.container.mocha()) {
|
|
66
|
-
options.reportDir = Codeceptjs.container.mocha()
|
|
67
|
+
options.reportDir = Codeceptjs.container.mocha()?.options?.reporterOptions && Codeceptjs.container.mocha()?.options?.reporterOptions?.reportDir
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
if (options.disableScreenshots) {
|
|
@@ -71,21 +72,19 @@ module.exports = function (config) {
|
|
|
71
72
|
return
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
event.dispatcher.on(event.test.failed, test => {
|
|
75
|
-
if (
|
|
76
|
-
|
|
75
|
+
event.dispatcher.on(event.test.failed, (test, _err, hookName) => {
|
|
76
|
+
if (hookName === 'BeforeSuite' || hookName === 'AfterSuite') {
|
|
77
|
+
// no browser here
|
|
77
78
|
return
|
|
78
79
|
}
|
|
80
|
+
|
|
79
81
|
recorder.add(
|
|
80
82
|
'screenshot of failed test',
|
|
81
83
|
async () => {
|
|
82
|
-
let fileName = clearString(test.title)
|
|
83
84
|
const dataType = 'image/png'
|
|
84
85
|
// This prevents data driven to be included in the failed screenshot file name
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
if (test.ctx && test.ctx.test && test.ctx.test.type === 'hook') fileName = clearString(`${test.title}_${test.ctx.test.title}`)
|
|
86
|
+
let fileName = testToFileName(test)
|
|
87
|
+
|
|
89
88
|
if (options.uniqueScreenshotNames && test) {
|
|
90
89
|
const uuid = _getUUID(test)
|
|
91
90
|
fileName = `${fileName.substring(0, 10)}_${uuid}.failed.png`
|
|
@@ -141,12 +140,8 @@ module.exports = function (config) {
|
|
|
141
140
|
})
|
|
142
141
|
|
|
143
142
|
function _getUUID(test) {
|
|
144
|
-
if (test.
|
|
145
|
-
return test.
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (test.ctx && test.ctx.test.uuid) {
|
|
149
|
-
return test.ctx.test.uuid
|
|
143
|
+
if (test.uid) {
|
|
144
|
+
return test.uid
|
|
150
145
|
}
|
|
151
146
|
|
|
152
147
|
return Math.floor(new Date().getTime() / 1000)
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
const
|
|
1
|
+
const Container = require('../container')
|
|
2
|
+
// due to using this in internal tooling we won't post deprecation warning
|
|
3
|
+
// but please switch to Container.STANDARD_ACTING_HELPERS
|
|
4
|
+
const standardActingHelpers = Container.STANDARD_ACTING_HELPERS
|
|
2
5
|
|
|
3
6
|
module.exports = standardActingHelpers
|
|
@@ -12,7 +12,7 @@ const event = require('../event')
|
|
|
12
12
|
const output = require('../output')
|
|
13
13
|
const { template, deleteDir } = require('../utils')
|
|
14
14
|
|
|
15
|
-
const supportedHelpers =
|
|
15
|
+
const supportedHelpers = Container.STANDARD_ACTING_HELPERS
|
|
16
16
|
|
|
17
17
|
const defaultConfig = {
|
|
18
18
|
deleteSuccessful: true,
|
|
@@ -121,12 +121,13 @@ module.exports = function (config) {
|
|
|
121
121
|
deleteDir(dir)
|
|
122
122
|
})
|
|
123
123
|
|
|
124
|
-
event.dispatcher.on(event.test.failed, (test,
|
|
125
|
-
if (
|
|
126
|
-
|
|
124
|
+
event.dispatcher.on(event.test.failed, (test, _err, hookName) => {
|
|
125
|
+
if (hookName === 'BeforeSuite' || hookName === 'AfterSuite') {
|
|
126
|
+
// no browser here
|
|
127
127
|
return
|
|
128
128
|
}
|
|
129
|
-
|
|
129
|
+
|
|
130
|
+
persist(test)
|
|
130
131
|
})
|
|
131
132
|
|
|
132
133
|
event.dispatcher.on(event.all.result, () => {
|
package/lib/plugin/tryTo.js
CHANGED
|
@@ -1,115 +1,25 @@
|
|
|
1
|
-
const
|
|
2
|
-
const { debug } = require('../output')
|
|
1
|
+
const { tryTo } = require('../effects')
|
|
3
2
|
|
|
4
|
-
const defaultConfig = {
|
|
5
|
-
registerGlobal: true,
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* Adds global `tryTo` function in which all failed steps won't fail a test but will return true/false.
|
|
12
|
-
*
|
|
13
|
-
* Enable this plugin in `codecept.conf.js` (enabled by default for new setups):
|
|
14
|
-
*
|
|
15
|
-
* ```js
|
|
16
|
-
* plugins: {
|
|
17
|
-
* tryTo: {
|
|
18
|
-
* enabled: true
|
|
19
|
-
* }
|
|
20
|
-
* }
|
|
21
|
-
* ```
|
|
22
|
-
* Use it in your tests:
|
|
23
|
-
*
|
|
24
|
-
* ```js
|
|
25
|
-
* const result = await tryTo(() => I.see('Welcome'));
|
|
26
|
-
*
|
|
27
|
-
* // if text "Welcome" is on page, result => true
|
|
28
|
-
* // if text "Welcome" is not on page, result => false
|
|
29
|
-
* ```
|
|
30
|
-
*
|
|
31
|
-
* Disables retryFailedStep plugin for steps inside a block;
|
|
32
|
-
*
|
|
33
|
-
* Use this plugin if:
|
|
34
|
-
*
|
|
35
|
-
* * you need to perform multiple assertions inside a test
|
|
36
|
-
* * there is A/B testing on a website you test
|
|
37
|
-
* * there is "Accept Cookie" banner which may surprisingly appear on a page.
|
|
38
|
-
*
|
|
39
|
-
* #### Usage
|
|
40
|
-
*
|
|
41
|
-
* #### Multiple Conditional Assertions
|
|
42
|
-
*
|
|
43
|
-
* ```js
|
|
44
|
-
*
|
|
45
|
-
* Add assert requires first:
|
|
46
|
-
* ```js
|
|
47
|
-
* const assert = require('assert');
|
|
48
|
-
* ```
|
|
49
|
-
* Then use the assertion:
|
|
50
|
-
* const result1 = await tryTo(() => I.see('Hello, user'));
|
|
51
|
-
* const result2 = await tryTo(() => I.seeElement('.welcome'));
|
|
52
|
-
* assert.ok(result1 && result2, 'Assertions were not succesful');
|
|
53
|
-
* ```
|
|
54
|
-
*
|
|
55
|
-
* ##### Optional click
|
|
56
|
-
*
|
|
57
|
-
* ```js
|
|
58
|
-
* I.amOnPage('/');
|
|
59
|
-
* tryTo(() => I.click('Agree', '.cookies'));
|
|
60
|
-
* ```
|
|
61
|
-
*
|
|
62
|
-
* #### Configuration
|
|
63
|
-
*
|
|
64
|
-
* * `registerGlobal` - to register `tryTo` function globally, true by default
|
|
65
|
-
*
|
|
66
|
-
* If `registerGlobal` is false you can use tryTo from the plugin:
|
|
67
|
-
*
|
|
68
|
-
* ```js
|
|
69
|
-
* const tryTo = codeceptjs.container.plugins('tryTo');
|
|
70
|
-
* ```
|
|
71
|
-
*
|
|
72
|
-
*/
|
|
73
3
|
module.exports = function (config) {
|
|
74
|
-
|
|
4
|
+
console.log(`
|
|
5
|
+
Deprecated Warning: 'tryTo' has been moved to the effects module.
|
|
6
|
+
You should update your tests to use it as follows:
|
|
7
|
+
|
|
8
|
+
\`\`\`javascript
|
|
9
|
+
const { tryTo } = require('codeceptjs/effects');
|
|
10
|
+
|
|
11
|
+
// Example: failed step won't fail a test but will return true/false
|
|
12
|
+
await tryTo(() => {
|
|
13
|
+
I.switchTo('#editor frame');
|
|
14
|
+
});
|
|
15
|
+
\`\`\`
|
|
16
|
+
|
|
17
|
+
For more details, refer to the documentation.
|
|
18
|
+
`)
|
|
75
19
|
|
|
76
20
|
if (config.registerGlobal) {
|
|
77
21
|
global.tryTo = tryTo
|
|
78
22
|
}
|
|
79
|
-
return tryTo
|
|
80
|
-
}
|
|
81
23
|
|
|
82
|
-
|
|
83
|
-
let result = false
|
|
84
|
-
return recorder.add(
|
|
85
|
-
'tryTo',
|
|
86
|
-
() => {
|
|
87
|
-
recorder.session.start('tryTo')
|
|
88
|
-
process.env.TRY_TO = 'true'
|
|
89
|
-
callback()
|
|
90
|
-
recorder.add(() => {
|
|
91
|
-
result = true
|
|
92
|
-
recorder.session.restore('tryTo')
|
|
93
|
-
return result
|
|
94
|
-
})
|
|
95
|
-
recorder.session.catch(err => {
|
|
96
|
-
result = false
|
|
97
|
-
const msg = err.inspect ? err.inspect() : err.toString()
|
|
98
|
-
debug(`Unsuccessful try > ${msg}`)
|
|
99
|
-
recorder.session.restore('tryTo')
|
|
100
|
-
return result
|
|
101
|
-
})
|
|
102
|
-
return recorder.add(
|
|
103
|
-
'result',
|
|
104
|
-
() => {
|
|
105
|
-
process.env.TRY_TO = undefined
|
|
106
|
-
return result
|
|
107
|
-
},
|
|
108
|
-
true,
|
|
109
|
-
false,
|
|
110
|
-
)
|
|
111
|
-
},
|
|
112
|
-
false,
|
|
113
|
-
false,
|
|
114
|
-
)
|
|
24
|
+
return tryTo
|
|
115
25
|
}
|
package/lib/recorder.js
CHANGED
|
@@ -3,7 +3,7 @@ const promiseRetry = require('promise-retry')
|
|
|
3
3
|
const chalk = require('chalk')
|
|
4
4
|
const { printObjectProperties } = require('./utils')
|
|
5
5
|
const { log } = require('./output')
|
|
6
|
-
|
|
6
|
+
const { TimeoutError } = require('./timeout')
|
|
7
7
|
const MAX_TASKS = 100
|
|
8
8
|
|
|
9
9
|
let promise
|
|
@@ -179,7 +179,7 @@ module.exports = {
|
|
|
179
179
|
}
|
|
180
180
|
if (retry === undefined) retry = true
|
|
181
181
|
if (!running && !force) {
|
|
182
|
-
return
|
|
182
|
+
return Promise.resolve()
|
|
183
183
|
}
|
|
184
184
|
tasks.push(taskName)
|
|
185
185
|
debug(chalk.gray(`${currentQueue()} Queued | ${taskName}`))
|
|
@@ -191,13 +191,13 @@ module.exports = {
|
|
|
191
191
|
.slice(-1)
|
|
192
192
|
.pop()
|
|
193
193
|
// no retries or unnamed tasks
|
|
194
|
+
debug(`${currentQueue()} Running | ${taskName} | Timeout: ${timeout || 'None'}`)
|
|
195
|
+
|
|
194
196
|
if (!retryOpts || !taskName || !retry) {
|
|
195
197
|
const [promise, timer] = getTimeoutPromise(timeout, taskName)
|
|
196
198
|
return Promise.race([promise, Promise.resolve(res).then(fn)]).finally(() => clearTimeout(timer))
|
|
197
199
|
}
|
|
198
200
|
|
|
199
|
-
debug(`${currentQueue()} Running | ${taskName}`)
|
|
200
|
-
|
|
201
201
|
const retryRules = this.retries.slice().reverse()
|
|
202
202
|
return promiseRetry(Object.assign(defaultRetryOptions, retryOpts), (retry, number) => {
|
|
203
203
|
if (number > 1) log(`${currentQueue()}Retrying... Attempt #${number}`)
|
|
@@ -386,7 +386,7 @@ function getTimeoutPromise(timeoutMs, taskName) {
|
|
|
386
386
|
return [
|
|
387
387
|
new Promise((done, reject) => {
|
|
388
388
|
timer = setTimeout(() => {
|
|
389
|
-
reject(new
|
|
389
|
+
reject(new TimeoutError(`Action ${taskName} was interrupted on timeout ${timeoutMs}ms`))
|
|
390
390
|
}, timeoutMs || 2e9)
|
|
391
391
|
}),
|
|
392
392
|
timer,
|
package/lib/rerun.js
CHANGED
|
@@ -1,81 +1,82 @@
|
|
|
1
|
-
const fsPath = require('path')
|
|
2
|
-
const container = require('./container')
|
|
3
|
-
const event = require('./event')
|
|
4
|
-
const BaseCodecept = require('./codecept')
|
|
5
|
-
const output = require('./output')
|
|
1
|
+
const fsPath = require('path')
|
|
2
|
+
const container = require('./container')
|
|
3
|
+
const event = require('./event')
|
|
4
|
+
const BaseCodecept = require('./codecept')
|
|
5
|
+
const output = require('./output')
|
|
6
6
|
|
|
7
7
|
class CodeceptRerunner extends BaseCodecept {
|
|
8
8
|
runOnce(test) {
|
|
9
9
|
return new Promise((resolve, reject) => {
|
|
10
10
|
// @ts-ignore
|
|
11
|
-
container.createMocha()
|
|
12
|
-
const mocha = container.mocha()
|
|
13
|
-
this.testFiles.forEach(
|
|
14
|
-
delete require.cache[file]
|
|
15
|
-
})
|
|
16
|
-
mocha.files = this.testFiles
|
|
11
|
+
container.createMocha()
|
|
12
|
+
const mocha = container.mocha()
|
|
13
|
+
this.testFiles.forEach(file => {
|
|
14
|
+
delete require.cache[file]
|
|
15
|
+
})
|
|
16
|
+
mocha.files = this.testFiles
|
|
17
17
|
if (test) {
|
|
18
18
|
if (!fsPath.isAbsolute(test)) {
|
|
19
|
-
test = fsPath.join(global.codecept_dir, test)
|
|
19
|
+
test = fsPath.join(global.codecept_dir, test)
|
|
20
20
|
}
|
|
21
|
-
mocha.files = mocha.files.filter(t => fsPath.basename(t, '.js') === test || t === test)
|
|
21
|
+
mocha.files = mocha.files.filter(t => fsPath.basename(t, '.js') === test || t === test)
|
|
22
22
|
}
|
|
23
23
|
try {
|
|
24
|
-
mocha.run(
|
|
24
|
+
mocha.run(failures => {
|
|
25
25
|
if (failures === 0) {
|
|
26
|
-
resolve()
|
|
26
|
+
resolve()
|
|
27
27
|
} else {
|
|
28
|
-
reject(new Error(`${failures} tests fail`))
|
|
28
|
+
reject(new Error(`${failures} tests fail`))
|
|
29
29
|
}
|
|
30
|
-
})
|
|
30
|
+
})
|
|
31
31
|
} catch (e) {
|
|
32
|
-
reject(e)
|
|
32
|
+
reject(e)
|
|
33
33
|
}
|
|
34
|
-
})
|
|
34
|
+
})
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
async runTests(test) {
|
|
38
|
-
const configRerun = this.config.rerun || {}
|
|
39
|
-
const minSuccess = configRerun.minSuccess || 1
|
|
40
|
-
const maxReruns = configRerun.maxReruns || 1
|
|
38
|
+
const configRerun = this.config.rerun || {}
|
|
39
|
+
const minSuccess = configRerun.minSuccess || 1
|
|
40
|
+
const maxReruns = configRerun.maxReruns || 1
|
|
41
41
|
if (minSuccess > maxReruns) {
|
|
42
|
-
process.exitCode = 1
|
|
43
|
-
throw new Error(`run-rerun Configuration Error: minSuccess must be less than maxReruns. Current values: minSuccess=${minSuccess} maxReruns=${maxReruns}`)
|
|
42
|
+
process.exitCode = 1
|
|
43
|
+
throw new Error(`run-rerun Configuration Error: minSuccess must be less than maxReruns. Current values: minSuccess=${minSuccess} maxReruns=${maxReruns}`)
|
|
44
44
|
}
|
|
45
45
|
if (maxReruns === 1) {
|
|
46
|
-
await this.runOnce(test)
|
|
47
|
-
return
|
|
46
|
+
await this.runOnce(test)
|
|
47
|
+
return
|
|
48
48
|
}
|
|
49
|
-
let successCounter = 0
|
|
50
|
-
let rerunsCounter = 0
|
|
49
|
+
let successCounter = 0
|
|
50
|
+
let rerunsCounter = 0
|
|
51
51
|
while (rerunsCounter < maxReruns && successCounter < minSuccess) {
|
|
52
|
-
|
|
52
|
+
container.result().reset() // reset result
|
|
53
|
+
rerunsCounter++
|
|
53
54
|
try {
|
|
54
|
-
await this.runOnce(test)
|
|
55
|
-
successCounter
|
|
56
|
-
output.success(`\nProcess run ${rerunsCounter} of max ${maxReruns}, success runs ${successCounter}/${minSuccess}\n`)
|
|
55
|
+
await this.runOnce(test)
|
|
56
|
+
successCounter++
|
|
57
|
+
output.success(`\nProcess run ${rerunsCounter} of max ${maxReruns}, success runs ${successCounter}/${minSuccess}\n`)
|
|
57
58
|
} catch (e) {
|
|
58
|
-
output.error(`\nFail run ${rerunsCounter} of max ${maxReruns}, success runs ${successCounter}/${minSuccess} \n`)
|
|
59
|
-
console.error(e)
|
|
59
|
+
output.error(`\nFail run ${rerunsCounter} of max ${maxReruns}, success runs ${successCounter}/${minSuccess} \n`)
|
|
60
|
+
console.error(e)
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
if (successCounter < minSuccess) {
|
|
63
|
-
throw new Error(`Flaky tests detected! ${successCounter} success runs achieved instead of ${minSuccess} success runs expected`)
|
|
64
|
+
throw new Error(`Flaky tests detected! ${successCounter} success runs achieved instead of ${minSuccess} success runs expected`)
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
async run(test) {
|
|
68
|
-
event.emit(event.all.before, this)
|
|
69
|
+
event.emit(event.all.before, this)
|
|
69
70
|
try {
|
|
70
|
-
await this.runTests(test)
|
|
71
|
+
await this.runTests(test)
|
|
71
72
|
} catch (e) {
|
|
72
|
-
output.error(e.stack)
|
|
73
|
-
throw e
|
|
73
|
+
output.error(e.stack)
|
|
74
|
+
throw e
|
|
74
75
|
} finally {
|
|
75
|
-
event.emit(event.all.result, this)
|
|
76
|
-
event.emit(event.all.after, this)
|
|
76
|
+
event.emit(event.all.result, this)
|
|
77
|
+
event.emit(event.all.after, this)
|
|
77
78
|
}
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
module.exports = CodeceptRerunner
|
|
82
|
+
module.exports = CodeceptRerunner
|