Skip to content

Commit 8878b04

Browse files
authored
fix: capture unhandledRejection even when base reporter is not used (#6812)
1 parent 0bf0ab0 commit 8878b04

File tree

5 files changed

+44
-21
lines changed

5 files changed

+44
-21
lines changed

packages/vitest/src/node/logger.ts

+21
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export class Logger {
4646
this.console = new Console({ stdout: outputStream, stderr: errorStream })
4747
this.logUpdate = createLogUpdate(this.outputStream)
4848
this._highlights.clear()
49+
this.registerUnhandledRejection()
4950
}
5051

5152
log(...args: any[]) {
@@ -317,4 +318,24 @@ export class Logger {
317318
})
318319
this.log(c.red(divider()))
319320
}
321+
322+
private registerUnhandledRejection() {
323+
const onUnhandledRejection = (err: unknown) => {
324+
process.exitCode = 1
325+
326+
this.printError(err, {
327+
fullStack: true,
328+
type: 'Unhandled Rejection',
329+
})
330+
331+
this.error('\n\n')
332+
process.exit()
333+
}
334+
335+
process.on('unhandledRejection', onUnhandledRejection)
336+
337+
this.ctx.onClose(() => {
338+
process.off('unhandledRejection', onUnhandledRejection)
339+
})
340+
}
320341
}

packages/vitest/src/node/reporters/base.ts

-21
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,9 @@ export abstract class BaseReporter implements Reporter {
5959
private _lastRunTimer: NodeJS.Timeout | undefined
6060
private _lastRunCount = 0
6161
private _timeStart = new Date()
62-
private _offUnhandledRejection?: () => void
6362

6463
constructor(options: BaseOptions = {}) {
6564
this.isTTY = options.isTTY ?? ((isNode || isDeno) && process.stdout?.isTTY && !isCI)
66-
this.registerUnhandledRejection()
6765
}
6866

6967
get mode() {
@@ -72,9 +70,6 @@ export abstract class BaseReporter implements Reporter {
7270

7371
onInit(ctx: Vitest) {
7472
this.ctx = ctx
75-
ctx.onClose(() => {
76-
this._offUnhandledRejection?.()
77-
})
7873
ctx.logger.printBanner()
7974
this.start = performance.now()
8075
}
@@ -626,22 +621,6 @@ export abstract class BaseReporter implements Reporter {
626621
errorDivider()
627622
}
628623
}
629-
630-
registerUnhandledRejection() {
631-
const onUnhandledRejection = async (err: unknown) => {
632-
process.exitCode = 1
633-
this.ctx.logger.printError(err, {
634-
fullStack: true,
635-
type: 'Unhandled Rejection',
636-
})
637-
this.ctx.logger.error('\n\n')
638-
process.exit()
639-
}
640-
process.on('unhandledRejection', onUnhandledRejection)
641-
this._offUnhandledRejection = () => {
642-
process.off('unhandledRejection', onUnhandledRejection)
643-
}
644-
}
645624
}
646625

647626
function padTitle(str: string) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function setup() {
2+
void new Promise((_, reject) => reject(new Error('intentional unhandled rejection')))
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { test } from "vitest"
2+
3+
test("Some test", () => {})
4+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { expect, test } from 'vitest'
2+
3+
import { runVitest } from '../../test-utils'
4+
5+
test('unhandled rejections of main thread are reported even when no reporter is used', async () => {
6+
const { stderr, exitCode } = await runVitest({
7+
root: 'fixtures/unhandled-rejections',
8+
globalSetup: ['setup-unhandled-rejections.ts'],
9+
reporters: [{ onInit: () => {} }],
10+
})
11+
12+
expect(exitCode).toBe(1)
13+
expect(stderr).toContain('Unhandled Rejection')
14+
expect(stderr).toContain('Error: intentional unhandled rejection')
15+
expect(stderr).toContain('setup-unhandled-rejections.ts:2:42')
16+
})

0 commit comments

Comments
 (0)