sveltejs / kit

web development, streamlined
https://svelte.dev/docs/kit
MIT License
18.64k stars 1.92k forks source link

Sveltekit dynamic public environment variable import fails in Vitest #10446

Open charlie-map opened 1 year ago

charlie-map commented 1 year ago

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

hahn-kev commented 1 year ago

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\@sveltejs+kit@1.24.1_svelte@4.2.0_vite@4.4.9\node_modules\@sveltejs\kit\src\runtime\app\environment.js

not sure if this is related.

gtm-nayan commented 1 year ago

@hahn-kev What version of vitest are you using?

https://github.com/vitest-dev/vitest/issues/4067

hahn-kev commented 1 year ago

@hahn-kev What version of vitest are you using?

vitest-dev/vitest#4067

0.34.3 looks like that's my issue, thanks! I'll just roll back for now.

gwest7 commented 8 months ago

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.

dominikg commented 8 months ago

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.

dominikg commented 8 months ago

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.

jjonescz commented 3 months ago

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