diff --git a/packages/vitest/src/node/pool.ts b/packages/vitest/src/node/pool.ts index 8f6a59fd8385..f48edac4f27e 100644 --- a/packages/vitest/src/node/pool.ts +++ b/packages/vitest/src/node/pool.ts @@ -89,6 +89,9 @@ export function createPool(ctx: Vitest): ProcessPool { const environments = await getSpecificationsEnvironments(specs) const groups = groupSpecs(sorted) + const projectEnvs = new WeakMap>() + const projectExecArgvs = new WeakMap() + for (const group of groups) { if (!group) { continue @@ -114,6 +117,33 @@ export function createPool(ctx: Vitest): ProcessPool { throw new Error(`Cannot find the environment. This is a bug in Vitest.`) } + let env = projectEnvs.get(project) + if (!env) { + env = { + ...process.env, + ...options.env, + ...ctx.config.env, + ...project.config.env, + } + + // env are case-insensitive on Windows, but spawned processes don't support it + if (isWindows) { + for (const name in env) { + env[name.toUpperCase()] = env[name] + } + } + projectEnvs.set(project, env) + } + + let execArgv = projectExecArgvs.get(project) + if (!execArgv) { + execArgv = [ + ...options.execArgv, + ...project.config.execArgv, + ] + projectExecArgvs.set(project, execArgv) + } + taskGroup.push({ context: { pool, @@ -126,8 +156,8 @@ export function createPool(ctx: Vitest): ProcessPool { workerId: workerId++, }, project, - env: { ...options.env, ...project.config.env }, - execArgv: [...options.execArgv, ...project.config.execArgv], + env, + execArgv, worker: pool, isolate: project.config.isolate, memoryLimit: getMemoryLimit(ctx.config, pool) ?? null, @@ -250,18 +280,9 @@ function resolveOptions(ctx: Vitest) { NODE_ENV: process.env.NODE_ENV || 'test', VITEST_MODE: ctx.config.watch ? 'WATCH' : 'RUN', FORCE_TTY: isatty(1) ? 'true' : '', - ...process.env, - ...ctx.config.env, }, } - // env are case-insensitive on Windows, but spawned processes don't support it - if (isWindows) { - for (const name in options.env) { - options.env[name.toUpperCase()] = options.env[name] - } - } - return options } diff --git a/packages/vitest/src/node/pools/types.ts b/packages/vitest/src/node/pools/types.ts index ea805fc86c4f..c32269e393d1 100644 --- a/packages/vitest/src/node/pools/types.ts +++ b/packages/vitest/src/node/pools/types.ts @@ -41,7 +41,15 @@ export interface PoolTask { worker: 'forks' | 'threads' | 'vmForks' | 'vmThreads' | (string & {}) project: TestProject isolate: boolean + /** + * Custom `process.env`. All tasks in the same project will reference the same object, + * so modifying it once will modify it for every task. + */ env: Partial + /** + * Custom `execArgv`. All tasks in the same project will reference the same array, + * so modifying it once will modify it for every task. + */ execArgv: string[] context: ContextRPC memoryLimit: number | null diff --git a/packages/vitest/src/node/pools/workers/vmForksWorker.ts b/packages/vitest/src/node/pools/workers/vmForksWorker.ts index a2e5a6700abf..2cc5c8d2e870 100644 --- a/packages/vitest/src/node/pools/workers/vmForksWorker.ts +++ b/packages/vitest/src/node/pools/workers/vmForksWorker.ts @@ -9,8 +9,7 @@ export class VmForksPoolWorker extends ForksPoolWorker { protected readonly entrypoint: string constructor(options: PoolOptions) { - super(options) - this.execArgv.push('--experimental-vm-modules') + super({ ...options, execArgv: [...options.execArgv, '--experimental-vm-modules'] }) /** Loads {@link file://./../../../runtime/workers/vmForks.ts} */ this.entrypoint = resolve(options.distPath, 'workers/vmForks.js') diff --git a/packages/vitest/src/node/pools/workers/vmThreadsWorker.ts b/packages/vitest/src/node/pools/workers/vmThreadsWorker.ts index cf66dacae36d..779e45b3be67 100644 --- a/packages/vitest/src/node/pools/workers/vmThreadsWorker.ts +++ b/packages/vitest/src/node/pools/workers/vmThreadsWorker.ts @@ -9,8 +9,7 @@ export class VmThreadsPoolWorker extends ThreadsPoolWorker { protected readonly entrypoint: string constructor(options: PoolOptions) { - super(options) - this.execArgv.push('--experimental-vm-modules') + super({ ...options, execArgv: [...options.execArgv, '--experimental-vm-modules'] }) /** Loads {@link file://./../../../runtime/workers/vmThreads.ts} */ this.entrypoint = resolve(options.distPath, 'workers/vmThreads.js') diff --git a/test/global-setup/globalSetup/update-env.ts b/test/global-setup/globalSetup/update-env.ts new file mode 100644 index 000000000000..65a5483a7b9f --- /dev/null +++ b/test/global-setup/globalSetup/update-env.ts @@ -0,0 +1,3 @@ +export default () => { + process.env.NEW_VALUE = 'true' +} diff --git a/test/global-setup/test/setup-files.test.ts b/test/global-setup/test/setup-files.test.ts index 7c0f6b267cf0..6d0ccc2e526b 100644 --- a/test/global-setup/test/setup-files.test.ts +++ b/test/global-setup/test/setup-files.test.ts @@ -11,3 +11,7 @@ test('setup file has been loaded without relative path prefix', () => { const result = loaded expect(result).toBeTruthy() }) + +test('the process.env is injected correctly', () => { + expect(process.env.NEW_VALUE).toBe('true') +}) diff --git a/test/global-setup/vitest.config.ts b/test/global-setup/vitest.config.ts index e330ce975bf8..cf17bb4e408d 100644 --- a/test/global-setup/vitest.config.ts +++ b/test/global-setup/vitest.config.ts @@ -20,6 +20,7 @@ export default defineConfig({ './globalSetup/named-exports.js', './globalSetup/ts-with-imports.ts', './globalSetup/another-vite-instance.ts', + './globalSetup/update-env.ts', ], }, })