Sveltekit dynamic public environment variable import fails in Vitest
Describe the bug
Attempted import:
// place files you want to import through the `$lib` alias in this folder.
import { env } from '$env/dynamic/private';
import { env as publicEnv } from '$env/dynamic/public';
Error during Vitest (npm run test):
FAIL src/index.test.ts [ src/index.test.ts ]
TypeError: Cannot read properties of undefined (reading 'env')
❯ $env/dynamic/public:1:40
❯ src/lib/index.ts:2:31
1| // place files you want to import through the `$lib` alias in this folder.
2| import { env } from '$env/dynamic/private';
| ^
3| import { env as publicEnv } from '$env/dynamic/public';
Another note: the carrot symbol (^) is confusingly placed one line above the error. For instance, switching the order to:
// place files you want to import through the `$lib` alias in this folder.
import { env as publicEnv } from '$env/dynamic/public';
import { env } from '$env/dynamic/private';
causes the following error during npm run test:
FAIL src/index.test.ts [ src/index.test.ts ]
TypeError: Cannot read properties of undefined (reading 'env')
❯ $env/dynamic/public:1:40
❯ src/lib/index.ts:1:31
1| // place files you want to import through the `$lib` alias in this folder.
| ^
2| import { env as publicEnv } from '$env/dynamic/public';
3| import { env } from '$env/dynamic/private';
Reproduction
There are notes in the README for setup: https://github.com/charlie-map/sveltekit-vitest-issue
Logs
No response
System Info
System:
OS: macOS 13.1
CPU: (8) arm64 Apple M1 Pro
Memory: 55.14 MB / 16.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 19.6.0 - /opt/homebrew/bin/node
npm: 9.4.0 - /opt/homebrew/bin/npm
Browsers:
Brave Browser: 105.1.43.88
Chrome: 114.0.5735.248
Safari: 16.2
npmPackages:
@sveltejs/adapter-auto: ^2.0.0 => 2.1.0
@sveltejs/kit: ^1.20.4 => 1.22.3
svelte: ^4.0.5 => 4.1.1
vite: ^4.4.2 => 4.4.7
Also test on:
System:
OS: Linux 5.10 Ubuntu 20.04.5 LTS (Focal Fossa)
CPU: (8) x64 Intel(R) Core(TM) i7-4720HQ CPU @ 2.60GHz
Memory: 1.23 GB / 5.80 GB
Container: Yes
Shell: 5.0.17 - /bin/bash
Binaries:
Node: 18.12.0 - ~/.nvm/versions/node/v18.12.0/bin/node
npm: 9.7.1 - ~/.nvm/versions/node/v18.12.0/bin/npm
npmPackages:
@sveltejs/adapter-node: ^1.2.4 => 1.2.4
@sveltejs/kit: ^1.22.1 => 1.22.1
svelte: ^4.0.5 => 4.0.5
vite: ^4.3.0 => 4.3.9
Severity
serious, but I can work around it
Additional Information
No response
I'm also having issues importing modules that import from '$app/environment' my errors is a bit different though:
Error: Cannot find package '__sveltekit' imported from C:\dev\DefaultTemplates\sveltekit\node_modules\.pnpm\@[email protected][email protected][email protected]\node_modules\@sveltejs\kit\src\runtime\app\environment.js
not sure if this is related.
@hahn-kev What version of vitest are you using?
https://github.com/vitest-dev/vitest/issues/4067
@hahn-kev What version of vitest are you using?
0.34.3 looks like that's my issue, thanks! I'll just roll back for now.
Our first time using a dynamic env var in a test is also not going well. We have the exact same "Cannot read properties of undefined (reading 'env')" as above.
looks like this recent change broke the fallback and expects the global to be set always, which isn't the case in vitest env
https://github.com/sveltejs/kit/pull/11601/files#diff-beef34c36ed87d7835d0166655010910fba9949a6ef95042cb468d7d73423816R427
leading to
TypeError: Cannot read properties of undefined (reading 'env')
❯ virtual:$env/dynamic/public:1:40
update: the fallback also uses the global env, so either browser would have to be false OR the globalThis.__sveltekit_dev.env needs to be initialized somehow.
workaround to stub it via vitest, use vites own tooling to load an env config and supply the public prefixes to globalThis.__sveltekit_dev.
Note that this is a workaround, and the code requires node 20.11 for import.meta.dirname
import { loadEnv } from 'vite';
// stub sveltekit client global env to avoid tests failing on import of $env/dynamic/public
vi.stubGlobal('__sveltekit_dev', { env: loadEnv('test', import.meta.dirname, 'PUBLIC_') });
put it in a global vitest setup file that is in the root of your app, alongside .env.test where you can set the needed values.
Might be a problem with the test environment - I had the problem with the jsdom environment, but switching to the node environment solved the issue. For example, adding this to the start of the test file:
// @vitest-environment node