vitest icon indicating copy to clipboard operation
vitest copied to clipboard

`define` config fails for constants like `process.env.FOO`, but only if in both browser mode and a project

Open dumbmatter opened this issue 3 months ago • 3 comments

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

dumbmatter avatar Oct 31 '25 03:10 dumbmatter

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,
          },
        },
      },

dumbmatter avatar Oct 31 '25 03:10 dumbmatter

Seems to be a similar issue for import.meta.env.FOO in define, even without a project, when using browser mode.

SomaH123 avatar Nov 04 '25 09:11 SomaH123

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.

hi-ogawa avatar Dec 12 '25 08:12 hi-ogawa