Skip to content

Commit

Permalink
fix: capture unhandledRejection even when base reporter is not used (
Browse files Browse the repository at this point in the history
  • Loading branch information
AriPerkkio authored Oct 29, 2024
1 parent 0bf0ab0 commit 8878b04
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 21 deletions.
21 changes: 21 additions & 0 deletions packages/vitest/src/node/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export class Logger {
this.console = new Console({ stdout: outputStream, stderr: errorStream })
this.logUpdate = createLogUpdate(this.outputStream)
this._highlights.clear()
this.registerUnhandledRejection()
}

log(...args: any[]) {
Expand Down Expand Up @@ -317,4 +318,24 @@ export class Logger {
})
this.log(c.red(divider()))
}

private registerUnhandledRejection() {
const onUnhandledRejection = (err: unknown) => {
process.exitCode = 1

this.printError(err, {
fullStack: true,
type: 'Unhandled Rejection',
})

this.error('\n\n')
process.exit()
}

process.on('unhandledRejection', onUnhandledRejection)

this.ctx.onClose(() => {
process.off('unhandledRejection', onUnhandledRejection)
})
}
}
21 changes: 0 additions & 21 deletions packages/vitest/src/node/reporters/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,9 @@ export abstract class BaseReporter implements Reporter {
private _lastRunTimer: NodeJS.Timeout | undefined
private _lastRunCount = 0
private _timeStart = new Date()
private _offUnhandledRejection?: () => void

constructor(options: BaseOptions = {}) {
this.isTTY = options.isTTY ?? ((isNode || isDeno) && process.stdout?.isTTY && !isCI)
this.registerUnhandledRejection()
}

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

onInit(ctx: Vitest) {
this.ctx = ctx
ctx.onClose(() => {
this._offUnhandledRejection?.()
})
ctx.logger.printBanner()
this.start = performance.now()
}
Expand Down Expand Up @@ -626,22 +621,6 @@ export abstract class BaseReporter implements Reporter {
errorDivider()
}
}

registerUnhandledRejection() {
const onUnhandledRejection = async (err: unknown) => {
process.exitCode = 1
this.ctx.logger.printError(err, {
fullStack: true,
type: 'Unhandled Rejection',
})
this.ctx.logger.error('\n\n')
process.exit()
}
process.on('unhandledRejection', onUnhandledRejection)
this._offUnhandledRejection = () => {
process.off('unhandledRejection', onUnhandledRejection)
}
}
}

function padTitle(str: string) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function setup() {
void new Promise((_, reject) => reject(new Error('intentional unhandled rejection')))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { test } from "vitest"

test("Some test", () => {})

16 changes: 16 additions & 0 deletions test/config/test/unhandled-rejections.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { expect, test } from 'vitest'

import { runVitest } from '../../test-utils'

test('unhandled rejections of main thread are reported even when no reporter is used', async () => {
const { stderr, exitCode } = await runVitest({
root: 'fixtures/unhandled-rejections',
globalSetup: ['setup-unhandled-rejections.ts'],
reporters: [{ onInit: () => {} }],
})

expect(exitCode).toBe(1)
expect(stderr).toContain('Unhandled Rejection')
expect(stderr).toContain('Error: intentional unhandled rejection')
expect(stderr).toContain('setup-unhandled-rejections.ts:2:42')
})

0 comments on commit 8878b04

Please sign in to comment.