Skip to content

Commit

Permalink
fix(vitest): allow testing unandled rejection/exception (#6016)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed Jul 1, 2024
1 parent eb6ea5b commit c8d56fe
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 3 deletions.
17 changes: 14 additions & 3 deletions packages/vitest/src/runtime/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,19 @@ function listenForErrors(state: () => WorkerGlobalState) {
dispose.forEach(fn => fn())
dispose.length = 0

function catchError(err: unknown, type: string) {
function catchError(err: unknown, type: string, event: 'uncaughtException' | 'unhandledRejection') {
const worker = state()

// if error happens during a test
if (worker.current) {
const listeners = process.listeners(event as 'uncaughtException')
// if there is another listener, assume that it's handled by user code
// one is Vitest's own listener
if (listeners.length > 1) {
return
}
}

const error = processError(err)
if (!isPrimitive(error)) {
error.VITEST_TEST_NAME = worker.current?.name
Expand All @@ -67,8 +78,8 @@ function listenForErrors(state: () => WorkerGlobalState) {
state().rpc.onUnhandledError(error, type)
}

const uncaughtException = (e: Error) => catchError(e, 'Uncaught Exception')
const unhandledRejection = (e: Error) => catchError(e, 'Unhandled Rejection')
const uncaughtException = (e: Error) => catchError(e, 'Uncaught Exception', 'uncaughtException')
const unhandledRejection = (e: Error) => catchError(e, 'Unhandled Rejection', 'unhandledRejection')

process.on('uncaughtException', uncaughtException)
process.on('unhandledRejection', unhandledRejection)
Expand Down
40 changes: 40 additions & 0 deletions test/core/test/handled-unhandled.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { nextTick } from 'node:process'
import { expect, test, vi } from 'vitest'

test('can test unhandled rejection', async () => {
const fn = vi.fn()

const promise = new Promise<void>((resolve) => {
process.on('unhandledRejection', () => {
fn()
resolve()
})
})

Promise.resolve().then(() => {
throw new Error('unhandled rejection')
})

await promise

expect(fn).toHaveBeenCalledTimes(1)
})

test('can test unhandled exception', async () => {
const fn = vi.fn()

const promise = new Promise<void>((resolve) => {
process.on('uncaughtException', () => {
fn()
resolve()
})
})

nextTick(() => {
throw new Error('unhandled exception')
})

await promise

expect(fn).toHaveBeenCalledTimes(1)
})

0 comments on commit c8d56fe

Please sign in to comment.