Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131import type { MaybeMockedDeep } from '@vitest/spy'import type { ModuleMockFactoryWithHelper, ModuleMockOptions } from '../types'import type { ModuleMocker } from './mocker'import { createSimpleStackTrace } from '@vitest/utils/helpers'import { parseSingleStack } from '@vitest/utils/source-map'
export interface CompilerHintsOptions { /** * This is the key used to access the globalThis object in the worker. * Unlike `globalThisAccessor` in other APIs, this is not injected into the script. * ```ts * // globalThisKey: '__my_variable__' produces: * globalThis['__my_variable__'] * // globalThisKey: '"__my_variable__"' produces: * globalThis['"__my_variable__"'] // notice double quotes * ``` * @default '__vitest_mocker__' */ globalThisKey?: string}
export interface ModuleMockerCompilerHints { hoisted: <T>(factory: () => T) => T mock: ( path: string | Promise<unknown>, factory?: ModuleMockOptions | ModuleMockFactoryWithHelper, ) => void unmock: (path: string | Promise<unknown>) => void doMock: ( path: string | Promise<unknown>, factory?: ModuleMockOptions | ModuleMockFactoryWithHelper, ) => void doUnmock: (path: string | Promise<unknown>) => void importActual: <T>(path: string) => Promise<T> importMock: <T>(path: string) => Promise<MaybeMockedDeep<T>>}
export function createCompilerHints(options?: CompilerHintsOptions): ModuleMockerCompilerHints { const globalThisAccessor = options?.globalThisKey || '__vitest_mocker__' function _mocker(): ModuleMocker { // @ts-expect-error injected by the plugin return typeof globalThis[globalThisAccessor] !== 'undefined' ? // @ts-expect-error injected by the plugin globalThis[globalThisAccessor] : new Proxy({} as any, { get(_, name) { throw new Error( 'Vitest mocker was not initialized in this environment. ' + `vi.${String(name)}() is forbidden.`, ) }, }) }
return { hoisted<T>(factory: () => T): T { if (typeof factory !== 'function') { throw new TypeError(`vi.hoisted() expects a function, but received a ${typeof factory}`) } return factory() },
mock( path: string | Promise<unknown>, factory?: ModuleMockOptions | ModuleMockFactoryWithHelper, ): void { if (typeof path !== 'string') { throw new TypeError(`vi.mock() expects a string path, but received a ${typeof path}`) } const importer = getImporter('mock') _mocker().queueMock( path, importer, typeof factory === 'function' ? () => factory(() => _mocker().importActual(path, importer)) : factory, ) },
unmock(path: string | Promise<unknown>): void { if (typeof path !== 'string') { throw new TypeError(`vi.unmock() expects a string path, but received a ${typeof path}`) } _mocker().queueUnmock(path, getImporter('unmock')) },
doMock( path: string | Promise<unknown>, factory?: ModuleMockOptions | ModuleMockFactoryWithHelper, ): void { if (typeof path !== 'string') { throw new TypeError(`vi.doMock() expects a string path, but received a ${typeof path}`) } const importer = getImporter('doMock') _mocker().queueMock( path, importer, typeof factory === 'function' ? () => factory(() => _mocker().importActual(path, importer)) : factory, ) },
doUnmock(path: string | Promise<unknown>): void { if (typeof path !== 'string') { throw new TypeError(`vi.doUnmock() expects a string path, but received a ${typeof path}`) } _mocker().queueUnmock(path, getImporter('doUnmock')) },
async importActual<T = unknown>(path: string): Promise<T> { return _mocker().importActual<T>(path, getImporter('importActual')) },
async importMock<T>(path: string): Promise<MaybeMockedDeep<T>> { return _mocker().importMock(path, getImporter('importMock')) }, }}
function getImporter(name: string) { const stackTrace = /* @__PURE__ */ createSimpleStackTrace({ stackTraceLimit: 5 }) const stackArray = stackTrace.split('\n') // if there is no message in a stack trace, use the item - 1 const importerStackIndex = stackArray.findIndex((stack) => { return stack.includes(` at Object.${name}`) || stack.includes(`${name}@`) }) const stack = /* @__PURE__ */ parseSingleStack(stackArray[importerStackIndex + 1]) return stack?.file || ''}