From 6efe61ab772c94d9b10ce34c88b7fa343a449714 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Fri, 24 Mar 2023 09:00:06 +0100 Subject: [PATCH] fix: do not fail, when primitive error is thrown (#3074) --- packages/vitest/src/api/setup.ts | 7 ++++--- packages/vitest/src/node/core.ts | 2 +- packages/vitest/src/node/error.ts | 7 ++++--- packages/vitest/src/utils/base.ts | 4 ++++ packages/vitest/src/utils/source-map.ts | 4 ++-- test/fails/fixtures/primitive-error.test.ts | 6 ++++++ test/fails/test/__snapshots__/runner.test.ts.snap | 2 ++ 7 files changed, 23 insertions(+), 9 deletions(-) create mode 100644 test/fails/fixtures/primitive-error.test.ts diff --git a/packages/vitest/src/api/setup.ts b/packages/vitest/src/api/setup.ts index 735b9ee0826a..57e3f7035f0d 100644 --- a/packages/vitest/src/api/setup.ts +++ b/packages/vitest/src/api/setup.ts @@ -9,7 +9,7 @@ import type { ViteDevServer } from 'vite' import { API_PATH } from '../constants' import type { Vitest } from '../node' import type { File, ModuleGraphData, Reporter, TaskResultPack, UserConsoleLog } from '../types' -import { getModuleGraph } from '../utils' +import { getModuleGraph, isPrimitive } from '../utils' import { parseErrorStacktrace } from '../utils/source-map' import type { TransformResultWithSource, WebSocketEvents, WebSocketHandlers } from './types' @@ -140,10 +140,11 @@ class WebSocketReporter implements Reporter { packs.forEach(([, result]) => { // TODO remove after "error" deprecation is removed - if (result?.error) + if (result?.error && !isPrimitive(result.error)) result.error.stacks = parseErrorStacktrace(result.error) result?.errors?.forEach((error) => { - error.stacks = parseErrorStacktrace(error) + if (!isPrimitive(error)) + error.stacks = parseErrorStacktrace(error) }) }) diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts index 814227a73951..891eaa7d96f4 100644 --- a/packages/vitest/src/node/core.ts +++ b/packages/vitest/src/node/core.ts @@ -721,7 +721,7 @@ export class Vitest { isBrowserEnabled() { if (this.config.browser.enabled) return true - return (this.config.poolMatchGlobs || []).some(([, pool]) => pool === 'browser') + return this.config.poolMatchGlobs?.length && this.config.poolMatchGlobs.some(([, pool]) => pool === 'browser') } // The server needs to be running for communication diff --git a/packages/vitest/src/node/error.ts b/packages/vitest/src/node/error.ts index 5e726d4ce4ab..b447c8e881db 100644 --- a/packages/vitest/src/node/error.ts +++ b/packages/vitest/src/node/error.ts @@ -9,6 +9,7 @@ import type { ErrorWithDiff, ParsedStack } from '../types' import { lineSplitRE, parseErrorStacktrace, positionToOffset } from '../utils/source-map' import { F_POINTER } from '../utils/figures' import { TypeCheckError } from '../typecheck/typechecker' +import { isPrimitive } from '../utils' import type { Vitest } from './core' import { divider } from './reporters/renderers/utils' import type { Logger } from './logger' @@ -23,10 +24,10 @@ export async function printError(error: unknown, ctx: Vitest, options: PrintErro const { showCodeFrame = true, fullStack = false, type } = options let e = error as ErrorWithDiff - if (typeof error === 'string') { + if (isPrimitive(e)) { e = { - message: error.split(/\n/g)[0], - stack: error, + message: String(error).split(/\n/g)[0], + stack: String(error), } as any } diff --git a/packages/vitest/src/utils/base.ts b/packages/vitest/src/utils/base.ts index 06b02509d11b..f66ed34b82d2 100644 --- a/packages/vitest/src/utils/base.ts +++ b/packages/vitest/src/utils/base.ts @@ -19,6 +19,10 @@ export function groupBy(collection: T[], }, {} as Record) } +export function isPrimitive(value: unknown) { + return value === null || (typeof value !== 'function' && typeof value !== 'object') +} + export function getAllMockableProperties(obj: any, isModule: boolean) { const allProps = new Map() let curr = obj diff --git a/packages/vitest/src/utils/source-map.ts b/packages/vitest/src/utils/source-map.ts index f4b82a376f66..1f653a9632df 100644 --- a/packages/vitest/src/utils/source-map.ts +++ b/packages/vitest/src/utils/source-map.ts @@ -1,6 +1,6 @@ import { resolve } from 'pathe' import type { ErrorWithDiff, ParsedStack } from '../types' -import { notNullish } from './base' +import { isPrimitive, notNullish } from './base' export const lineSplitRE = /\r?\n/ @@ -92,7 +92,7 @@ export function parseStacktrace(stack: string, full = false): ParsedStack[] { } export function parseErrorStacktrace(e: ErrorWithDiff, full = false): ParsedStack[] { - if (!e) + if (!e || isPrimitive(e)) return [] if (e.stacks) diff --git a/test/fails/fixtures/primitive-error.test.ts b/test/fails/fixtures/primitive-error.test.ts new file mode 100644 index 000000000000..ad4233f6deb1 --- /dev/null +++ b/test/fails/fixtures/primitive-error.test.ts @@ -0,0 +1,6 @@ +import { test } from 'vitest' + +test('primitive error thrown', () => { + // eslint-disable-next-line no-throw-literal + throw 42 +}) diff --git a/test/fails/test/__snapshots__/runner.test.ts.snap b/test/fails/test/__snapshots__/runner.test.ts.snap index 7e72c432c888..8a0d962d31ea 100644 --- a/test/fails/test/__snapshots__/runner.test.ts.snap +++ b/test/fails/test/__snapshots__/runner.test.ts.snap @@ -19,6 +19,8 @@ exports[`should fails > mock-import-proxy-module.test.ts > mock-import-proxy-mod exports[`should fails > nested-suite.test.ts > nested-suite.test.ts 1`] = `"AssertionError: expected true to be false // Object.is equality"`; +exports[`should fails > primitive-error.test.ts > primitive-error.test.ts 1`] = `"Unknown Error: 42"`; + exports[`should fails > stall.test.ts > stall.test.ts 1`] = ` "TypeError: failure TypeError: failure