From 1fe8286c790cef9063b1f5f8147f6d41fc14bf79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Fri, 10 Mar 2023 14:30:07 +0200 Subject: [PATCH] feat: uncaught errors to indicate env teardown (#2982) --- packages/vitest/src/node/error.ts | 7 +++++++ packages/vitest/src/runtime/entry.ts | 2 ++ packages/vitest/src/runtime/execute.ts | 2 ++ packages/vitest/src/types/worker.ts | 1 + test/core/test/dom.test.ts | 16 ---------------- 5 files changed, 12 insertions(+), 16 deletions(-) diff --git a/packages/vitest/src/node/error.ts b/packages/vitest/src/node/error.ts index df92c45545a7..5e726d4ce4ab 100644 --- a/packages/vitest/src/node/error.ts +++ b/packages/vitest/src/node/error.ts @@ -72,6 +72,7 @@ export async function printError(error: unknown, ctx: Vitest, options: PrintErro const testPath = (e as any).VITEST_TEST_PATH const testName = (e as any).VITEST_TEST_NAME + const afterEnvTeardown = (e as any).VITEST_AFTER_ENV_TEARDOWN // testName has testPath inside if (testPath) ctx.logger.error(c.red(`This error originated in "${c.bold(testPath)}" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.`)) @@ -80,6 +81,11 @@ export async function printError(error: unknown, ctx: Vitest, options: PrintErro + '\n- The error was thrown, while Vitest was running this test.' + '\n- This was the last recorded test before the error was thrown, if error originated after test finished its execution.')) } + if (afterEnvTeardown) { + ctx.logger.error(c.red('This error was caught after test environment was torn down. Make sure to cancel any running tasks before test finishes:' + + '\n- cancel timeouts using clearTimeout and clearInterval' + + '\n- wait for promises to resolve using the await keyword')) + } if (typeof e.cause === 'object' && e.cause && 'name' in e.cause) { (e.cause as any).name = `Caused by: ${(e.cause as any).name}` @@ -117,6 +123,7 @@ const skipErrorProperties = new Set([ 'expected', 'VITEST_TEST_NAME', 'VITEST_TEST_PATH', + 'VITEST_AFTER_ENV_TEARDOWN', ...Object.getOwnPropertyNames(Error.prototype), ...Object.getOwnPropertyNames(Object.prototype), ]) diff --git a/packages/vitest/src/runtime/entry.ts b/packages/vitest/src/runtime/entry.ts index e785b63a000e..f3575ddbcd98 100644 --- a/packages/vitest/src/runtime/entry.ts +++ b/packages/vitest/src/runtime/entry.ts @@ -100,4 +100,6 @@ export async function run(files: string[], config: ResolvedConfig, environment: await stopCoverageInsideWorker(config.coverage, executor) }) + + workerState.environmentTeardownRun = true } diff --git a/packages/vitest/src/runtime/execute.ts b/packages/vitest/src/runtime/execute.ts index 49fc0943f8dc..333707685ecf 100644 --- a/packages/vitest/src/runtime/execute.ts +++ b/packages/vitest/src/runtime/execute.ts @@ -53,6 +53,8 @@ export async function startViteNode(ctx: ContextRPC) { error.VITEST_TEST_NAME = worker.current?.name error.VITEST_TEST_PATH = relative(config.root, worker.filepath) } + error.VITEST_AFTER_ENV_TEARDOWN = worker.environmentTeardownRun + rpc().onUnhandledError(error, type) } diff --git a/packages/vitest/src/types/worker.ts b/packages/vitest/src/types/worker.ts index 165940c4589d..a90c214fb26f 100644 --- a/packages/vitest/src/types/worker.ts +++ b/packages/vitest/src/types/worker.ts @@ -23,6 +23,7 @@ export interface WorkerGlobalState { rpc: BirpcReturn current?: Test filepath?: string + environmentTeardownRun?: boolean moduleCache: ModuleCacheMap mockMap: MockMap } diff --git a/test/core/test/dom.test.ts b/test/core/test/dom.test.ts index fe8575ba1817..1f6a04010072 100644 --- a/test/core/test/dom.test.ts +++ b/test/core/test/dom.test.ts @@ -171,19 +171,3 @@ it('doesn\'t throw, if listening for error', () => { dispatchEvent(new Event('custom')) expect(spy).toHaveBeenCalled() }) - -it('timers are not run after environment teardown', async () => { - setInterval(() => { - try { - window.document.createElement('div') - } - catch (err) { - if (/window is not defined/.test((err as any).message)) - throw new Error('setInterval was called after environment teardown') - - throw err - } - }, 1) - - expect(window.document).toBeDefined() -})