From 135030abc91b20989946cb7ecef716b1665c7ecf Mon Sep 17 00:00:00 2001 From: Vladimir Date: Sun, 3 Jul 2022 15:45:31 +0300 Subject: [PATCH] fix: mocking works with base url (#1581) * fix: mocking works with base url * refactor: removed not needed code --- packages/vitest/src/runtime/execute.ts | 12 +---- packages/vitest/src/runtime/mocker.ts | 63 +++++++++--------------- pnpm-lock.yaml | 6 +++ test/base/package.json | 11 +++++ test/base/src/index.ts | 1 + test/base/test/mocking-with-base.spec.ts | 10 ++++ test/base/vitest.config.ts | 5 ++ 7 files changed, 58 insertions(+), 50 deletions(-) create mode 100644 test/base/package.json create mode 100644 test/base/src/index.ts create mode 100644 test/base/test/mocking-with-base.spec.ts create mode 100644 test/base/vitest.config.ts diff --git a/packages/vitest/src/runtime/execute.ts b/packages/vitest/src/runtime/execute.ts index 30480ceb56db..5c99bafb9ab8 100644 --- a/packages/vitest/src/runtime/execute.ts +++ b/packages/vitest/src/runtime/execute.ts @@ -1,5 +1,5 @@ import { ViteNodeRunner } from 'vite-node/client' -import type { ModuleCache, ViteNodeRunnerOptions } from 'vite-node' +import type { ViteNodeRunnerOptions } from 'vite-node' import { normalizePath } from 'vite' import type { MockMap } from '../types/mocker' import { getWorkerState } from '../utils' @@ -23,23 +23,15 @@ export async function executeInViteNode(options: ExecuteOptions & { files: strin } export class VitestRunner extends ViteNodeRunner { - mocker: VitestMocker - entries = new Set() - constructor(public options: ExecuteOptions) { super(options) - this.mocker = new VitestMocker(options, this.moduleCache) } prepareContext(context: Record) { const request = context.__vite_ssr_import__ const resolveId = context.__vitest_resolve_id__ - const mocker = this.mocker.withRequest(request) - - mocker.on('mocked', (dep: string, module: Partial) => { - this.moduleCache.set(dep, module) - }) + const mocker = new VitestMocker(this.options, this.moduleCache, request) const workerState = getWorkerState() diff --git a/packages/vitest/src/runtime/mocker.ts b/packages/vitest/src/runtime/mocker.ts index 17a10ea051ef..7a062a3b6414 100644 --- a/packages/vitest/src/runtime/mocker.ts +++ b/packages/vitest/src/runtime/mocker.ts @@ -8,8 +8,6 @@ import { distDir } from '../constants' import type { PendingSuiteMock } from '../types/mocker' import type { ExecuteOptions } from './execute' -type Callback = (...args: any[]) => unknown - interface ViteRunnerRequest { (dep: string): any callstack: string[] @@ -19,31 +17,22 @@ export class VitestMocker { private static pendingIds: PendingSuiteMock[] = [] private static spyModule?: typeof import('../integrations/spy') - private request!: ViteRunnerRequest - - private root: string - private callbacks: Record unknown)[]> = {} - constructor( public options: ExecuteOptions, private moduleCache: ModuleCacheMap, - request?: ViteRunnerRequest, - ) { - this.root = this.options.root - this.request = request! - } + private request: ViteRunnerRequest, + ) {} - get mockMap() { - return this.options.mockMap + private get root() { + return this.options.root } - public on(event: string, cb: Callback) { - this.callbacks[event] ??= [] - this.callbacks[event].push(cb) + private get base() { + return this.options.base } - private emit(event: string, ...args: any[]) { - (this.callbacks[event] ?? []).forEach(fn => fn(...args)) + private get mockMap() { + return this.options.mockMap } public getSuiteFilepath(): string { @@ -91,20 +80,16 @@ export class VitestMocker { if (cached) return cached const exports = await mock() - this.emit('mocked', cacheName, { exports }) + this.moduleCache.set(cacheName, { exports }) return exports } public getDependencyMock(dep: string) { - return this.getMocks()[this.resolveDependency(dep)] - } - - public resolveDependency(dep: string) { - return normalizeRequestId(dep.replace(this.root, '')).replace(/^\/@fs\//, isWindows ? '' : '/') + return this.getMocks()[this.normalizePath(dep)] } public normalizePath(path: string) { - return normalizeRequestId(path.replace(this.root, '')).replace(/^\/@fs\//, isWindows ? '' : '/') + return normalizeRequestId(path.replace(this.root, ''), this.base).replace(/^\/@fs\//, isWindows ? '' : '/') } public getFsPath(path: string, external: string | null) { @@ -183,22 +168,22 @@ export class VitestMocker { public unmockPath(path: string) { const suitefile = this.getSuiteFilepath() - const fsPath = this.normalizePath(path) + const id = this.normalizePath(path) const mock = this.mockMap.get(suitefile) - if (mock?.[fsPath]) - delete mock[fsPath] + if (mock?.[id]) + delete mock[id] } public mockPath(path: string, external: string | null, factory?: () => any) { const suitefile = this.getSuiteFilepath() + const id = this.normalizePath(path) - const fsPath = this.normalizePath(path) + const mocks = this.mockMap.get(suitefile) || {} - if (!this.mockMap.has(suitefile)) - this.mockMap.set(suitefile, {}) + mocks[id] = factory || this.resolveMockPath(path, external) - this.mockMap.get(suitefile)![fsPath] = factory || this.resolveMockPath(path, external) + this.mockMap.set(suitefile, mocks) } public async importActual(id: string, importer: string): Promise { @@ -234,8 +219,10 @@ export class VitestMocker { } public async requestWithMock(dep: string) { - await this.ensureSpy() - await this.resolveMocks() + await Promise.all([ + this.ensureSpy(), + this.resolveMocks(), + ]) const mock = this.getDependencyMock(dep) @@ -249,7 +236,7 @@ export class VitestMocker { const cacheKey = toFilePath(dep, this.root) const mod = this.moduleCache.get(cacheKey)?.exports || await this.request(dep) const exports = this.mockValue(mod) - this.emit('mocked', cacheName, { exports }) + this.moduleCache.set(cacheName, { exports }) return exports } if (typeof mock === 'function' && !callstack.includes(`mock:${dep}`)) { @@ -271,8 +258,4 @@ export class VitestMocker { public queueUnmock(id: string, importer: string) { VitestMocker.pendingIds.push({ type: 'unmock', id, importer }) } - - public withRequest(request: ViteRunnerRequest) { - return new VitestMocker(this.options, this.moduleCache, request) - } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 610cf7a2b2b6..4a84342f3a3b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -768,6 +768,12 @@ importers: devDependencies: rollup: 2.75.7 + test/base: + specifiers: + vitest: workspace:* + devDependencies: + vitest: link:../../packages/vitest + test/cache: specifiers: vitest: workspace:* diff --git a/test/base/package.json b/test/base/package.json new file mode 100644 index 000000000000..c0eb91451bb6 --- /dev/null +++ b/test/base/package.json @@ -0,0 +1,11 @@ +{ + "name": "@vitest/test-base", + "private": true, + "scripts": { + "test": "vitest", + "coverage": "vitest run --coverage" + }, + "devDependencies": { + "vitest": "workspace:*" + } +} diff --git a/test/base/src/index.ts b/test/base/src/index.ts new file mode 100644 index 000000000000..cb356468240d --- /dev/null +++ b/test/base/src/index.ts @@ -0,0 +1 @@ +export const foo = 'foo' diff --git a/test/base/test/mocking-with-base.spec.ts b/test/base/test/mocking-with-base.spec.ts new file mode 100644 index 000000000000..4202ebccb5d8 --- /dev/null +++ b/test/base/test/mocking-with-base.spec.ts @@ -0,0 +1,10 @@ +import { expect, test, vi } from 'vitest' +import { foo } from '../src' + +vi.mock('../src', () => ({ + foo: 'baz', +})) + +test('module is mocked', () => { + expect(foo).toBe('baz') +}) diff --git a/test/base/vitest.config.ts b/test/base/vitest.config.ts new file mode 100644 index 000000000000..999c4a2e687c --- /dev/null +++ b/test/base/vitest.config.ts @@ -0,0 +1,5 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + base: '/some/base/url', +})