Open dietrich-iti opened 4 months ago
There is already one: https://vitest.dev/api/vi.html#vi-unstuballenvs
There is already one: https://vitest.dev/api/vi.html#vi-unstuballenvs
No, sorry, what I am requesting is different than that. unstubAllEnvs
undoes any stubbing that has occurred, restoring the environment back to its "true" state.
What I am wanting is:
I've put together an explicit example:
import { expect, test, vi } from 'vitest'
const defEnv = 'ACTUALLY_DEFINED_IN_ENVIRONMENT' // this is set to "original_defined_value" before vitest starts
const undefEnv = 'ACTUALLY_UNDEFINED_IN_ENVIRONMENT' // this envvar does not exist when vitest starts
test('this shows the use case for unstubAllEnvs', () => {
// env starts as:
// ACTUALLY_DEFINED_IN_ENVIRONMENT=original_defined_value
expect(process.env[defEnv]).toEqual('original_defined_value')
expect(process.env[undefEnv]).toBeUndefined()
// env becomes:
// ACTUALLY_DEFINED_IN_ENVIRONMENT=change_defined_value
// ACTUALLY_UNDEFINED_IN_ENVIRONMENT=add_undefined_value
vi.stubEnv(defEnv, 'change_defined_value')
vi.stubEnv(undefEnv, 'add_undefined_value')
expect(process.env[defEnv]).toEqual('change_defined_value')
expect(process.env[undefEnv]).toEqual('add_undefined_value')
// env returns to:
// ACTUALLY_DEFINED_IN_ENVIRONMENT=original_defined_value
vi.unstubAllEnvs()
expect(process.env[defEnv]).toEqual('original_defined_value')
expect(process.env[undefEnv]).toBeUndefined()
})
test('this shows the use case for the requested functionality', () => {
// env starts as:
// ACTUALLY_DEFINED_IN_ENVIRONMENT=original_defined_value
expect(process.env[defEnv]).toEqual('original_defined_value')
expect(process.env[undefEnv]).toBeUndefined()
// env becomes:
// ACTUALLY_UNDEFINED_IN_ENVIRONMENT=add_undefined_value
vi.stubEnv(defEnv, undefined) // <---------- this is the requested functionality
vi.stubEnv(undefEnv, 'add_undefined_value')
expect(process.env[defEnv]).toBeUndefined() // <---------- this is the desired outcome
expect(process.env[undefEnv]).toEqual('add_undefined_value')
// env returns to:
// ACTUALLY_DEFINED_IN_ENVIRONMENT=original_defined_value
vi.unstubAllEnvs()
expect(process.env[defEnv]).toEqual('original_defined_value')
expect(process.env[undefEnv]).toBeUndefined()
})
(note: This code will execute currently, but that's just because in the line labeled "this is the requested functionality", the undefined
gets coerced to a string. Consequently, the line labeled "this is the desired outcome" fails with AssertionError: expected 'undefined' to be undefined
.)
I've successfully implemented and tested this feature in a local branch. I took the "alternative" approach and made a new method, as I realized that changing the existing behavior of stubEnv
should be avoided if possible. Would it be appropriate to push this branch up at this point, so it can be looked over? Forgive my ignorance -- I haven't contributed to an open-source project before. 😅
stubEnvUndefined(name) {
if (!_stubsEnv.has(name))
_stubsEnv.set(name, process.env[name])
delete process.env[name]
return utils
},
I'm also a big fan of setting this up. It's quite common to have tests around the absence of an environment variable. However, it's also normal to have these environment variables set when doing local development with something like .env.local
. Since the variables are set the aforementioned tests will fail, which can lead to confusion. Expanding the vi.stubEnv
utility to support undefined
is something I've done in past projects using pnpm's patch command which also allows me to continue using vi.unstubAllEnvs
. I know this is still pending triage, but I do have this wired up in a fork as a potential reference point in case this ends up becoming desired functionality.
Shouldn't we call any new method that unsets a specific stubbed environment variable vi.unstubEnv()
? This would match the existing naming scheme: vi.stubEnv(), vi.unstubAllEnvs()
.
I agree this functionality would be great. We use feature flags and have hit bugs in the past where an envvar is undefined in an environment and behaves differently than we'd expect. Being able to test and control the functionality of the app when the envvar is undefined is valuable.
Clear and concise description of the problem
As a developer using Vitest, I want to be able to use the environment variable stubbing feature to make a given variable be "unset", so that I can easily test my code's behavior when environment variables are not present.
Suggested solution
Expand the functionality of
vi.stubEnv(name: string, value: string)
, changing the second argument tovalue: string | undefined
. Ifundefined
is given as the value, remove the named variable fromprocess.env
.Alternative
Alternatively, a new function like
vi.stubEnvUnset(name: string)
that does the same thing.Additional context
My current workaround is to use
beforeAll
to store theprocess.env
entries in question and then delete them, and useafterAll
to restore them.Validations