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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104import type { Plugin, ViteDevServer } from 'vite'import type { AutomockPluginOptions } from './automockPlugin'import type { HoistMocksPluginOptions } from './hoistMocksPlugin'import { readFile } from 'node:fs/promises'import { fileURLToPath } from 'node:url'import { dirname, resolve } from 'pathe'import { automockPlugin } from './automockPlugin'import { dynamicImportPlugin } from './dynamicImportPlugin'import { hoistMocksPlugin } from './hoistMocksPlugin'import { interceptorPlugin } from './interceptorPlugin'import { ServerMockResolver } from './resolver'
interface MockerPluginOptions extends AutomockPluginOptions { hoistMocks?: HoistMocksPluginOptions}
// this is an implementation for public usage// vitest doesn't use this plugin directly
export function mockerPlugin(options: MockerPluginOptions = {}): Plugin[] { let server: ViteDevServer const registerPath = resolve(fileURLToPath(new URL('./register.js', import.meta.url))) const distDir = `${dirname(registerPath)}/` return [ { name: 'vitest:mocker:msw', enforce: 'pre', async resolveId(id, importer, options) { if (id !== 'msw/http' || !importer?.startsWith(distDir)) { return } try { return await this.resolve(id, importer, { ...options, skipSelf: true }) } catch { // msw v2 exports `http` from `msw/core/http` return this.resolve('msw/core/http', importer, { ...options, skipSelf: true }) } }, }, { name: 'vitest:mocker:ws-rpc', config(_, { command }) { if (command !== 'serve') { return } return { server: { // don't pre-transform request because they might be mocked at runtime preTransformRequests: false, }, optimizeDeps: { exclude: ['@vitest/mocker/register', '@vitest/mocker/browser'], }, } }, configureServer(server_) { server = server_ const mockResolver = new ServerMockResolver(server) server.ws.on( 'vitest:mocks:resolveId', async ({ id, importer }: { id: string; importer: string }) => { const resolved = await mockResolver.resolveId(id, importer) server.ws.send('vitest:mocks:resolvedId:result', resolved) }, ) server.ws.on( 'vitest:mocks:resolveMock', async ({ id, importer, options }: { id: string; importer: string; options: any }) => { const resolved = await mockResolver.resolveMock(id, importer, options) server.ws.send('vitest:mocks:resolveMock:result', resolved) }, ) server.ws.on('vitest:mocks:invalidate', async ({ ids }: { ids: string[] }) => { mockResolver.invalidate(ids) server.ws.send('vitest:mocks:invalidate:result') }) }, async load(id) { if (id !== registerPath) { return }
if (!server) { // mocker doesn't work during build return 'export {}' }
const content = await readFile(registerPath, 'utf-8') const result = content .replace( /__VITEST_GLOBAL_THIS_ACCESSOR__/g, options.globalThisAccessor ?? '"__vitest_mocker__"', ) .replace('__VITEST_MOCKER_ROOT__', JSON.stringify(server.config.root)) return result }, }, hoistMocksPlugin(options.hoistMocks), interceptorPlugin(options), automockPlugin(options), dynamicImportPlugin(options), ]}