diff --git a/packages/vite-node/src/client.ts b/packages/vite-node/src/client.ts index 80aca993bf32..eb97c6e3dd66 100644 --- a/packages/vite-node/src/client.ts +++ b/packages/vite-node/src/client.ts @@ -4,7 +4,7 @@ import vm from 'vm' import { dirname, extname, isAbsolute, resolve } from 'pathe' import { isNodeBuiltin } from 'mlly' import createDebug from 'debug' -import { isPrimitive, normalizeModuleId, normalizeRequestId, slash, toFilePath } from './utils' +import { isPrimitive, mergeSlashes, normalizeModuleId, normalizeRequestId, slash, toFilePath } from './utils' import type { ModuleCache, ViteNodeRunnerOptions } from './types' const debugExecute = createDebug('vite-node:client:execute') @@ -135,7 +135,7 @@ export class ViteNodeRunner { if (importer && importer.startsWith('mock:')) importer = importer.slice(5) const { id } = await this.options.resolveId(dep, importer) || {} - dep = id && isAbsolute(id) ? `/@fs/${id}` : id || dep + dep = id && isAbsolute(id) ? mergeSlashes(`/@fs/${id}`) : id || dep } return dep diff --git a/packages/vite-node/src/utils.ts b/packages/vite-node/src/utils.ts index aa51574d568c..54fbcc696121 100644 --- a/packages/vite-node/src/utils.ts +++ b/packages/vite-node/src/utils.ts @@ -8,6 +8,10 @@ export function slash(str: string) { return str.replace(/\\/g, '/') } +export function mergeSlashes(str: string) { + return str.replace(/\/\//g, '/') +} + export function normalizeRequestId(id: string, base?: string): string { if (base && id.startsWith(base)) id = `/${id.slice(base.length)}` diff --git a/packages/vitest/src/runtime/mocker.ts b/packages/vitest/src/runtime/mocker.ts index a3daa1ca77ff..b63783aa7453 100644 --- a/packages/vitest/src/runtime/mocker.ts +++ b/packages/vitest/src/runtime/mocker.ts @@ -100,7 +100,7 @@ export class VitestMocker { } public resolveDependency(dep: string) { - return normalizeRequestId(dep).replace(/^\/@fs\//, isWindows ? '' : '/') + return normalizeRequestId(dep.replace(this.root, '')).replace(/^\/@fs\//, isWindows ? '' : '/') } public normalizePath(path: string) { diff --git a/test/core/src/dynamic-import.ts b/test/core/src/dynamic-import.ts new file mode 100644 index 000000000000..c5f7d0f7627e --- /dev/null +++ b/test/core/src/dynamic-import.ts @@ -0,0 +1,4 @@ +export async function dynamicImport(name: string) { + const pkg = await import(name) + return pkg +} diff --git a/test/core/test/mock-internals.test.ts b/test/core/test/mock-internals.test.ts index 85d82e97c0b5..64d50402cb4c 100644 --- a/test/core/test/mock-internals.test.ts +++ b/test/core/test/mock-internals.test.ts @@ -2,6 +2,7 @@ import childProcess, { exec } from 'child_process' import timers from 'timers' import { expect, test, vi } from 'vitest' import { execDefault, execHelloWorld, execImportAll } from '../src/exec' +import { dynamicImport } from '../src/dynamic-import' vi.mock('child_process') vi.mock('timers') // node built in inside __mocks__ @@ -20,3 +21,10 @@ test('node internal is mocked', () => { test('builtin is mocked with __mocks__ folder', () => { expect(timers.clearInterval()).toBe('foo') }) + +test('mocked dynamically imported packages', async () => { + const mod = await dynamicImport('timers') + expect(mod).toHaveProperty('default') + expect(mod.default).toHaveProperty('clearInterval') + expect(mod.default.clearInterval()).toBe('foo') +})