diff --git a/packages/vite-node/src/utils.ts b/packages/vite-node/src/utils.ts index 9140b4986912..aefd48a0ee65 100644 --- a/packages/vite-node/src/utils.ts +++ b/packages/vite-node/src/utils.ts @@ -14,6 +14,22 @@ export function mergeSlashes(str: string) { return str.replace(/\/\//g, '/') } +export function snipBase(path: string, base: string) { + if (!base.endsWith('/')) + base += '/' + + const isAtFS = path.startsWith('/@fs/') + if (isAtFS && !base.startsWith('/@fs/')) + base = base.startsWith('/') ? `/@fs${base}` : `/@fs/${base}` + + if (path.startsWith(base)) { + // Subtract 1 to ensure the result has a leading slash + const snipped = path.slice(base.length - 1) + return isAtFS ? `/@fs${snipped}` : snipped + } + return path +} + 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 d2105de179c3..00f7e0fee5a8 100644 --- a/packages/vitest/src/runtime/mocker.ts +++ b/packages/vitest/src/runtime/mocker.ts @@ -1,7 +1,7 @@ import { existsSync, readdirSync } from 'fs' import { isNodeBuiltin } from 'mlly' import { basename, dirname, join, resolve } from 'pathe' -import { normalizeRequestId, toFilePath } from 'vite-node/utils' +import { normalizeRequestId, snipBase, toFilePath } from 'vite-node/utils' import type { ModuleCacheMap } from 'vite-node/client' import { getAllMockableProperties, getType, getWorkerState, isWindows, mergeSlashes, slash } from '../utils' import { distDir } from '../constants' @@ -142,14 +142,14 @@ export class VitestMocker { } public normalizePath(path: string) { - return normalizeRequestId(path.replace(this.root, ''), this.base).replace(/^\/@fs\//, isWindows ? '' : '/') + return normalizeRequestId(snipBase(path, this.root), this.base).replace(/^\/@fs\//, isWindows ? '' : '/') } public getFsPath(path: string, external: string | null) { if (external) return mergeSlashes(`/@fs/${path}`) - return normalizeRequestId(path.replace(this.root, '')) + return normalizeRequestId(snipBase(path, this.root)) } public resolveMockPath(mockPath: string, external: string | null) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8cebc95f0f46..6883aeca8e93 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -983,14 +983,19 @@ importers: specifiers: '@edge-runtime/vm': 1.1.0-beta.26 '@vitest/test-path-res-target': workspace:* + '@vitest/test-path-resolution-target': workspace:* '@vitest/web-worker': workspace:* vitest: workspace:* devDependencies: '@edge-runtime/vm': 1.1.0-beta.26 '@vitest/test-path-res-target': link:../path-res-target + '@vitest/test-path-resolution-target': link:../path-resolution-target '@vitest/web-worker': link:../../packages/web-worker vitest: link:../../packages/vitest + test/path-resolution-target: + specifiers: {} + test/related: specifiers: execa: ^6.1.0 diff --git a/test/path-resolution-target/.eslintignore b/test/path-resolution-target/.eslintignore new file mode 100644 index 000000000000..af18ca9559d2 --- /dev/null +++ b/test/path-resolution-target/.eslintignore @@ -0,0 +1 @@ +!dist/ diff --git a/test/path-resolution-target/.gitignore b/test/path-resolution-target/.gitignore new file mode 100644 index 000000000000..af18ca9559d2 --- /dev/null +++ b/test/path-resolution-target/.gitignore @@ -0,0 +1 @@ +!dist/ diff --git a/test/path-resolution-target/README.md b/test/path-resolution-target/README.md new file mode 100644 index 000000000000..79839556fa38 --- /dev/null +++ b/test/path-resolution-target/README.md @@ -0,0 +1,2 @@ +This package is here just to be a sibling package to `path-resolution`. It +contains no tests of its own. diff --git a/test/path-resolution-target/dist/index.d.ts b/test/path-resolution-target/dist/index.d.ts new file mode 100644 index 000000000000..c6540bfe64fa --- /dev/null +++ b/test/path-resolution-target/dist/index.d.ts @@ -0,0 +1 @@ +export function add(a: number, b: number): number diff --git a/test/path-resolution-target/dist/index.js b/test/path-resolution-target/dist/index.js new file mode 100644 index 000000000000..7d658310b0d9 --- /dev/null +++ b/test/path-resolution-target/dist/index.js @@ -0,0 +1,3 @@ +export function add(a, b) { + return a + b; +} diff --git a/test/path-resolution-target/package.json b/test/path-resolution-target/package.json new file mode 100644 index 000000000000..8b66a23ae3c1 --- /dev/null +++ b/test/path-resolution-target/package.json @@ -0,0 +1,6 @@ +{ + "name": "@vitest/test-path-resolution-target", + "type": "module", + "private": true, + "main": "./dist/index.js" +} diff --git a/test/path-resolution/package.json b/test/path-resolution/package.json index db64a812ab50..828ae163b712 100644 --- a/test/path-resolution/package.json +++ b/test/path-resolution/package.json @@ -9,6 +9,7 @@ "devDependencies": { "@edge-runtime/vm": "1.1.0-beta.26", "@vitest/test-path-res-target": "workspace:*", + "@vitest/test-path-resolution-target": "workspace:*", "@vitest/web-worker": "workspace:*", "vitest": "workspace:*" } diff --git a/test/path-resolution/test/starts-with.test.ts b/test/path-resolution/test/starts-with.test.ts new file mode 100644 index 000000000000..6f3f1352bb27 --- /dev/null +++ b/test/path-resolution/test/starts-with.test.ts @@ -0,0 +1,17 @@ +import { expect, it, vitest } from 'vitest' + +import { add } from '@vitest/test-path-resolution-target' + +vitest.mock('@vitest/test-path-resolution-target') + +it('should be mocked', () => { + expect(add).toHaveProperty('mock') + expect(add(2, 3)).toBeUndefined() +}) + +it('should import actual', async () => { + const { add } = await vitest.importActual('@vitest/test-path-resolution-target') + + expect(add).not.toHaveProperty('mock') + expect(add(2, 3)).toBe(5) +})