Skip to content

Commit

Permalink
fix: mocking works with base url (#1581)
Browse files Browse the repository at this point in the history
* fix: mocking works with base url

* refactor: removed not needed code
  • Loading branch information
sheremet-va committed Jul 3, 2022
1 parent 9c60757 commit 135030a
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 50 deletions.
12 changes: 2 additions & 10 deletions 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'
Expand All @@ -23,23 +23,15 @@ export async function executeInViteNode(options: ExecuteOptions & { files: strin
}

export class VitestRunner extends ViteNodeRunner {
mocker: VitestMocker
entries = new Set<string>()

constructor(public options: ExecuteOptions) {
super(options)
this.mocker = new VitestMocker(options, this.moduleCache)
}

prepareContext(context: Record<string, any>) {
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<ModuleCache>) => {
this.moduleCache.set(dep, module)
})
const mocker = new VitestMocker(this.options, this.moduleCache, request)

const workerState = getWorkerState()

Expand Down
63 changes: 23 additions & 40 deletions packages/vitest/src/runtime/mocker.ts
Expand Up @@ -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[]
Expand All @@ -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<string, ((...args: any[]) => 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 {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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<T>(id: string, importer: string): Promise<T> {
Expand Down Expand Up @@ -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)

Expand All @@ -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}`)) {
Expand All @@ -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)
}
}
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions test/base/package.json
@@ -0,0 +1,11 @@
{
"name": "@vitest/test-base",
"private": true,
"scripts": {
"test": "vitest",
"coverage": "vitest run --coverage"
},
"devDependencies": {
"vitest": "workspace:*"
}
}
1 change: 1 addition & 0 deletions test/base/src/index.ts
@@ -0,0 +1 @@
export const foo = 'foo'
10 changes: 10 additions & 0 deletions 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')
})
5 changes: 5 additions & 0 deletions test/base/vitest.config.ts
@@ -0,0 +1,5 @@
import { defineConfig } from 'vitest/config'

export default defineConfig({
base: '/some/base/url',
})

0 comments on commit 135030a

Please sign in to comment.