diff --git a/docs/config/index.md b/docs/config/index.md index 37ba61e626e6..bf829135dcb6 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -1410,3 +1410,20 @@ This config option affects truncating values in `test.each` titles and inside th Stop test execution when given number of tests have failed. By default Vitest will run all of your test cases even if some of them fail. This may not be desired for CI builds where you are only interested in 100% successful builds and would like to stop test execution as early as possible when test failures occur. The `bail` option can be used to speed up CI runs by preventing it from running more tests when failures have occured. + +### modulePatterns + +- **Type**: `string[]` +- **Default**: `['**/node_modules/**']` + +Glob pattern for file paths that should be treated as modules. Setting this option will override the default, if you wish to still search `**/node_modules/**` for packages include it along with any other options: + +```ts +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + modulePatterns: ['**/node_modules/**', path.resolve('../../packages/**')], + }, +}) +``` diff --git a/packages/vitest/src/defaults.ts b/packages/vitest/src/defaults.ts index f06e14bf4c65..05b24004c2e0 100644 --- a/packages/vitest/src/defaults.ts +++ b/packages/vitest/src/defaults.ts @@ -94,6 +94,7 @@ const config = { exclude: defaultExclude, }, slowTestThreshold: 300, + modulePatterns: ['**/node_modules/**'], } export const configDefaults: Required> = Object.freeze(config) diff --git a/packages/vitest/src/runtime/execute.ts b/packages/vitest/src/runtime/execute.ts index 7fb8f2622cad..457ec995ec7b 100644 --- a/packages/vitest/src/runtime/execute.ts +++ b/packages/vitest/src/runtime/execute.ts @@ -13,6 +13,7 @@ import { rpc } from './rpc' export interface ExecuteOptions extends ViteNodeRunnerOptions { mockMap: MockMap + modulePatterns: string[] } export async function createVitestExecutor(options: ExecuteOptions) { @@ -70,6 +71,7 @@ export async function startViteNode(ctx: ContextRPC) { moduleCache, mockMap, interopDefault: config.deps.interopDefault, + modulePatterns: config.modulePatterns, root: config.root, base: config.base, }) diff --git a/packages/vitest/src/runtime/mocker.ts b/packages/vitest/src/runtime/mocker.ts index a3f617113b50..20d3031befee 100644 --- a/packages/vitest/src/runtime/mocker.ts +++ b/packages/vitest/src/runtime/mocker.ts @@ -2,6 +2,7 @@ import { existsSync, readdirSync } from 'node:fs' import { basename, dirname, extname, isAbsolute, join, resolve } from 'pathe' import { getColors, getType } from '@vitest/utils' import { isNodeBuiltin } from 'vite-node/utils' +import mm from 'micromatch' import { getWorkerState } from '../utils/global' import { getAllMockableProperties } from '../utils/base' import { spyOn } from '../integrations/spy' @@ -58,6 +59,10 @@ export class VitestMocker { return this.executor.moduleCache } + private get modulePatterns() { + return this.executor.options.modulePatterns + } + private deleteCachedItem(id: string) { const mockId = this.getMockPath(id) if (this.moduleCache.has(mockId)) @@ -83,7 +88,7 @@ export class VitestMocker { const [id, fsPath] = await this.executor.resolveUrl(rawId, importer) // external is node_module or unresolved module // for example, some people mock "vscode" and don't have it installed - const external = (!isAbsolute(fsPath) || fsPath.includes('/node_modules/')) ? rawId : null + const external = (!isAbsolute(fsPath) || mm.isMatch(fsPath, this.modulePatterns, { dot: true })) ? rawId : null // { dot: true } is needed to match dotfolder like .pnpm return { id, diff --git a/packages/vitest/src/types/config.ts b/packages/vitest/src/types/config.ts index 0956b38e8599..e7e4cc6290b9 100644 --- a/packages/vitest/src/types/config.ts +++ b/packages/vitest/src/types/config.ts @@ -580,6 +580,13 @@ export interface InlineConfig { * Stop test execution when given number of tests have failed. */ bail?: number + + /** + * Glob pattern for file paths that should be treated as modules. + * + * @default ['**\/node_modules\/**'] + */ + modulePatterns?: string[] } export interface TypecheckConfig {