`define` config fails for constants like `process.env.FOO`, but only if in both browser mode and a project
Describe the bug
define in the vitest config works.
It also works in browser mode.
It also works in a project.
It even works in a project that uses browser mode... unless the constant is named something like process.env.FOO. In the case where you have all 3 of those things (project, browser mode, define for a constant named process.env.FOO) it fails.
I know that sounds crazy, but I have a minimal reproduction!
Reproduction
https://github.com/dumbmatter/vitest-define-bug
Everything below is in that repo, ready to easily run, I'm just copying it here so the bug report is self contained.
This is the config causing trouble:
import { defineConfig } from "vitest/config";
import { playwright } from "@vitest/browser-playwright";
export default defineConfig({
test: {
projects: [
{
define: {
"process.env.FOO": JSON.stringify("BAR"),
},
test: {
name: "node",
include: ["src/test.ts"],
},
},
{
define: {
"process.env.FOO": JSON.stringify("BAR"),
},
test: {
name: "browser",
include: ["src/test.ts"],
browser: {
enabled: true,
headless: true,
provider: playwright(),
instances: [{ browser: "chromium" }],
screenshotFailures: false,
},
},
},
{
define: {
"process.FOO.FOO": JSON.stringify("BAR"),
},
test: {
name: "browser2",
include: ["src/test2.ts"],
browser: {
enabled: true,
headless: true,
provider: playwright(),
instances: [{ browser: "chromium" }],
screenshotFailures: false,
},
},
},
],
},
});
And these are the test files:
src/test.ts:
import { expect, test } from "vitest";
test("process.env.FOO", () => {
expect(process.env.FOO).toBe("BAR");
});
src/test2.ts:
import { expect, test } from "vitest";
test("process.FOO.FOO", () => {
expect(process.FOO.FOO).toBe("BAR");
});
I think all those tests should pass, but instead the "browser" test fails:
FAIL browser (chromium) src/test.ts > process.env.FOO
ReferenceError: process is not defined
❯ src/test.ts:4:9
2|
3| test('process.env.FOO', () => {
4| expect(process.env.FOO).toBe("BAR")
| ^
5| })
If I take that project and move it to its own config file:
import { playwright } from "@vitest/browser-playwright";
import { defineConfig } from "vitest/config";
export default defineConfig({
define: {
"process.env.FOO": JSON.stringify("BAR"),
},
test: {
name: "browser",
include: ["src/test.ts"],
browser: {
enabled: true,
headless: true,
provider: playwright(),
instances: [{ browser: "chromium" }],
screenshotFailures: false,
},
},
});
Then the test passes.
System Info
System:
OS: Linux 6.8 Ubuntu 24.04.3 LTS 24.04.3 LTS (Noble Numbat)
CPU: (8) x64 Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
Memory: 12.57 GB / 31.13 GB
Container: Yes
Shell: 5.2.21 - /bin/bash
Binaries:
Node: 24.10.0 - /usr/bin/node
npm: 11.6.1 - /usr/bin/npm
pnpm: 10.20.0 - /home/user/.local/share/pnpm/pnpm
Browsers:
Chrome: 141.0.7390.107
Firefox: 144.0.2
Firefox Developer Edition: 144.0.2
npmPackages:
@vitest/browser-playwright: ^4.0.5 => 4.0.5
vitest: ^4.0.5 => 4.0.5
Used Package Manager
pnpm
Validations
- [x] Follow our Code of Conduct
- [x] Read the Contributing Guidelines.
- [x] Read the docs.
- [x] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [x] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- [x] The provided reproduction is a minimal reproducible example of the bug.
Also same error happens if you use test.env rather than define, like here the first one works and the second one doesn't, with the same error message as in the initial bug report:
{
test: {
name: "node",
env: {
FOO: "BAR",
},
include: ["src/test.ts"],
},
},
{
test: {
name: "browser",
env: {
FOO: "BAR",
},
include: ["src/test.ts"],
browser: {
enabled: true,
headless: true,
provider: playwright(),
instances: [{ browser: "chromium" }],
screenshotFailures: false,
},
},
},
Seems to be a similar issue for import.meta.env.FOO in define, even without a project, when using browser mode.
There's a special handling for process.env.xxx and import.meta.env.xxx and this is preventing browser mode from picking up defines.
https://github.com/vitest-dev/vitest/blob/6a024c501003d923b557eaff6b463f2be79d949d/packages/vitest/src/node/plugins/utils.ts#L85-L94
This doesn't happen where browser mode project has config file associated with it as it directly picks up defines from config file. This happens when browser mode project is defined inside inline projects: [{ ...}] array.