vitest-dev / vscode

VS Code extension for Vitest
https://vitest.dev/vscode
MIT License
736 stars 83 forks source link

Environment variables declared in vitest.config.ts undefined when using the extension #326

Closed sambarfoot closed 4 months ago

sambarfoot commented 5 months ago

Describe the bug

If env variables are defined in the vitest config files, they are undefined when using the extension

Reproduction

vitest.workspace.ts

export default [
  'packages/*'
]

vitest.config.mts

import { defineProject } from 'vitest/config'
import tsconfigPaths from 'vite-tsconfig-paths';

export default defineProject({
  plugins: [tsconfigPaths()],
  test: {
    env: {
      DATABASE_URL: "http://localhost:3000",
    }
  }
});
test('should successfully login and set access token', () => {
    // Act
    const database_url = process.env.DATABASE_URL!;
}

System Info

System:
    OS: Linux 6.6 Debian GNU/Linux 11 (bullseye) 11 (bullseye)
    CPU: (10) arm64 unknown
    Memory: 4.69 GB / 7.75 GB
    Container: Yes
    Shell: 5.1.4 - /bin/bash
  Binaries:
    Node: 20.12.0 - /usr/local/share/nvm/versions/node/v20.12.0/bin/node
    Yarn: 1.22.19 - /usr/bin/yarn
    npm: 10.5.0 - /usr/local/share/nvm/versions/node/v20.12.0/bin/npm
    pnpm: 8.15.5 - /usr/local/share/nvm/versions/node/v20.12.0/bin/pnpm

Used Package Manager

npm

Validations

hi-ogawa commented 4 months ago

This might be a same issue as this:

@sambarfoot Could you check if it works from vitest cli?

sambarfoot commented 4 months ago

I did some testing this morning and it didn't work from the root of the project but it does from within the packages.

You can test using the example from vitest#5016 - https://stackblitz.com/edit/github-2srz39?file=packages%2Flib1%2Fvite.config.ts

~/projects/github-2srz39/packages/lib1
❯ npx vitest --run

 RUN  v1.4.0 /home/projects/github-2srz39/packages/lib1

 ✓ test/double.test.ts (3)
   ✓ double
   ✓ env
   ✓ define

 Test Files  1 passed (1)
      Tests  3 passed (3)
   Start at  07:15:55
   Duration  1.40s (transform 41ms, setup 0ms, collect 25ms, tests 2ms, environment 0ms, prepare 163ms)
~/projects/github-2srz39
❯ npx vitest --run

 RUN  v1.4.0 /home/projects/github-2srz39

 ✓ |lib2| test/square.test.ts (2)
 ❯ |lib1| test/double.test.ts (3)
   ✓ double
   × env
   ✓ define
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL  |lib1| test/double.test.ts > env
AssertionError: expected undefined to be 'hello' // Object.is equality

- Expected: 
"hello"

+ Received: 
undefined

 ❯ eval test/double.test.ts:9:35
      7| test('env', () => {
      8|   // @ts-ignore
      9|   expect(process.env['SOME_ENV']).toBe('hello');
       |                                   ^
     10| });
     11| 

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯

 Test Files  1 failed | 1 passed (2)
      Tests  1 failed | 4 passed (5)
   Start at  07:21:30
   Duration  1.32s (transform 28ms, setup 0ms, collect 29ms, tests 7ms, environment 0ms, prepare 311ms)
hi-ogawa commented 4 months ago

it didn't work from the root of the project but it does from within the packages.

Thanks for checking. Yeah, that's the same behavior as https://github.com/vitest-dev/vitest/issues/5016.

For now, the workaround I can suggest is to use setupFiles to setup your own process.env.DATABASE_URL instead of using test.env config. https://vitest.dev/config/#setupfiles

Or if you don't need isolate environment variables for each project, then you could directly assign process.env somewhere and that'll be probably available from you test files:

import { defineProject } from 'vitest/config'
import tsconfigPaths from 'vite-tsconfig-paths';

process.env.DATABASE_URL = "http://localhost:3000"

export default defineProject({
  plugins: [tsconfigPaths()],
});
1111mp commented 4 months ago

@hi-ogawa Setting environment variables via setupFiles does not seem to work. Currently, I can pass the test using vitest cli in this way, but vitest vscode will report an error: Error: Invalid environment variables.

vitest.config.mts:

/// <reference types="vitest" />

import { resolve } from "path";
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  test: {
    alias: {
      "@": resolve(__dirname, "./src"),
    },
    watch: false,
    environment: "jsdom",
    reporters: ["verbose"],
    setupFiles: ["./vitest-setup.mts"],
  },
});

vitest-setup.mts:

import "@testing-library/jest-dom/vitest";
import { loadEnvConfig } from "@next/env";

// Because I use nextjs, this api can be used to load ".env" file
loadEnvConfig(process.cwd());

When run pnpm test, can work normally:

Screenshot 2024-04-07 at 14 49 31

But in the vitest vscode plug-in, an error will be reported:

Screenshot 2024-04-07 at 14 51 36

Did I miss something?

System Info

System:
    OS: macOS Sonoma 14.4.1 (23E224)
    CPU: arm64 Apple M1 max
    Memory: 32GB
  Binaries:
    Node: v20.12.0
    pnpm: v8.15.6

vitest version: 1.4.0

Vitest vscode extension version:

Screenshot 2024-04-07 at 14 56 50

Vscode info:

  Version: 1.88.0 (Universal)
  Commit: 5c3e652f63e798a5ac2f31ffd0d863669328dc4c
  Date: 2024-04-03T13:28:18.899Z
  Electron: 28.2.8
  ElectronBuildId: 27744544
  Chromium: 120.0.6099.291
  Node.js: 18.18.2
  V8: 12.0.267.19-electron.0
  OS: Darwin arm64 23.4.0
hi-ogawa commented 4 months ago

@1111mp Please provide a reproduction if you're having a problem with setupFiles and want to solve it. But note that, setupFiles based workaround will be irrelevant from the next Vitest release.

Setting environment variables via setupFiles does not seem to work. Currently, I can pass the test using vitest cli in this way

If using vitest cli, it would work even without setupFiles, so this information doesn't necessary help.

From a quick look, it looks like you might need to pass forceReload: true around here to actually update process.env: https://github.com/vercel/next.js/blob/42f8ac16c6ff497f297198e42fc2abb113bf4a7b/packages/next-env/index.ts#L109

1111mp commented 4 months ago

Ok, you can reproduce the issue via this repository: https://github.com/1111mp/next-temp-app

But note that, setupFiles based workaround will be irrelevant from the next Vitest release.

I am using the preview version of vitest vscode extension because for me its official version cannot be loaded into test cases:

Screenshot 2024-04-07 at 16 26 30

Only preview version works fine.

From a quick look, it looks like you might need to pass forceReload: true around here to actually update process.env: https://github.com/vercel/next.js/blob/42f8ac16c6ff497f297198e42fc2abb113bf4a7b/packages/next-env/index.ts#L109

This has nothing to do with the loadEnvConfig api, which will load the .env file and merge it into process.env. Things get a little weird when I use the env configuration of vitest:

/// <reference types="vitest" />

import { resolve } from "path";
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";

export default defineConfig(async () => {
  const { loadEnvConfig } = (await import("@next/env")).default;
  const { combinedEnv } = loadEnvConfig(process.cwd());

  console.log(combinedEnv);

  return {
    plugins: [react()],
    test: {
      alias: {
        "@": resolve(__dirname, "./src"),
      },
      env: {
        ...(combinedEnv as Record<string, string>),
      },
      watch: false,
      environment: "jsdom",
      reporters: ["verbose"],
      setupFiles: ["./vitest-setup.mts"],
    },
  };
});

will print:

{
  TERM_PROGRAM: 'vscode',
  REDIS_HOST: '127.0.0.1',
  REDIS_PORT: '6379',
  REDIS_DB: '0',
  REDIS_USERNAME: 'root',
  REDIS_PWD: 'root',
  SMTP_HOST: 'smtp.office365.com',
  SMTP_PORT: '587',
  EMAIL_FROM: '"The1111mp" <The1111mp@outlook.com>',
  SMTP_USER: 'The1111mp@outlook.com',
  SMTP_PASSWORD: '###########'
 // ......
}

It still doesn't work for the vitest vscode extension, but if I hardcode these environment variables it will work:

/// <reference types="vitest" />

import { resolve } from "path";
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";

export default defineConfig(() => {

  return {
    plugins: [react()],
    test: {
      alias: {
        "@": resolve(__dirname, "./src"),
      },
      env: {
        TEST: "true",
        VITEST: "true",
        NODE_ENV: "test",
        DATABASE_URL: "file:./db.sqlite",
        APP_AUTH_KEY: "app_auth_key",
        APP_RANDOM_PASSWORD: "################",
        REDIS_HOST: "127.0.0.1",
        REDIS_PORT: "6379",
        REDIS_DB: "0",
        REDIS_USERNAME: "root",
        REDIS_PWD: "root",
        SMTP_HOST: "smtp.office365.com",
        SMTP_PORT: "587",
        EMAIL_FROM: '"The1111mp" <The1111mp@outlook.com>',
        SMTP_USER: "The1111mp@outlook.com",
        SMTP_PASSWORD: '###########'
      },
      watch: false,
      environment: "jsdom",
      reporters: ["verbose"],
      setupFiles: ["./vitest-setup.mts"],
    },
  };
});
Screenshot 2024-04-07 at 16 39 35
hi-ogawa commented 4 months ago

But note that, setupFiles based workaround will be irrelevant from the next Vitest release.

I am using the preview version of vitest vscode extension because for me its official version cannot be loaded into test cases:

Ah, I wasn't clear but what I meant was next vitest release, which will include this fix https://github.com/vitest-dev/vitest/pull/5476.