Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vite/Vitest not picking up environment variables? #2117

Closed
6 tasks done
kevinmamaqi opened this issue Oct 6, 2022 · 17 comments · Fixed by #6063
Closed
6 tasks done

Vite/Vitest not picking up environment variables? #2117

kevinmamaqi opened this issue Oct 6, 2022 · 17 comments · Fixed by #6063
Labels
documentation Improvements or additions to documentation

Comments

@kevinmamaqi
Copy link

Describe the bug

I am trying to test a file that relies on environment variables, though it doesn't load them. I use vite+vitest with React.js. It works well on development/production, but when I test the component with the variable is undefined: import.meta.env.VITE_API_URL

When I initialize the test, it loads properly on my vite.config.js:

export default ({ mode }) => {
  process.env = { ...process.env, ...loadEnv(mode, process.cwd()) }
  console.log('mode', mode, loadEnv(mode, process.cwd())) <----- HERE IT APPEARS TO BE DEFINED WHEN THE TEST STARTS
  return defineConfig({
    base: '/',
    server: {
      port: 3000,
      proxy: {
        '/public': {
          target: `${process.env.VITE_API_URL}/`,
          changeOrigin: true,
        },
      },
    },
    publicDir: './public',
    plugins: [react()],
    test: {
      globals: true,
      environment: 'jsdom',
      setupFiles: './src/__test__/setup.js',
      include: ['./src/__test__/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
    },
  })
}

Reproduction

  1. Create react app with vite-react template
  2. Add vitest
  3. Create .env with some environment variables
  4. Create a file that uses the variable
  5. Test the file and that the variable is present

Github repo: https://github.com/IT-Academy-BCN/ita-directory
Branch: https://github.com/IT-Academy-BCN/ita-directory/tree/511-test-recover-password
File: https://github.com/IT-Academy-BCN/ita-directory/blob/511-test-recover-password/frontend/src/__test__/pages/UserFlow/RecoverPassword.test.jsx

System Info

envinfo command not found

Used Package Manager

npm

Validations

@sheremet-va
Copy link
Member

Vitest runs with test mode, so it will not read .env.development by default (only .env and .env.test, so I'm not sure what you expect here 🤔

@kevinmamaqi
Copy link
Author

kevinmamaqi commented Oct 6, 2022

@sheremet-va As soon as you npm run frontend the .env.development is copied to a .env file in the frontend directory. Moreover, when the test start, the variables are defined:

console.log('mode', mode, loadEnv(mode, process.cwd())) <----- HERE IT APPEARS TO BE DEFINED WHEN THE TEST STARTS

Vitest runs with test mode, so it will not read .env.development by default (only .env and .env.test, so I'm not sure what you expect here 🤔

@DragonAxe01
Copy link

Spent many hours trying to load basic environment variables and I'm still on it. Just saying...

@jamierytlewski
Copy link

jamierytlewski commented Aug 3, 2023

Yeah, I'm having the same issue. It works when the environment is node. But if I'm using jsdom for the environment I'm not getting anything.

import.meta { url: 'file:///C:/git/vite-project/src/App.tsx' } - This is the output that I'm getting from the import.meta.

I have created an .env.test file that has VITE_APP_TITLE in it.

I have create an .env.test.local an .env.local.test and all the same issues.

The error message from the test is

TypeError: Cannot set properties of null (setting 'innerText')
 ❯ src/App.tsx:11:11
      9|     console.log("import.meta", import.meta);
     10|     const title = document.querySelector("title") as HTMLTitleElement;
     11|     title.innerText = `${import.meta.env.VITE_APP_TITLE}}`;
       |           ^
     12|   }, []);

This works in the browser, not on vitest.

@sheremet-va
Copy link
Member

import.meta { url: 'file:///C:/git/vite-project/src/App.tsx' } - This is the output that I'm getting from the import.meta.

import.meta.{env} is statically replaced, so you will never see it in there.

@chriswilty
Copy link

@jamierytlewski, title is null according to the error message, it has nothing to do with your env var.

Plus you have a double curly brace at the end of your innerText value which is probably not what you want.

@Michael-indochat
Copy link

Vitest runs with test mode, so it will not read .env.development by default (only .env and .env.test, so I'm not sure what you expect here 🤔

@sheremet-va
Where can I find this narrative in the official documentation, Want to confirm if only .env & .env.test is supported.

@sheremet-va
Copy link
Member

@sheremet-va Where can I find this narrative in the official documentation, Want to confirm if only .env & .env.test is supported.

@shekhov
Copy link

shekhov commented Nov 5, 2023

The same issue here, but instead of using process.env I used vi.stubEnv. With the following test:

it ('Should fetch an api "/api/v1/hello-github"', async () => {

    vi.stubEnv('VITE_API_BASE_ADDRESS', 'http://localhost:5000')
    fetch.mockResponseOnce('Success', {status: 200});    
    inputField.value = validEmail; 

    await user.click(submitBtn);

    expect(import.meta.env.VITE_API_BASE_ADDRESS).toBe('http://localhost:5000')
    expect (fetch.requests().length).toEqual(1);
    expect (fetch.requests()[0].url).toEqual('http://localhost:5000/api/v1/hello-github');
});

the test fails on the last expect, meaning that from vitest perspective it actually has loaded the env var, only later it did not pass it to the component under test

@SiNONiMiTY
Copy link

This will make Vitest load your .env file

// vitest.config.ts

import { loadEnv } from 'vite'
import { defineConfig } from 'vitest/config'

export default defineConfig({
    test: {
        env: loadEnv('', process.cwd(), ''),
    },
})

@taminhtienhai
Copy link

taminhtienhai commented May 26, 2024

https://stackoverflow.com/a/78206557/11722137

import { defineConfig, mergeConfig } from 'vitest/config';
import viteConfig from './vite.config.js';
import { config } from "dotenv";

export default mergeConfig(viteConfig, defineConfig({
    test: {
        root: './tests',
        env: {
            ...config({ path: ".env.development" }).parsed,
        }, // this work for me
    },
    
}));

@sheremet-va
Copy link
Member

stackoverflow.com/a/78206557/11722137

There is no need to install dotenv package since Vite exposes it via loadEnv already.


Vitest cannot load all envs because it would break Vite tests that rely on Vite loading only prefixed envs. If you still want to expose any env, you can use loadEnv method:

import { loadEnv } from 'vite'
import { defineConfig } from 'vitest/config'

export default defineConfig(({ mode }) => {
  return {
    test: {
      env: loadEnv(mode, process.cwd(), '')
    }
  }
})

I think we should make it clear in the documentation before closing this issue.

@sheremet-va sheremet-va added the documentation Improvements or additions to documentation label May 27, 2024
@wesamjabali
Copy link

This fixed it for me:

import path from 'path'
import { loadEnvFile } from 'process'

loadEnvFile(path.resolve(__dirname, '.env'))

export default defineVitestConfig({/* */})

@Boby900
Copy link

Boby900 commented Jun 30, 2024

this worked for me,

// vitest.config.ts
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
import path from 'path'
import dotenv from "dotenv";
dotenv.config({ path: ".env.local" });
export default defineConfig({
  plugins: [react()],
  test: {
    environment: 'jsdom',
  },
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
  
 
})

@githorse
Copy link

githorse commented Jul 6, 2024

@wesamjabali's answer is the only one that I can get to expose REACT_APP_ envars to the component under test:

import path from 'path'
import { loadEnvFile } from 'process'

loadEnvFile(path.resolve(__dirname, '.env'))

export default defineVitestConfig({/* */})

@ticup
Copy link

ticup commented Jul 18, 2024

stackoverflow.com/a/78206557/11722137

There is no need to install dotenv package since Vite exposes it via loadEnv already.

Vitest cannot load all envs because it would break Vite tests that rely on Vite loading only prefixed envs. If you still want to expose any env, you can use loadEnv method:

import { loadEnv } from 'vite'
import { defineConfig } from 'vitest/config'

export default defineConfig(({ mode }) => {
  return {
    test: {
      env: loadEnv(mode, process.cwd(), '')
    }
  }
})

I think we should make it clear in the documentation before closing this issue.

This works for me, but I also have a globalSetup file, and there the test environment variables from .env.test aren't loaded...

import { defineConfig } from 'vitest/config';
import { loadEnv } from 'vite'

export default defineConfig(({mode}) => {
  return {
    test: {
      include: ['src/**/*.{test,spec}.{js,ts}'],
      env: loadEnv(mode, process.cwd(), ''),
      globalSetup: ['src/test/globalSetup.ts'],
  }
}
});

@surya-muruganantham
Copy link

vitest --mode development

adding mode flag for vitest command in package.json is working.

@github-actions github-actions bot locked and limited conversation to collaborators Aug 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging a pull request may close this issue.