From c8d56fe5fceabfc61b8f1e42e9d30f740e671638 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Mon, 1 Jul 2024 18:04:19 +0200 Subject: [PATCH] fix(vitest): allow testing unandled rejection/exception (#6016) --- packages/vitest/src/runtime/execute.ts | 17 ++++++++-- test/core/test/handled-unhandled.test.ts | 40 ++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 test/core/test/handled-unhandled.test.ts diff --git a/packages/vitest/src/runtime/execute.ts b/packages/vitest/src/runtime/execute.ts index 788a9cb58b34..fa43260ff69b 100644 --- a/packages/vitest/src/runtime/execute.ts +++ b/packages/vitest/src/runtime/execute.ts @@ -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 @@ -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) diff --git a/test/core/test/handled-unhandled.test.ts b/test/core/test/handled-unhandled.test.ts new file mode 100644 index 000000000000..b86c23ff9e6f --- /dev/null +++ b/test/core/test/handled-unhandled.test.ts @@ -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((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((resolve) => { + process.on('uncaughtException', () => { + fn() + resolve() + }) + }) + + nextTick(() => { + throw new Error('unhandled exception') + }) + + await promise + + expect(fn).toHaveBeenCalledTimes(1) +})