From e9b638d40d037f910d19d76b38bc3dc7d6f5cd59 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Mon, 1 Jul 2024 09:27:20 +0200 Subject: [PATCH] fix(api): don't call process.exit manually (#5926) --- packages/vitest/src/constants.ts | 2 -- packages/vitest/src/node/cli/cac.ts | 9 +++++++-- packages/vitest/src/node/cli/cli-api.ts | 16 ++++++++++------ packages/vitest/src/node/core.ts | 9 +++++---- packages/vitest/src/node/errors.ts | 15 +++++++++++++++ packages/vitest/src/node/index.ts | 2 ++ packages/vitest/src/node/packageInstaller.ts | 3 +-- packages/vitest/src/node/reporters/base.ts | 2 +- test/config/test/mode.test.ts | 2 +- 9 files changed, 42 insertions(+), 18 deletions(-) create mode 100644 packages/vitest/src/node/errors.ts diff --git a/packages/vitest/src/constants.ts b/packages/vitest/src/constants.ts index 066c7b8c143a..3bde7bb53993 100644 --- a/packages/vitest/src/constants.ts +++ b/packages/vitest/src/constants.ts @@ -3,8 +3,6 @@ export const defaultPort = 51204 export const defaultBrowserPort = 63315 export const defaultInspectPort = 9229 -export const EXIT_CODE_RESTART = 43 - export const API_PATH = '/__vitest_api__' export const extraInlineDeps = [ diff --git a/packages/vitest/src/node/cli/cac.ts b/packages/vitest/src/node/cli/cac.ts index 9df2d566cfb8..6c11444ce76b 100644 --- a/packages/vitest/src/node/cli/cac.ts +++ b/packages/vitest/src/node/cli/cac.ts @@ -265,10 +265,15 @@ async function start(mode: VitestRunMode, cliFilters: string[], options: CliOpti } catch (e) { const { divider } = await import('../reporters/renderers/utils') - console.error(`\n${c.red(divider(c.bold(c.inverse(' Unhandled Error '))))}`) + console.error(`\n${c.red(divider(c.bold(c.inverse(' Startup Error '))))}`) console.error(e) console.error('\n\n') - process.exit(1) + + if (process.exitCode == null) { + process.exitCode = 1 + } + + process.exit() } } diff --git a/packages/vitest/src/node/cli/cli-api.ts b/packages/vitest/src/node/cli/cli-api.ts index 7ba0fda8b2e5..9d255807bf86 100644 --- a/packages/vitest/src/node/cli/cli-api.ts +++ b/packages/vitest/src/node/cli/cli-api.ts @@ -1,12 +1,12 @@ import { resolve } from 'pathe' import type { UserConfig as ViteUserConfig } from 'vite' -import { EXIT_CODE_RESTART } from '../../constants' import { CoverageProviderMap } from '../../integrations/coverage' import { getEnvPackageName } from '../../integrations/env' import type { UserConfig, Vitest, VitestRunMode } from '../../types' import { createVitest } from '../create' import { registerConsoleShortcuts } from '../stdin' import type { VitestOptions } from '../core' +import { FilesNotFoundError, GitNotFoundError } from '../errors' export interface CliOptions extends UserConfig { /** @@ -86,11 +86,6 @@ export async function startVitest( ctx.onServerRestart((reason) => { ctx.report('onServerRestart', reason) - - // if it's in a CLI wrapper, exit with a special code to request restart - if (process.env.VITEST_CLI_WRAPPER) { - process.exit(EXIT_CODE_RESTART) - } }) ctx.onAfterSetServer(() => { @@ -114,6 +109,15 @@ export async function startVitest( } } catch (e) { + if (e instanceof FilesNotFoundError) { + return ctx + } + + if (e instanceof GitNotFoundError) { + ctx.logger.error(e.message) + return ctx + } + process.exitCode = 1 ctx.logger.printError(e, { fullStack: true, type: 'Unhandled Error' }) ctx.logger.error('\n\n') diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts index d0ed0afeeef5..41ca9c8b74d9 100644 --- a/packages/vitest/src/node/core.ts +++ b/packages/vitest/src/node/core.ts @@ -6,7 +6,6 @@ import { mergeConfig } from 'vite' import { basename, dirname, join, normalize, relative, resolve } from 'pathe' import fg from 'fast-glob' import mm from 'micromatch' -import c from 'picocolors' import { ViteNodeRunner } from 'vite-node/client' import { SnapshotManager } from '@vitest/snapshot/manager' import type { CancelReason, File, TaskResultPack } from '@vitest/runner' @@ -29,6 +28,7 @@ import { VitestCache } from './cache' import { WorkspaceProject, initializeProject } from './workspace' import { VitestPackageInstaller } from './packageInstaller' import { BlobReporter, readBlobs } from './reporters/blob' +import { FilesNotFoundError, GitNotFoundError } from './errors' const WATCHER_DEBOUNCE = 100 @@ -492,7 +492,8 @@ export class Vitest { if (!this.config.watch || !(this.config.changed || this.config.related?.length)) { const exitCode = this.config.passWithNoTests ? 0 : 1 - process.exit(exitCode) + process.exitCode = exitCode + throw new FilesNotFoundError(this.mode) } } @@ -564,8 +565,8 @@ export class Vitest { changedSince: this.config.changed, }) if (!related) { - this.logger.error(c.red('Could not find Git root. Have you initialized git with `git init`?\n')) - process.exit(1) + process.exitCode = 1 + throw new GitNotFoundError() } this.config.related = Array.from(new Set(related)) } diff --git a/packages/vitest/src/node/errors.ts b/packages/vitest/src/node/errors.ts new file mode 100644 index 000000000000..296458134d67 --- /dev/null +++ b/packages/vitest/src/node/errors.ts @@ -0,0 +1,15 @@ +export class FilesNotFoundError extends Error { + code = 'VITEST_FILES_NOT_FOUND' + + constructor(mode: 'test' | 'benchmark') { + super(`No ${mode} files found`) + } +} + +export class GitNotFoundError extends Error { + code = 'VITEST_GIT_NOT_FOUND' + + constructor() { + super('Could not find Git root. Have you initialized git with `git init`?') + } +} diff --git a/packages/vitest/src/node/index.ts b/packages/vitest/src/node/index.ts index fd81636562a2..2f509fc86926 100644 --- a/packages/vitest/src/node/index.ts +++ b/packages/vitest/src/node/index.ts @@ -14,6 +14,8 @@ export { createDebugger } from '../utils/debugger' export { resolveFsAllow } from './plugins/utils' export { resolveApiServerConfig, resolveConfig } from './config' +export { GitNotFoundError, FilesNotFoundError as TestsNotFoundError } from './errors' + export { distDir, rootDir } from '../paths' export type { diff --git a/packages/vitest/src/node/packageInstaller.ts b/packages/vitest/src/node/packageInstaller.ts index 7d37b46f60e8..85ca05d3042c 100644 --- a/packages/vitest/src/node/packageInstaller.ts +++ b/packages/vitest/src/node/packageInstaller.ts @@ -2,7 +2,6 @@ import url from 'node:url' import { createRequire } from 'node:module' import c from 'picocolors' import { isPackageExists } from 'local-pkg' -import { EXIT_CODE_RESTART } from '../constants' import { isCI } from '../utils/env' const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) @@ -59,7 +58,7 @@ export class VitestPackageInstaller { `\nPackage ${dependency} installed, re-run the command to start.\n`, ), ) - process.exit(EXIT_CODE_RESTART) + process.exit() return true } diff --git a/packages/vitest/src/node/reporters/base.ts b/packages/vitest/src/node/reporters/base.ts index c2d4eb6241d5..5fcb7f6b69e7 100644 --- a/packages/vitest/src/node/reporters/base.ts +++ b/packages/vitest/src/node/reporters/base.ts @@ -625,7 +625,7 @@ export abstract class BaseReporter implements Reporter { type: 'Unhandled Rejection', }) this.ctx.logger.error('\n\n') - process.exit(1) + process.exit() } process.on('unhandledRejection', onUnhandledRejection) this._offUnhandledRejection = () => { diff --git a/test/config/test/mode.test.ts b/test/config/test/mode.test.ts index 7381e06c6155..19d3413f90a6 100644 --- a/test/config/test/mode.test.ts +++ b/test/config/test/mode.test.ts @@ -17,7 +17,7 @@ test.each([ const { stdout, stderr } = await testUtils.runVitestCli(...(command), 'fixtures/mode', '-c', `fixtures/mode/vitest.${expectedMode}.config.ts`) expect(stderr).toContain(`env.mode: ${actualMode}`) - expect(stderr).toContain('⎯⎯⎯⎯⎯⎯ Unhandled Error ⎯⎯⎯⎯⎯⎯⎯') + expect(stderr).toContain('Startup Error') expect(stderr).toContain(`Error: env.mode should be equal to "${expectedMode}"`) expect(stdout).toBe('') })