diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts index fc77fdfd41e2..88ebd36e0c20 100644 --- a/packages/vitest/src/node/core.ts +++ b/packages/vitest/src/node/core.ts @@ -1,7 +1,7 @@ import { existsSync, promises as fs } from 'node:fs' import type { Writable } from 'node:stream' import type { ViteDevServer } from 'vite' -import { dirname, join, normalize, relative, resolve } from 'pathe' +import { dirname, join, normalize, relative } from 'pathe' import mm from 'micromatch' import { ViteNodeRunner } from 'vite-node/client' import { SnapshotManager } from '@vitest/snapshot/manager' @@ -12,10 +12,10 @@ import { version } from '../../package.json' with { type: 'json' } import { getTasks, hasFailed, noop, slash, toArray, wildcardPatternToRegExp } from '../utils' import { getCoverageProvider } from '../integrations/coverage' import { workspacesFiles as workspaceFiles } from '../constants' -import { rootDir } from '../paths' import { WebSocketReporter } from '../api/setup' import type { SerializedCoverageConfig } from '../runtime/config' import type { ArgumentsType, OnServerRestartHandler, ProvidedContext, UserConsoleLog } from '../types/general' +import { distDir } from '../paths' import type { ProcessPool, WorkspaceSpec } from './pool' import { createPool, getFilePoolName } from './pool' import { createBenchmarkReporters, createReporters } from './reporters/utils' @@ -78,7 +78,7 @@ export class Vitest { private resolvedProjects: WorkspaceProject[] = [] public projects: WorkspaceProject[] = [] - public distPath!: string + public distPath = distDir private _cachedSpecs = new Map() @@ -106,7 +106,6 @@ export class Vitest { this.pool = undefined this.coverageProvider = undefined this.runningPromise = undefined - this.distPath = undefined! this._cachedSpecs.clear() const resolved = resolveConfig(this.mode, options, server.config, this.logger) @@ -560,20 +559,7 @@ export class Vitest { } } - private async initializeDistPath() { - if (this.distPath) { - return - } - - // if Vitest is running globally, then we should still import local vitest if possible - const projectVitestPath = await this.vitenode.resolveId('vitest') - const vitestDir = projectVitestPath ? resolve(projectVitestPath.id, '../..') : rootDir - this.distPath = join(vitestDir, 'dist') - } - async runFiles(specs: TestSpecification[], allTestsRun: boolean) { - await this.initializeDistPath() - const filepaths = specs.map(spec => spec.moduleId) this.state.collectPaths(filepaths) @@ -638,8 +624,6 @@ export class Vitest { } async collectFiles(specs: WorkspaceSpec[]) { - await this.initializeDistPath() - const filepaths = specs.map(spec => spec.moduleId) this.state.collectPaths(filepaths) diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts index a22215c852bf..7c1077ee88d5 100644 --- a/packages/vitest/src/node/plugins/index.ts +++ b/packages/vitest/src/node/plugins/index.ts @@ -23,6 +23,7 @@ import { } from './utils' import { VitestOptimizer } from './optimizer' import { NormalizeURLPlugin } from './normalizeURL' +import { VitestCoreResolver } from './vitestResolver' export async function VitestPlugin( options: UserConfig = {}, @@ -253,6 +254,7 @@ export async function VitestPlugin( SsrReplacerPlugin(), ...CSSEnablerPlugin(ctx), CoverageTransform(ctx), + VitestCoreResolver(ctx), options.ui ? await UIPlugin() : null, ...MocksPlugins(), VitestOptimizer(), diff --git a/packages/vitest/src/node/plugins/vitestResolver.ts b/packages/vitest/src/node/plugins/vitestResolver.ts index 7a18d2078b02..6582db943c48 100644 --- a/packages/vitest/src/node/plugins/vitestResolver.ts +++ b/packages/vitest/src/node/plugins/vitestResolver.ts @@ -1,12 +1,14 @@ import type { Plugin } from 'vite' +import { join, resolve } from 'pathe' import type { Vitest } from '../core' +import { distDir } from '../../paths' -export function VitestResolver(ctx: Vitest): Plugin { +export function VitestProjectResolver(ctx: Vitest): Plugin { const plugin: Plugin = { name: 'vitest:resolve-root', enforce: 'pre', async resolveId(id, _, { ssr }) { - if (id === 'vitest' || id.startsWith('@vitest/')) { + if (id === 'vitest' || id.startsWith('@vitest/') || id.startsWith('vitest/')) { // always redirect the request to the root vitest plugin since // it will be the one used to run Vitest const resolved = await ctx.server.pluginContainer.resolveId(id, undefined, { @@ -19,3 +21,21 @@ export function VitestResolver(ctx: Vitest): Plugin { } return plugin } + +export function VitestCoreResolver(ctx: Vitest): Plugin { + return { + name: 'vitest:resolve-core', + enforce: 'pre', + async resolveId(id) { + if (id === 'vitest') { + return resolve(distDir, 'index.js') + } + if (id.startsWith('@vitest/') || id.startsWith('vitest/')) { + // ignore actual importer, we want it to be resolved relative to the root + return this.resolve(id, join(ctx.config.root, 'index.html'), { + skipSelf: true, + }) + } + }, + } +} diff --git a/packages/vitest/src/node/plugins/workspace.ts b/packages/vitest/src/node/plugins/workspace.ts index 768f4ad1445f..1c5ff4878835 100644 --- a/packages/vitest/src/node/plugins/workspace.ts +++ b/packages/vitest/src/node/plugins/workspace.ts @@ -15,7 +15,7 @@ import { hijackVitePluginInject, resolveFsAllow, } from './utils' -import { VitestResolver } from './vitestResolver' +import { VitestProjectResolver } from './vitestResolver' import { VitestOptimizer } from './optimizer' import { NormalizeURLPlugin } from './normalizeURL' @@ -140,7 +140,7 @@ export function WorkspaceVitestPlugin( ...CSSEnablerPlugin(project), CoverageTransform(project.ctx), ...MocksPlugins(), - VitestResolver(project.ctx), + VitestProjectResolver(project.ctx), VitestOptimizer(), NormalizeURLPlugin(), ]