codeceptjs 3.7.0-beta.7 → 3.7.0-beta.8
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/lib/actor.js +1 -2
- package/lib/ai.js +130 -121
- package/lib/codecept.js +4 -4
- package/lib/command/check.js +4 -0
- package/lib/command/run-workers.js +1 -53
- package/lib/command/workers/runTests.js +25 -189
- package/lib/container.js +16 -0
- package/lib/event.js +18 -17
- package/lib/listener/exit.js +5 -8
- package/lib/listener/globalTimeout.js +26 -9
- package/lib/listener/result.js +12 -0
- package/lib/listener/steps.js +0 -6
- package/lib/mocha/asyncWrapper.js +12 -2
- package/lib/mocha/cli.js +50 -24
- package/lib/mocha/hooks.js +32 -3
- package/lib/mocha/suite.js +27 -1
- package/lib/mocha/test.js +91 -7
- package/lib/mocha/types.d.ts +5 -0
- package/lib/output.js +1 -0
- package/lib/plugin/analyze.js +351 -0
- package/lib/plugin/commentStep.js +5 -0
- package/lib/plugin/customReporter.js +52 -0
- package/lib/plugin/heal.js +2 -2
- package/lib/plugin/pageInfo.js +143 -0
- package/lib/plugin/retryTo.js +10 -2
- package/lib/plugin/screenshotOnFail.js +4 -6
- package/lib/plugin/stepTimeout.js +1 -1
- package/lib/plugin/tryTo.js +9 -1
- package/lib/recorder.js +4 -4
- package/lib/rerun.js +43 -42
- package/lib/result.js +161 -0
- package/lib/step/base.js +52 -4
- package/lib/step/helper.js +3 -0
- package/lib/step/meta.js +9 -1
- package/lib/step/record.js +5 -5
- package/lib/step/section.js +55 -0
- package/lib/steps.js +28 -1
- package/lib/{step/timeout.js → timeout.js} +24 -0
- package/lib/utils.js +35 -0
- package/lib/workers.js +28 -38
- package/package.json +2 -2
- package/typings/promiseBasedTypes.d.ts +12 -518
- package/typings/types.d.ts +75 -518
- package/lib/listener/artifacts.js +0 -19
- package/lib/plugin/debugErrors.js +0 -67
|
@@ -75,217 +75,53 @@ function filterTests() {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
function initializeListeners() {
|
|
78
|
-
function simplifyError(error) {
|
|
79
|
-
if (error) {
|
|
80
|
-
const { stack, uncaught, message, actual, expected } = error
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
stack,
|
|
84
|
-
uncaught,
|
|
85
|
-
message,
|
|
86
|
-
actual,
|
|
87
|
-
expected,
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return null
|
|
92
|
-
}
|
|
93
|
-
function simplifyTest(test, err = null) {
|
|
94
|
-
test = { ...test }
|
|
95
|
-
|
|
96
|
-
if (test.start && !test.duration) {
|
|
97
|
-
const end = new Date()
|
|
98
|
-
test.duration = end - test.start
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (test.err) {
|
|
102
|
-
err = simplifyError(test.err)
|
|
103
|
-
test.status = 'failed'
|
|
104
|
-
} else if (err) {
|
|
105
|
-
err = simplifyError(err)
|
|
106
|
-
test.status = 'failed'
|
|
107
|
-
}
|
|
108
|
-
const parent = {}
|
|
109
|
-
if (test.parent) {
|
|
110
|
-
parent.title = test.parent.title
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (test.opts) {
|
|
114
|
-
Object.keys(test.opts).forEach(k => {
|
|
115
|
-
if (typeof test.opts[k] === 'object') delete test.opts[k]
|
|
116
|
-
if (typeof test.opts[k] === 'function') delete test.opts[k]
|
|
117
|
-
})
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return {
|
|
121
|
-
opts: test.opts || {},
|
|
122
|
-
tags: test.tags || [],
|
|
123
|
-
uid: test.uid,
|
|
124
|
-
workerIndex,
|
|
125
|
-
retries: test._retries,
|
|
126
|
-
title: test.title,
|
|
127
|
-
status: test.status,
|
|
128
|
-
notes: test.notes || [],
|
|
129
|
-
meta: test.meta || {},
|
|
130
|
-
artifacts: test.artifacts || [],
|
|
131
|
-
duration: test.duration || 0,
|
|
132
|
-
err,
|
|
133
|
-
parent,
|
|
134
|
-
steps: test.steps && test.steps.length > 0 ? simplifyStepsInTestObject(test.steps, err) : [],
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function simplifyStepsInTestObject(steps, err) {
|
|
139
|
-
steps = [...steps]
|
|
140
|
-
const _steps = []
|
|
141
|
-
|
|
142
|
-
for (step of steps) {
|
|
143
|
-
const _args = []
|
|
144
|
-
|
|
145
|
-
if (step.args) {
|
|
146
|
-
for (const arg of step.args) {
|
|
147
|
-
// check if arg is a JOI object
|
|
148
|
-
if (arg && arg.$_root) {
|
|
149
|
-
_args.push(JSON.stringify(arg).slice(0, 300))
|
|
150
|
-
// check if arg is a function
|
|
151
|
-
} else if (arg && typeof arg === 'function') {
|
|
152
|
-
_args.push(arg.name)
|
|
153
|
-
} else {
|
|
154
|
-
_args.push(arg)
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
_steps.push({
|
|
160
|
-
actor: step.actor,
|
|
161
|
-
name: step.name,
|
|
162
|
-
status: step.status,
|
|
163
|
-
args: JSON.stringify(_args),
|
|
164
|
-
startedAt: step.startedAt,
|
|
165
|
-
startTime: step.startTime,
|
|
166
|
-
endTime: step.endTime,
|
|
167
|
-
finishedAt: step.finishedAt,
|
|
168
|
-
duration: step.duration,
|
|
169
|
-
err,
|
|
170
|
-
})
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return _steps
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function simplifyStep(step, err = null) {
|
|
177
|
-
step = { ...step }
|
|
178
|
-
|
|
179
|
-
if (step.startTime && !step.duration) {
|
|
180
|
-
const end = new Date()
|
|
181
|
-
step.duration = end - step.startTime
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (step.err) {
|
|
185
|
-
err = simplifyError(step.err)
|
|
186
|
-
step.status = 'failed'
|
|
187
|
-
} else if (err) {
|
|
188
|
-
err = simplifyError(err)
|
|
189
|
-
step.status = 'failed'
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const parent = {}
|
|
193
|
-
if (step.metaStep) {
|
|
194
|
-
parent.title = step.metaStep.actor
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (step.opts) {
|
|
198
|
-
Object.keys(step.opts).forEach(k => {
|
|
199
|
-
if (typeof step.opts[k] === 'object') delete step.opts[k]
|
|
200
|
-
if (typeof step.opts[k] === 'function') delete step.opts[k]
|
|
201
|
-
})
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return {
|
|
205
|
-
opts: step.opts || {},
|
|
206
|
-
workerIndex,
|
|
207
|
-
title: step.name,
|
|
208
|
-
status: step.status,
|
|
209
|
-
duration: step.duration || 0,
|
|
210
|
-
err,
|
|
211
|
-
parent,
|
|
212
|
-
test: simplifyTest(step.test),
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
collectStats()
|
|
217
78
|
// suite
|
|
218
|
-
event.dispatcher.on(event.suite.before, suite => sendToParentThread({ event: event.suite.before, workerIndex, data:
|
|
219
|
-
event.dispatcher.on(event.suite.after, suite => sendToParentThread({ event: event.suite.after, workerIndex, data:
|
|
79
|
+
event.dispatcher.on(event.suite.before, suite => sendToParentThread({ event: event.suite.before, workerIndex, data: suite.simplify() }))
|
|
80
|
+
event.dispatcher.on(event.suite.after, suite => sendToParentThread({ event: event.suite.after, workerIndex, data: suite.simplify() }))
|
|
220
81
|
|
|
221
82
|
// calculate duration
|
|
222
83
|
event.dispatcher.on(event.test.started, test => (test.start = new Date()))
|
|
223
84
|
|
|
224
85
|
// tests
|
|
225
|
-
event.dispatcher.on(event.test.before, test => sendToParentThread({ event: event.test.before, workerIndex, data:
|
|
226
|
-
event.dispatcher.on(event.test.after, test => sendToParentThread({ event: event.test.after, workerIndex, data:
|
|
86
|
+
event.dispatcher.on(event.test.before, test => sendToParentThread({ event: event.test.before, workerIndex, data: test.simplify() }))
|
|
87
|
+
event.dispatcher.on(event.test.after, test => sendToParentThread({ event: event.test.after, workerIndex, data: test.simplify() }))
|
|
227
88
|
// we should force-send correct errors to prevent race condition
|
|
228
|
-
event.dispatcher.on(event.test.finished, (test, err) => sendToParentThread({ event: event.test.finished, workerIndex, data:
|
|
229
|
-
event.dispatcher.on(event.test.failed, (test, err) => sendToParentThread({ event: event.test.failed, workerIndex, data:
|
|
230
|
-
event.dispatcher.on(event.test.passed, (test, err) => sendToParentThread({ event: event.test.passed, workerIndex, data:
|
|
231
|
-
event.dispatcher.on(event.test.started, test => sendToParentThread({ event: event.test.started, workerIndex, data:
|
|
232
|
-
event.dispatcher.on(event.test.skipped, test => sendToParentThread({ event: event.test.skipped, workerIndex, data:
|
|
89
|
+
event.dispatcher.on(event.test.finished, (test, err) => sendToParentThread({ event: event.test.finished, workerIndex, data: { ...test.simplify(), err } }))
|
|
90
|
+
event.dispatcher.on(event.test.failed, (test, err) => sendToParentThread({ event: event.test.failed, workerIndex, data: { ...test.simplify(), err } }))
|
|
91
|
+
event.dispatcher.on(event.test.passed, (test, err) => sendToParentThread({ event: event.test.passed, workerIndex, data: { ...test.simplify(), err } }))
|
|
92
|
+
event.dispatcher.on(event.test.started, test => sendToParentThread({ event: event.test.started, workerIndex, data: test.simplify() }))
|
|
93
|
+
event.dispatcher.on(event.test.skipped, test => sendToParentThread({ event: event.test.skipped, workerIndex, data: test.simplify() }))
|
|
233
94
|
|
|
234
95
|
// steps
|
|
235
|
-
event.dispatcher.on(event.step.finished, step => sendToParentThread({ event: event.step.finished, workerIndex, data:
|
|
236
|
-
event.dispatcher.on(event.step.started, step => sendToParentThread({ event: event.step.started, workerIndex, data:
|
|
237
|
-
event.dispatcher.on(event.step.passed, step => sendToParentThread({ event: event.step.passed, workerIndex, data:
|
|
238
|
-
event.dispatcher.on(event.step.failed, step => sendToParentThread({ event: event.step.failed, workerIndex, data:
|
|
96
|
+
event.dispatcher.on(event.step.finished, step => sendToParentThread({ event: event.step.finished, workerIndex, data: step.simplify() }))
|
|
97
|
+
event.dispatcher.on(event.step.started, step => sendToParentThread({ event: event.step.started, workerIndex, data: step.simplify() }))
|
|
98
|
+
event.dispatcher.on(event.step.passed, step => sendToParentThread({ event: event.step.passed, workerIndex, data: step.simplify() }))
|
|
99
|
+
event.dispatcher.on(event.step.failed, step => sendToParentThread({ event: event.step.failed, workerIndex, data: step.simplify() }))
|
|
239
100
|
|
|
240
|
-
event.dispatcher.on(event.hook.failed, (
|
|
241
|
-
event.dispatcher.on(event.hook.passed,
|
|
242
|
-
event.dispatcher.on(event.
|
|
101
|
+
event.dispatcher.on(event.hook.failed, (hook, err) => sendToParentThread({ event: event.hook.failed, workerIndex, data: { ...hook.simplify(), err } }))
|
|
102
|
+
event.dispatcher.on(event.hook.passed, hook => sendToParentThread({ event: event.hook.passed, workerIndex, data: hook.simplify() }))
|
|
103
|
+
event.dispatcher.on(event.hook.finished, hook => sendToParentThread({ event: event.hook.finished, workerIndex, data: hook.simplify() }))
|
|
243
104
|
|
|
105
|
+
event.dispatcher.once(event.all.after, () => {
|
|
106
|
+
sendToParentThread({ event: event.all.after, workerIndex, data: container.result().simplify() })
|
|
107
|
+
})
|
|
244
108
|
// all
|
|
245
|
-
event.dispatcher.once(event.all.result, () =>
|
|
109
|
+
event.dispatcher.once(event.all.result, () => {
|
|
110
|
+
sendToParentThread({ event: event.all.result, workerIndex, data: container.result().simplify() })
|
|
111
|
+
parentPort?.close()
|
|
112
|
+
})
|
|
246
113
|
}
|
|
247
114
|
|
|
248
115
|
function disablePause() {
|
|
249
116
|
global.pause = () => {}
|
|
250
117
|
}
|
|
251
118
|
|
|
252
|
-
function collectStats() {
|
|
253
|
-
const stats = {
|
|
254
|
-
passes: 0,
|
|
255
|
-
failures: 0,
|
|
256
|
-
skipped: 0,
|
|
257
|
-
tests: 0,
|
|
258
|
-
pending: 0,
|
|
259
|
-
}
|
|
260
|
-
event.dispatcher.on(event.test.skipped, () => {
|
|
261
|
-
stats.skipped++
|
|
262
|
-
})
|
|
263
|
-
event.dispatcher.on(event.test.passed, () => {
|
|
264
|
-
stats.passes++
|
|
265
|
-
})
|
|
266
|
-
event.dispatcher.on(event.test.failed, test => {
|
|
267
|
-
if (test.ctx._runnable.title.includes('hook: AfterSuite')) {
|
|
268
|
-
stats.failedHooks += 1
|
|
269
|
-
}
|
|
270
|
-
stats.failures++
|
|
271
|
-
})
|
|
272
|
-
event.dispatcher.on(event.test.skipped, () => {
|
|
273
|
-
stats.pending++
|
|
274
|
-
})
|
|
275
|
-
event.dispatcher.on(event.test.finished, () => {
|
|
276
|
-
stats.tests++
|
|
277
|
-
})
|
|
278
|
-
event.dispatcher.once(event.all.after, () => {
|
|
279
|
-
sendToParentThread({ event: event.all.after, data: stats })
|
|
280
|
-
})
|
|
281
|
-
}
|
|
282
|
-
|
|
283
119
|
function sendToParentThread(data) {
|
|
284
|
-
parentPort
|
|
120
|
+
parentPort?.postMessage(data)
|
|
285
121
|
}
|
|
286
122
|
|
|
287
123
|
function listenToParentThread() {
|
|
288
|
-
parentPort
|
|
124
|
+
parentPort?.on('message', eventData => {
|
|
289
125
|
container.append({ support: eventData.data })
|
|
290
126
|
})
|
|
291
127
|
}
|
package/lib/container.js
CHANGED
|
@@ -9,6 +9,7 @@ const recorder = require('./recorder')
|
|
|
9
9
|
const event = require('./event')
|
|
10
10
|
const WorkerStorage = require('./workerStorage')
|
|
11
11
|
const store = require('./store')
|
|
12
|
+
const Result = require('./result')
|
|
12
13
|
const ai = require('./ai')
|
|
13
14
|
|
|
14
15
|
let asyncHelperPromise
|
|
@@ -25,6 +26,8 @@ let container = {
|
|
|
25
26
|
*/
|
|
26
27
|
mocha: {},
|
|
27
28
|
translation: {},
|
|
29
|
+
/** @type {Result | null} */
|
|
30
|
+
result: null,
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
/**
|
|
@@ -54,6 +57,7 @@ class Container {
|
|
|
54
57
|
container.translation = loadTranslation(config.translation || null, config.vocabularies || [])
|
|
55
58
|
container.proxySupport = createSupportObjects(config.include || {})
|
|
56
59
|
container.plugins = createPlugins(config.plugins || {}, opts)
|
|
60
|
+
container.result = new Result()
|
|
57
61
|
|
|
58
62
|
createActor(config.include?.I)
|
|
59
63
|
|
|
@@ -127,6 +131,18 @@ class Container {
|
|
|
127
131
|
return container.mocha
|
|
128
132
|
}
|
|
129
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Get result
|
|
136
|
+
*
|
|
137
|
+
* @returns {Result}
|
|
138
|
+
*/
|
|
139
|
+
static result() {
|
|
140
|
+
if (!container.result) {
|
|
141
|
+
container.result = new Result()
|
|
142
|
+
}
|
|
143
|
+
return container.result
|
|
144
|
+
}
|
|
145
|
+
|
|
130
146
|
/**
|
|
131
147
|
* Append new services to container
|
|
132
148
|
*
|
package/lib/event.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
const debug = require('debug')('codeceptjs:event')
|
|
2
|
-
const events = require('events')
|
|
3
|
-
const { error } = require('./output')
|
|
1
|
+
const debug = require('debug')('codeceptjs:event')
|
|
2
|
+
const events = require('events')
|
|
3
|
+
const { error } = require('./output')
|
|
4
4
|
|
|
5
|
-
const dispatcher = new events.EventEmitter()
|
|
5
|
+
const dispatcher = new events.EventEmitter()
|
|
6
6
|
|
|
7
|
-
dispatcher.setMaxListeners(50)
|
|
7
|
+
dispatcher.setMaxListeners(50)
|
|
8
8
|
/**
|
|
9
9
|
* @namespace
|
|
10
10
|
* @alias event
|
|
@@ -59,6 +59,7 @@ module.exports = {
|
|
|
59
59
|
started: 'hook.start',
|
|
60
60
|
passed: 'hook.passed',
|
|
61
61
|
failed: 'hook.failed',
|
|
62
|
+
finished: 'hook.finished',
|
|
62
63
|
},
|
|
63
64
|
|
|
64
65
|
/**
|
|
@@ -141,33 +142,33 @@ module.exports = {
|
|
|
141
142
|
* @param {*} [param]
|
|
142
143
|
*/
|
|
143
144
|
emit(event, param) {
|
|
144
|
-
let msg = `Emitted | ${event}
|
|
145
|
+
let msg = `Emitted | ${event}`
|
|
145
146
|
if (param && param.toString()) {
|
|
146
|
-
msg += ` (${param.toString()})
|
|
147
|
+
msg += ` (${param.toString()})`
|
|
147
148
|
}
|
|
148
|
-
debug(msg)
|
|
149
|
+
debug(msg)
|
|
149
150
|
try {
|
|
150
|
-
this.dispatcher.emit.apply(this.dispatcher, arguments)
|
|
151
|
+
this.dispatcher.emit.apply(this.dispatcher, arguments)
|
|
151
152
|
} catch (err) {
|
|
152
|
-
error(`Error processing ${event} event:`)
|
|
153
|
-
error(err.stack)
|
|
153
|
+
error(`Error processing ${event} event:`)
|
|
154
|
+
error(err.stack)
|
|
154
155
|
}
|
|
155
156
|
},
|
|
156
157
|
|
|
157
158
|
/** for testing only! */
|
|
158
159
|
cleanDispatcher: () => {
|
|
159
|
-
let event
|
|
160
|
+
let event
|
|
160
161
|
for (event in this.test) {
|
|
161
|
-
this.dispatcher.removeAllListeners(this.test[event])
|
|
162
|
+
this.dispatcher.removeAllListeners(this.test[event])
|
|
162
163
|
}
|
|
163
164
|
for (event in this.suite) {
|
|
164
|
-
this.dispatcher.removeAllListeners(this.test[event])
|
|
165
|
+
this.dispatcher.removeAllListeners(this.test[event])
|
|
165
166
|
}
|
|
166
167
|
for (event in this.step) {
|
|
167
|
-
this.dispatcher.removeAllListeners(this.test[event])
|
|
168
|
+
this.dispatcher.removeAllListeners(this.test[event])
|
|
168
169
|
}
|
|
169
170
|
for (event in this.all) {
|
|
170
|
-
this.dispatcher.removeAllListeners(this.test[event])
|
|
171
|
+
this.dispatcher.removeAllListeners(this.test[event])
|
|
171
172
|
}
|
|
172
173
|
},
|
|
173
|
-
}
|
|
174
|
+
}
|
package/lib/listener/exit.js
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
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,
|
|
7
|
-
|
|
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,
|
|
15
|
-
|
|
16
|
-
// is a suite and not a test
|
|
17
|
-
const id = testOrSuite.uid || (testOrSuite.ctx && testOrSuite.ctx.test.uid) || 'empty'
|
|
13
|
+
event.dispatcher.on(event.test.passed, test => {
|
|
14
|
+
const id = test.uid || (test.ctx && test.ctx.test.uid) || 'empty'
|
|
18
15
|
failedTests = failedTests.filter(failed => id !== failed)
|
|
19
16
|
})
|
|
20
17
|
|
|
@@ -4,7 +4,7 @@ const recorder = require('../recorder')
|
|
|
4
4
|
const Config = require('../config')
|
|
5
5
|
const store = require('../store')
|
|
6
6
|
const debug = require('debug')('codeceptjs:timeout')
|
|
7
|
-
const { TIMEOUT_ORDER } = require('../
|
|
7
|
+
const { TIMEOUT_ORDER, TimeoutError, TestTimeoutError, StepTimeoutError } = require('../timeout')
|
|
8
8
|
const { BeforeSuiteHook, AfterSuiteHook } = require('../mocha/hooks')
|
|
9
9
|
|
|
10
10
|
module.exports = function () {
|
|
@@ -119,24 +119,41 @@ module.exports = function () {
|
|
|
119
119
|
}
|
|
120
120
|
})
|
|
121
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
|
+
|
|
122
143
|
event.dispatcher.on(event.step.finished, step => {
|
|
123
144
|
if (!store.timeouts) {
|
|
124
145
|
debug('step', step.toCode().trim(), 'timeout disabled')
|
|
125
146
|
return
|
|
126
147
|
}
|
|
127
148
|
|
|
149
|
+
if (typeof timeout === 'number') debug('Timeout', timeout)
|
|
150
|
+
|
|
151
|
+
debug(`step ${step.toCode().trim()}:${step.status} duration`, step.duration)
|
|
128
152
|
if (typeof timeout === 'number' && !Number.isNaN(timeout)) timeout -= step.duration
|
|
129
153
|
|
|
130
154
|
if (typeof timeout === 'number' && timeout <= 0 && recorder.isRunning()) {
|
|
131
155
|
debug(`step ${step.toCode().trim()} timed out`)
|
|
132
|
-
|
|
133
|
-
debug(`Failing test ${currentTest.title} with timeout ${currentTimeout}s`)
|
|
134
|
-
recorder.reset()
|
|
135
|
-
// replace mocha timeout with custom timeout
|
|
136
|
-
currentTest.timeout(0)
|
|
137
|
-
currentTest.callback(new Error(`Timeout ${currentTimeout}s exceeded (with Before hook)`))
|
|
138
|
-
currentTest.timedOut = true
|
|
139
|
-
}
|
|
156
|
+
recorder.throw(new TestTimeoutError(currentTimeout))
|
|
140
157
|
}
|
|
141
158
|
})
|
|
142
159
|
}
|
|
@@ -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
|
+
}
|
package/lib/listener/steps.js
CHANGED
|
@@ -13,7 +13,6 @@ let currentHook
|
|
|
13
13
|
module.exports = function () {
|
|
14
14
|
event.dispatcher.on(event.test.before, test => {
|
|
15
15
|
test.startedAt = +new Date()
|
|
16
|
-
test.artifacts = {}
|
|
17
16
|
})
|
|
18
17
|
|
|
19
18
|
event.dispatcher.on(event.test.started, test => {
|
|
@@ -71,8 +70,6 @@ module.exports = function () {
|
|
|
71
70
|
})
|
|
72
71
|
|
|
73
72
|
event.dispatcher.on(event.step.started, step => {
|
|
74
|
-
step.startedAt = +new Date()
|
|
75
|
-
step.test = currentTest
|
|
76
73
|
store.currentStep = step
|
|
77
74
|
if (currentHook && Array.isArray(currentHook.steps)) {
|
|
78
75
|
return currentHook.steps.push(step)
|
|
@@ -82,9 +79,6 @@ module.exports = function () {
|
|
|
82
79
|
})
|
|
83
80
|
|
|
84
81
|
event.dispatcher.on(event.step.finished, step => {
|
|
85
|
-
step.finishedAt = +new Date()
|
|
86
|
-
if (step.startedAt) step.duration = step.finishedAt - step.startedAt
|
|
87
|
-
debug(`Step '${step}' finished; Duration: ${step.duration || 0}ms`)
|
|
88
82
|
store.currentStep = null
|
|
89
83
|
store.stepOptions = null
|
|
90
84
|
})
|
|
@@ -13,12 +13,19 @@ const injectHook = function (inject, suite) {
|
|
|
13
13
|
recorder.throw(err)
|
|
14
14
|
}
|
|
15
15
|
recorder.catch(err => {
|
|
16
|
-
|
|
16
|
+
suiteTestFailedHookError(suite, err)
|
|
17
17
|
throw err
|
|
18
18
|
})
|
|
19
19
|
return recorder.promise()
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
function suiteTestFailedHookError(suite, err) {
|
|
23
|
+
suite.eachTest(test => {
|
|
24
|
+
test.err = err
|
|
25
|
+
event.emit(event.test.failed, test, err)
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
function makeDoneCallableOnce(done) {
|
|
23
30
|
let called = false
|
|
24
31
|
return function (err) {
|
|
@@ -61,6 +68,7 @@ module.exports.test = test => {
|
|
|
61
68
|
err = newErr
|
|
62
69
|
}
|
|
63
70
|
}
|
|
71
|
+
test.err = err
|
|
64
72
|
event.emit(event.test.failed, test, err)
|
|
65
73
|
event.emit(event.test.finished, test)
|
|
66
74
|
recorder.add(() => doneFn(err))
|
|
@@ -112,7 +120,7 @@ module.exports.injected = function (fn, suite, hookName) {
|
|
|
112
120
|
const errHandler = err => {
|
|
113
121
|
recorder.session.start('teardown')
|
|
114
122
|
recorder.cleanAsyncErr()
|
|
115
|
-
|
|
123
|
+
if (hookName == 'before' || hookName == 'beforeSuite') suiteTestFailedHookError(suite, err)
|
|
116
124
|
if (hookName === 'after') event.emit(event.test.after, suite)
|
|
117
125
|
if (hookName === 'afterSuite') event.emit(event.suite.after, suite)
|
|
118
126
|
recorder.add(() => doneFn(err))
|
|
@@ -156,6 +164,7 @@ module.exports.injected = function (fn, suite, hookName) {
|
|
|
156
164
|
)
|
|
157
165
|
.then(() => {
|
|
158
166
|
recorder.add('fire hook.passed', () => fireHook(event.hook.passed, suite))
|
|
167
|
+
recorder.add('fire hook.finished', () => fireHook(event.hook.finished, suite))
|
|
159
168
|
recorder.add(`finish ${hookName} hook`, doneFn)
|
|
160
169
|
recorder.catch()
|
|
161
170
|
})
|
|
@@ -166,6 +175,7 @@ module.exports.injected = function (fn, suite, hookName) {
|
|
|
166
175
|
errHandler(err)
|
|
167
176
|
})
|
|
168
177
|
recorder.add('fire hook.failed', () => fireHook(event.hook.failed, suite, e))
|
|
178
|
+
recorder.add('fire hook.finished', () => fireHook(event.hook.finished, suite))
|
|
169
179
|
})
|
|
170
180
|
}
|
|
171
181
|
}
|