Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions lib/listener/globalTimeout.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,15 @@ export default function () {
if (typeof timeout !== 'number') return

if (!store.timeouts) {
debug('step', step.toCode().trim(), 'timeout disabled')
debug('step', (step.code || (typeof step.toCode === 'function' ? step.toCode() : step.name)).trim(), 'timeout disabled')
return
}

if (timeout < 0) {
debug('Previous steps timed out, setting timeout to 0.01s')
step.setTimeout(0.01, TIMEOUT_ORDER.testOrSuite)
} else {
debug(`Setting timeout ${timeout}ms for step ${step.toCode().trim()}`)
debug(`Setting timeout ${timeout}ms for step ${(step.code || (typeof step.toCode === 'function' ? step.toCode() : step.name)).trim()}`)
step.setTimeout(timeout, TIMEOUT_ORDER.testOrSuite)
}
})
Expand Down Expand Up @@ -158,17 +158,17 @@ export default function () {

event.dispatcher.on(event.step.finished, step => {
if (!store.timeouts) {
debug('step', step.toCode().trim(), 'timeout disabled')
debug('step', (step.code || (typeof step.toCode === 'function' ? step.toCode() : step.name)).trim(), 'timeout disabled')
return
}

if (typeof timeout === 'number') debug('Timeout', timeout)

debug(`step ${step.toCode().trim()}:${step.status} duration`, step.duration)
debug(`step ${(step.code || (typeof step.toCode === 'function' ? step.toCode() : step.name)).trim()}:${step.status} duration`, step.duration)
if (typeof timeout === 'number' && !Number.isNaN(timeout)) timeout -= step.duration

if (typeof timeout === 'number' && timeout <= 0 && recorder.isRunning()) {
debug(`step ${step.toCode().trim()} timed out`)
debug(`step ${(step.code || (typeof step.toCode === 'function' ? step.toCode() : step.name)).trim()} timed out`)
recorder.throw(new TestTimeoutError(currentTimeout))
}
})
Expand Down
1 change: 1 addition & 0 deletions lib/step/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ class Step {
startTime: step.startTime,
endTime: step.endTime,
parent,
code: step.toCode(),
}
}

Expand Down
19 changes: 19 additions & 0 deletions lib/workers.js
Original file line number Diff line number Diff line change
Expand Up @@ -626,18 +626,22 @@ class Workers extends EventEmitter {
break
case event.suite.before:
this.emit(event.suite.before, deserializeSuite(message.data))
event.dispatcher.emit(event.suite.before, deserializeSuite(message.data))
break
case event.test.before:
this.emit(event.test.before, deserializeTest(message.data))
event.dispatcher.emit(event.test.before, deserializeTest(message.data))
break
case event.test.started:
this.emit(event.test.started, deserializeTest(message.data))
event.dispatcher.emit(event.test.started, deserializeTest(message.data))
break
case event.test.failed:
// For hook failures, emit immediately as there won't be a test.finished event
// Regular test failures are handled via test.finished to support retries
if (message.data?.hookName) {
this.emit(event.test.failed, deserializeTest(message.data))
event.dispatcher.emit(event.test.failed, deserializeTest(message.data))
}
// Otherwise skip - we'll emit based on finished state
break
Expand All @@ -646,6 +650,7 @@ class Workers extends EventEmitter {
break
case event.test.skipped:
this.emit(event.test.skipped, deserializeTest(message.data))
event.dispatcher.emit(event.test.skipped, deserializeTest(message.data))
break
case event.test.finished:
// Handle different types of test completion properly
Expand All @@ -669,34 +674,44 @@ class Workers extends EventEmitter {
// For tests without UID, emit immediately
if (isFailed) {
this.emit(event.test.failed, deserializeTest(data))
event.dispatcher.emit(event.test.failed, deserializeTest(data))
} else {
this.emit(event.test.passed, deserializeTest(data))
event.dispatcher.emit(event.test.passed, deserializeTest(data))
}
}

this.emit(event.test.finished, deserializeTest(data))
event.dispatcher.emit(event.test.finished, deserializeTest(data))
}
break
case event.test.after:
this.emit(event.test.after, deserializeTest(message.data))
event.dispatcher.emit(event.test.after, deserializeTest(message.data))
break
case event.step.finished:
this.emit(event.step.finished, message.data)
event.dispatcher.emit(event.step.finished, message.data)
break
case event.step.started:
this.emit(event.step.started, message.data)
event.dispatcher.emit(event.step.started, message.data)
break
case event.step.passed:
this.emit(event.step.passed, message.data)
event.dispatcher.emit(event.step.passed, message.data)
break
case event.step.failed:
this.emit(event.step.failed, message.data, message.data.error)
event.dispatcher.emit(event.step.failed, message.data, message.data.error)
break
case event.hook.failed:
// Hook failures are already reported as test failures by the worker
// Just emit the hook.failed event for listeners
this.emit(event.hook.failed, message.data)
event.dispatcher.emit(event.hook.failed, message.data)
break

}
})

Expand Down Expand Up @@ -759,16 +774,20 @@ class Workers extends EventEmitter {
for (const state of states) {
if (state.isFailed) {
this.emit(event.test.failed, deserializeTest(state.data))
event.dispatcher.emit(event.test.failed, deserializeTest(state.data))
} else {
this.emit(event.test.passed, deserializeTest(state.data))
event.dispatcher.emit(event.test.passed, deserializeTest(state.data))
}
}
} else {
// For non-retries (like step failures), emit only the final state
if (lastState.isFailed) {
this.emit(event.test.failed, deserializeTest(lastState.data))
event.dispatcher.emit(event.test.failed, deserializeTest(lastState.data))
} else {
this.emit(event.test.passed, deserializeTest(lastState.data))
event.dispatcher.emit(event.test.passed, deserializeTest(lastState.data))
}
}
}
Expand Down
Loading