[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

fix: mock node builtins (#454)

authored by

Vladimir and committed by
GitHub
(Jan 6, 2022, 11:29 PM +0800) fdfffaeb e6da42bc

+41 -23
+3
test/core/__mocks__/timers.ts
··· 1 + export default { 2 + clearInterval: () => 'foo', 3 + }
+6 -1
test/core/src/exec.ts
··· 1 1 /* eslint-disable import/no-duplicates */ 2 2 import { exec } from 'child_process' 3 3 import * as child_process from 'child_process' 4 + import defaultProcess from 'child_process' 4 5 5 6 export function execHelloWorld() { 6 7 exec('hello world') 7 8 } 8 9 10 + export function execImportAll() { 11 + child_process.exec('import all') 12 + } 13 + 9 14 export function execDefault() { 10 - child_process.exec('default') 15 + defaultProcess.exec('default') 11 16 }
+13 -8
test/core/test/mock-internals.test.ts
··· 1 - import { exec } from 'child_process' 1 + import childProcess, { exec } from 'child_process' 2 + import timers from 'timers' 2 3 import { expect, test, vi } from 'vitest' 3 - import { execDefault, execHelloWorld } from '../src/exec' 4 + import { execDefault, execHelloWorld, execImportAll } from '../src/exec' 4 5 5 - vi.mock('child_process', () => { 6 - return { 7 - exec: vi.fn(), 8 - } 9 - }) 6 + vi.mock('child_process') 7 + vi.mock('timers') // node built in inside __mocks__ 10 8 11 9 test('node internal is mocked', () => { 12 10 execHelloWorld() 13 11 expect(exec).toHaveBeenCalledWith('hello world') 14 12 13 + execImportAll() 14 + expect(exec).toHaveBeenCalledWith('import all') 15 + 15 16 execDefault() 16 - expect(exec).toHaveBeenCalledWith('default') 17 + expect(childProcess.exec).toHaveBeenCalledWith('default') 18 + }) 19 + 20 + test('builtin is mocked with __mocks__ folder', () => { 21 + expect(timers.clearInterval()).toBe('foo') 17 22 })
+14 -10
packages/vitest/src/node/execute.ts
··· 100 100 if (canMock) { 101 101 const mocks = mockMap[suite || ''] || {} 102 102 const mock = mocks[resolveDependency(dep)] 103 + if (mock === null) { 104 + const mockedKey = `${dep}__mock` 105 + const cache = moduleCache.get(mockedKey) 106 + if (cache?.exports) 107 + return cache.exports 108 + const cacheKey = toFilePath(dep, root) 109 + const mod = moduleCache.get(cacheKey)?.exports || await cachedRequest(dep, callstack) 110 + const exports = mockObject(mod) 111 + setCache(mockedKey, { exports }) 112 + return exports 113 + } 103 114 if (typeof mock === 'function') 104 115 return callFunctionMock(dep, mock) 105 116 if (typeof mock === 'string') ··· 142 153 return request(getActualPath(path, nmName), false) 143 154 } 144 155 145 - const importMock = async(path: string, nmName: string) => { 156 + async function importMock(path: string, nmName: string): Promise<any> { 146 157 if (!suite) 147 158 throw new Error('You can import mock only inside of a running test') 148 159 149 160 const mock = (mockMap[suite] || {})[path] || resolveMockPath(path, root, nmName) 150 161 if (mock === null) { 151 162 const fsPath = getActualPath(path, nmName) 152 - const exports = mockObject(await request(fsPath, false)) 153 - setCache(fsPath, { exports }) 154 - return exports 163 + const mod = await request(fsPath, false) 164 + return mockObject(mod) 155 165 } 156 166 if (typeof mock === 'function') 157 167 return callFunctionMock(path, mock) ··· 188 198 lineOffset: 0, 189 199 }) 190 200 await fn(...Object.values(context)) 191 - 192 - const mocks = suite ? mockMap[suite] : null 193 - if (mocks) { 194 - if (mocks[id] === null) 195 - exportAll(exports, mockObject(exports)) 196 - } 197 201 198 202 return exports 199 203 }
+5 -4
packages/vitest/src/node/mocker.ts
··· 1 1 import { existsSync, readdirSync } from 'fs' 2 + import { isNodeBuiltin } from 'mlly' 2 3 import { basename, dirname, join, resolve } from 'pathe' 3 4 import { spies, spyOn } from '../integrations/jest-mock' 4 5 import { mergeSlashes } from '../utils' ··· 9 10 } 10 11 } 11 12 12 - function resolveMockPath(mockPath: string, root: string, nmName: string | null) { 13 + function resolveMockPath(mockPath: string, root: string, external: string | null) { 13 14 // it's a node_module alias 14 15 // all mocks should be inside <root>/__mocks__ 15 - if (nmName) { 16 - const mockDirname = dirname(nmName) // for nested mocks: @vueuse/integration/useJwt 17 - const baseFilename = basename(nmName) 16 + if (external || isNodeBuiltin(mockPath)) { 17 + const mockDirname = dirname(external || mockPath) // for nested mocks: @vueuse/integration/useJwt 18 + const baseFilename = basename(external || mockPath) 18 19 const mockFolder = resolve(root, '__mocks__', mockDirname) 19 20 20 21 if (!existsSync(mockFolder)) return null