diff --git a/docs/advanced/runner.md b/docs/advanced/runner.md index 734b279d9042..f6bcf63275f4 100644 --- a/docs/advanced/runner.md +++ b/docs/advanced/runner.md @@ -73,7 +73,7 @@ export interface VitestRunner { */ extendTestContext?(context: TestContext): TestContext /** - * Called, when files are imported. Can be called in two situations: when collecting tests and when importing setup files. + * Called, when certain files are imported. Can be called in two situations: when collecting tests and when importing setup files. */ importFile(filepath: string, source: VitestRunnerImportSource): unknown /** @@ -86,7 +86,9 @@ export interface VitestRunner { When initiating this class, Vitest passes down Vitest config, - you should expose it as a `config` property. ::: warning -`importFile` method in your custom runner must be inlined in `deps.inline` config option, if you call Node `import` inside. +Vitest also injects an instance of `ViteNodeRunner` as `__vitest_executor` property. You can use it to process files in `importFile` method (this is default behavior of `TestRunner`` and `BenchmarkRunner`). + +`ViteNodeRunner` exposes `executeId` method, which is used to import test files in a Vite-friendly environment. Meaning, it will resolve imports and transform file content at runtime so that Node can understand it. ::: ::: tip diff --git a/packages/vitest/src/node/config.ts b/packages/vitest/src/node/config.ts index 5b67b53511df..a2f2cf12c333 100644 --- a/packages/vitest/src/node/config.ts +++ b/packages/vitest/src/node/config.ts @@ -17,12 +17,6 @@ const extraInlineDeps = [ /^(?!.*(?:node_modules)).*\.cjs\.js$/, // Vite client /vite\w*\/dist\/client\/env.mjs/, - // Vitest - /\/vitest\/dist\/runners\.js/, - // yarn's .store folder - /vitest-virtual-\w+\/dist\/runners\.js/, - // cnpm - /@vitest\/dist\/runners\.js/, // Nuxt '@nuxt/test-utils', ] diff --git a/packages/vitest/src/runtime/entry.ts b/packages/vitest/src/runtime/entry.ts index 2b129796b926..e36336335b00 100644 --- a/packages/vitest/src/runtime/entry.ts +++ b/packages/vitest/src/runtime/entry.ts @@ -13,6 +13,8 @@ import { setupGlobalEnv, withEnv } from './setup.node' import { rpc } from './rpc' import type { VitestExecutor } from './execute' +const runnersFile = resolve(distDir, 'runners.js') + function groupBy(collection: T[], iteratee: (item: T) => K) { return collection.reduce((acc, item) => { const key = iteratee(item) @@ -24,7 +26,7 @@ function groupBy(collection: T[], iterate async function getTestRunnerConstructor(config: ResolvedConfig, executor: VitestExecutor): Promise { if (!config.runner) { - const { VitestTestRunner, NodeBenchmarkRunner } = await executor.executeFile(resolve(distDir, 'runners.js')) + const { VitestTestRunner, NodeBenchmarkRunner } = await executor.executeFile(runnersFile) return (config.mode === 'test' ? VitestTestRunner : NodeBenchmarkRunner) as VitestRunnerConstructor } const mod = await executor.executeId(config.runner) @@ -37,6 +39,13 @@ async function getTestRunner(config: ResolvedConfig, executor: VitestExecutor): const TestRunner = await getTestRunnerConstructor(config, executor) const testRunner = new TestRunner(config) + // inject private executor to every runner + Object.defineProperty(testRunner, '__vitest_executor', { + value: executor, + enumerable: false, + configurable: false, + }) + if (!testRunner.config) testRunner.config = config diff --git a/packages/vitest/src/runtime/runners/benchmark.ts b/packages/vitest/src/runtime/runners/benchmark.ts index 9dfe2a8d74af..8166c166424f 100644 --- a/packages/vitest/src/runtime/runners/benchmark.ts +++ b/packages/vitest/src/runtime/runners/benchmark.ts @@ -5,6 +5,7 @@ import { getBenchFn, getBenchOptions } from '../benchmark' import { getWorkerState } from '../../utils' import type { BenchTask, Benchmark, BenchmarkResult } from '../../types/benchmark' import type { ResolvedConfig } from '../../types/config' +import type { VitestExecutor } from '../execute' async function importTinybench() { if (!globalThis.EventTarget) @@ -121,12 +122,14 @@ async function runBenchmarkSuite(suite: Suite, runner: VitestRunner) { } export class NodeBenchmarkRunner implements VitestRunner { + private __vitest_executor!: VitestExecutor + constructor(public config: ResolvedConfig) {} importFile(filepath: string, source: VitestRunnerImportSource): unknown { if (source === 'setup') getWorkerState().moduleCache.delete(filepath) - return import(filepath) + return this.__vitest_executor.executeId(filepath) } async runSuite(suite: Suite): Promise { diff --git a/packages/vitest/src/runtime/runners/test.ts b/packages/vitest/src/runtime/runners/test.ts index ca41f1f45970..628fb545ebe8 100644 --- a/packages/vitest/src/runtime/runners/test.ts +++ b/packages/vitest/src/runtime/runners/test.ts @@ -5,17 +5,19 @@ import { vi } from '../../integrations/vi' import { getFullName, getWorkerState } from '../../utils' import { createExpect } from '../../integrations/chai/index' import type { ResolvedConfig } from '../../types/config' +import type { VitestExecutor } from '../execute' export class VitestTestRunner implements VitestRunner { private snapshotClient = getSnapshotClient() private workerState = getWorkerState() + private __vitest_executor!: VitestExecutor constructor(public config: ResolvedConfig) {} importFile(filepath: string, source: VitestRunnerImportSource): unknown { if (source === 'setup') this.workerState.moduleCache.delete(filepath) - return import(filepath) + return this.__vitest_executor.executeId(filepath) } onBeforeRun() {