From 19a08b584d1609c864a948f17979758323df7805 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Wed, 11 Jan 2023 14:45:02 +0100 Subject: [PATCH 1/2] feat: add more information about unhandler error --- packages/vitest/src/node/error.ts | 17 +++++++++++++---- packages/vitest/src/runtime/worker.ts | 15 ++++++++++----- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/packages/vitest/src/node/error.ts b/packages/vitest/src/node/error.ts index 31c30fa03781..e5f696169434 100644 --- a/packages/vitest/src/node/error.ts +++ b/packages/vitest/src/node/error.ts @@ -66,6 +66,17 @@ 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 + // testName has testPath inside + if (testPath && !testName) + 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.`)) + if (testName) { + ctx.logger.error(c.red(`The latest test that migh've cause the error is "${c.bold(testName)}". It might mean one of the following:` + + '\n- The error was thrown, while Vitest was running this test.' + + '\n- This was the last recorder test before the error was thrown, if error originated after test finished its execution.')) + } + if (typeof e.cause === 'object' && e.cause && 'name' in e.cause) { (e.cause as any).name = `Caused by: ${(e.cause as any).name}` await printError(e.cause, ctx, { fullStack, showCodeFrame: false }) @@ -97,6 +108,8 @@ const skipErrorProperties = new Set([ 'showDiff', 'actual', 'expected', + 'VITEST_TEST_NAME', + 'VITEST_TEST_PATH', ...Object.getOwnPropertyNames(Error.prototype), ...Object.getOwnPropertyNames(Object.prototype), ]) @@ -183,10 +196,6 @@ function printStack( logger.error(color(` ${c.dim(F_POINTER)} ${[frame.method, c.dim(`${path}:${frame.line}:${frame.column}`)].filter(Boolean).join(' ')}`)) onStack?.(frame) - - // reached at test file, skip the follow stack - if (frame.file in ctx.state.filesMap) - break } logger.error() const hasProperties = Object.keys(errorProperties).length > 0 diff --git a/packages/vitest/src/runtime/worker.ts b/packages/vitest/src/runtime/worker.ts index 20264039c600..09d70016e3cd 100644 --- a/packages/vitest/src/runtime/worker.ts +++ b/packages/vitest/src/runtime/worker.ts @@ -1,7 +1,8 @@ -import { resolve } from 'pathe' +import { relative, resolve } from 'pathe' import { createBirpc } from 'birpc' import { workerId as poolId } from 'tinypool' import { ModuleCacheMap } from 'vite-node/client' +import { isPrimitive } from 'vite-node/utils' import type { ResolvedConfig, WorkerContext, WorkerRPC } from '../types' import { distDir } from '../constants' import { getWorkerState } from '../utils' @@ -21,7 +22,7 @@ async function startViteNode(ctx: WorkerContext) { if (_viteNode) return _viteNode - const processExit = process.exit + const { config } = ctx process.on('beforeExit', (code) => { rpc().onWorkerExit(code) @@ -33,11 +34,15 @@ async function startViteNode(ctx: WorkerContext) { } process.on('unhandledRejection', (err) => { - rpc().onUnhandledRejection(processError(err)) + const worker = getWorkerState() + const error = processError(err) + if (worker.filepath && !isPrimitive(error)) { + error.VITEST_TEST_NAME = worker.current?.name + error.VITEST_TEST_PATH = relative(config.root, worker.filepath) + } + rpc().onUnhandledRejection(error) }) - const { config } = ctx - const { run } = (await executeInViteNode({ files: [ resolve(distDir, 'entry.js'), From 6596868098751c8e2befd33d0dda620208c7e825 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Wed, 11 Jan 2023 15:01:31 +0100 Subject: [PATCH 2/2] chore: fix type issue --- packages/vitest/src/runtime/worker.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/vitest/src/runtime/worker.ts b/packages/vitest/src/runtime/worker.ts index 09d70016e3cd..c834003a9efe 100644 --- a/packages/vitest/src/runtime/worker.ts +++ b/packages/vitest/src/runtime/worker.ts @@ -24,6 +24,8 @@ async function startViteNode(ctx: WorkerContext) { const { config } = ctx + const processExit = process.exit + process.on('beforeExit', (code) => { rpc().onWorkerExit(code) })