From f6eeefa5364c310292ba790c009fdbc128f2c6a0 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Wed, 9 Feb 2022 15:47:24 +0300 Subject: [PATCH 1/5] feat: allow change import.meta.env --- .../vitest/src/node/plugins/envReplacer.ts | 30 +++++++++++++++++++ packages/vitest/src/node/plugins/index.ts | 11 +++++++ test/core/src/env.ts | 3 ++ test/core/test/basic.test.ts | 13 ++++++++ test/core/tsconfig.json | 6 ++++ 5 files changed, 63 insertions(+) create mode 100644 packages/vitest/src/node/plugins/envReplacer.ts create mode 100644 test/core/src/env.ts create mode 100644 test/core/tsconfig.json diff --git a/packages/vitest/src/node/plugins/envReplacer.ts b/packages/vitest/src/node/plugins/envReplacer.ts new file mode 100644 index 000000000000..28c7027e182d --- /dev/null +++ b/packages/vitest/src/node/plugins/envReplacer.ts @@ -0,0 +1,30 @@ +import MagicString from 'magic-string' +import type { Plugin } from 'vite' + +export const EnvReplacerPlugin = (): Plugin => { + return { + name: 'vitest:env-replacer', + enforce: 'pre', + transform(code) { + let s: MagicString | null = null + + const envs = code.matchAll(/\bimport\.meta\.env\b/g) + + for (const env of envs) { + s ||= new MagicString(code) + + const startIndex = env.index! + const endIndex = startIndex + env[0].length + + s.overwrite(startIndex, endIndex, 'process.env') + } + + if (s) { + return { + code: s.toString(), + map: s.generateMap({ hires: true }), + } + } + }, + } +} diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts index 539f7b7c80b2..0ed81ea894b4 100644 --- a/packages/vitest/src/node/plugins/index.ts +++ b/packages/vitest/src/node/plugins/index.ts @@ -5,6 +5,7 @@ import { resolveApiConfig } from '../config' import { Vitest } from '../core' import { GlobalSetupPlugin } from './globalSetup' import { MocksPlugin } from './mock' +import { EnvReplacerPlugin } from './envReplacer' export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest()): Promise { let haveStarted = false @@ -47,6 +48,15 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest()) // viteConfig.test is final now, merge it for real options = deepMerge(options, viteConfig.test as any || {}) options.api = resolveApiConfig(options) + + // account for user env defines + for (const key in viteConfig.define) { + if (key.startsWith('import.meta.env.')) { + const val = viteConfig.define[key] + const envKey = key.slice('import.meta.env.'.length) + process.env[envKey] = typeof val === 'string' ? val : JSON.stringify(val) + } + } }, async configureServer(server) { if (haveStarted) @@ -61,6 +71,7 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest()) await server.watcher.close() }, }, + EnvReplacerPlugin(), MocksPlugin(), GlobalSetupPlugin(ctx), options.ui diff --git a/test/core/src/env.ts b/test/core/src/env.ts new file mode 100644 index 000000000000..dc81c1f038c2 --- /dev/null +++ b/test/core/src/env.ts @@ -0,0 +1,3 @@ +export function getAuthToken() { + return import.meta.env.AUTH_TOKEN +} diff --git a/test/core/test/basic.test.ts b/test/core/test/basic.test.ts index b646ce3220e4..63ffa3f6810f 100644 --- a/test/core/test/basic.test.ts +++ b/test/core/test/basic.test.ts @@ -1,6 +1,19 @@ import { assert, expect, it, suite, test } from 'vitest' import { two } from '../src/submodule' import { timeout } from '../src/timeout' +import { getAuthToken } from '../src/env' + +test('can reassign env locally', () => { + import.meta.env.VITEST_ENV = 'TEST' + expect(import.meta.env.VITEST_ENV).toBe('TEST') +}) + +test('can reassign env everywhere', () => { + import.meta.env.AUTH_TOKEN = '123' + expect(getAuthToken()).toBe('123') + process.env.AUTH_TOKEN = '321' + expect(getAuthToken()).toBe('321') +}) test('Math.sqrt()', async() => { assert.equal(Math.sqrt(4), two) diff --git a/test/core/tsconfig.json b/test/core/tsconfig.json new file mode 100644 index 000000000000..d2167fe37dce --- /dev/null +++ b/test/core/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "types": ["vite/client"], + }, +} \ No newline at end of file From 19b3ed22f461da8a8d356712570961db68e48ab1 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Wed, 9 Feb 2022 15:51:30 +0300 Subject: [PATCH 2/5] chore: more tests for "define" import.meta.env --- packages/vitest/src/node/plugins/index.ts | 2 +- test/core/test/basic.test.ts | 13 ------------- test/core/test/env.test.ts | 19 +++++++++++++++++++ test/core/vitest.config.ts | 3 +++ 4 files changed, 23 insertions(+), 14 deletions(-) create mode 100644 test/core/test/env.test.ts diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts index 0ed81ea894b4..036538f3c825 100644 --- a/packages/vitest/src/node/plugins/index.ts +++ b/packages/vitest/src/node/plugins/index.ts @@ -54,7 +54,7 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest()) if (key.startsWith('import.meta.env.')) { const val = viteConfig.define[key] const envKey = key.slice('import.meta.env.'.length) - process.env[envKey] = typeof val === 'string' ? val : JSON.stringify(val) + process.env[envKey] = typeof val === 'string' ? JSON.parse(val) : val } } }, diff --git a/test/core/test/basic.test.ts b/test/core/test/basic.test.ts index 63ffa3f6810f..b646ce3220e4 100644 --- a/test/core/test/basic.test.ts +++ b/test/core/test/basic.test.ts @@ -1,19 +1,6 @@ import { assert, expect, it, suite, test } from 'vitest' import { two } from '../src/submodule' import { timeout } from '../src/timeout' -import { getAuthToken } from '../src/env' - -test('can reassign env locally', () => { - import.meta.env.VITEST_ENV = 'TEST' - expect(import.meta.env.VITEST_ENV).toBe('TEST') -}) - -test('can reassign env everywhere', () => { - import.meta.env.AUTH_TOKEN = '123' - expect(getAuthToken()).toBe('123') - process.env.AUTH_TOKEN = '321' - expect(getAuthToken()).toBe('321') -}) test('Math.sqrt()', async() => { assert.equal(Math.sqrt(4), two) diff --git a/test/core/test/env.test.ts b/test/core/test/env.test.ts new file mode 100644 index 000000000000..fee811c1c156 --- /dev/null +++ b/test/core/test/env.test.ts @@ -0,0 +1,19 @@ +import { expect, test } from 'vitest' +import { getAuthToken } from '../src/env' + +test('can reassign env locally', () => { + import.meta.env.VITEST_ENV = 'TEST' + expect(import.meta.env.VITEST_ENV).toBe('TEST') +}) + +test('can reassign env everywhere', () => { + import.meta.env.AUTH_TOKEN = '123' + expect(getAuthToken()).toBe('123') + process.env.AUTH_TOKEN = '321' + expect(getAuthToken()).toBe('321') +}) + +test('can see env in "define"', () => { + expect(import.meta.env.TEST_NAME).toBe('hello world') + expect(process.env.TEST_NAME).toBe('hello world') +}) diff --git a/test/core/vitest.config.ts b/test/core/vitest.config.ts index c53eaf09ce5c..3a2f0b1749d7 100644 --- a/test/core/vitest.config.ts +++ b/test/core/vitest.config.ts @@ -17,6 +17,9 @@ export default defineConfig({ }, }, ], + define: { + 'import.meta.env.TEST_NAME': '"hello world"', + }, test: { testTimeout: 2000, // threads: false, From 2591ba59e4738ea7c59190665650decbefee015d Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Wed, 9 Feb 2022 16:03:56 +0300 Subject: [PATCH 3/5] chore: expose BASE_URL, MODE, PROD, DEV on env --- packages/vitest/src/node/plugins/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts index 036538f3c825..0314912f2b02 100644 --- a/packages/vitest/src/node/plugins/index.ts +++ b/packages/vitest/src/node/plugins/index.ts @@ -49,6 +49,13 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest()) options = deepMerge(options, viteConfig.test as any || {}) options.api = resolveApiConfig(options) + process.env.BASE_URL = viteConfig.base + process.env.MODE = viteConfig.mode + // process.env can have only string values and will cast string on it if we pass other type, + // so we are making them truthy + process.env.PROD = viteConfig.env.PROD ? '1' : '' + process.env.DEV = viteConfig.env.DEV ? '1' : '' + // account for user env defines for (const key in viteConfig.define) { if (key.startsWith('import.meta.env.')) { From f30c3cabf0b75e7a74f5394076e96c49aa983a7e Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Wed, 9 Feb 2022 16:08:14 +0300 Subject: [PATCH 4/5] chore: fix typings --- packages/vitest/src/node/plugins/index.ts | 1 + test/core/tsconfig.json | 6 ------ test/core/types/env.d.ts | 12 ++++++++++++ 3 files changed, 13 insertions(+), 6 deletions(-) delete mode 100644 test/core/tsconfig.json create mode 100644 test/core/types/env.d.ts diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts index 0314912f2b02..4ff21fe2e555 100644 --- a/packages/vitest/src/node/plugins/index.ts +++ b/packages/vitest/src/node/plugins/index.ts @@ -55,6 +55,7 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest()) // so we are making them truthy process.env.PROD = viteConfig.env.PROD ? '1' : '' process.env.DEV = viteConfig.env.DEV ? '1' : '' + process.env.SSR = '1' // account for user env defines for (const key in viteConfig.define) { diff --git a/test/core/tsconfig.json b/test/core/tsconfig.json deleted file mode 100644 index d2167fe37dce..000000000000 --- a/test/core/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "types": ["vite/client"], - }, -} \ No newline at end of file diff --git a/test/core/types/env.d.ts b/test/core/types/env.d.ts new file mode 100644 index 000000000000..c45958f8bec8 --- /dev/null +++ b/test/core/types/env.d.ts @@ -0,0 +1,12 @@ +interface ImportMeta { + readonly env: ImportMetaEnv +} + +interface ImportMetaEnv { + [key: string]: string | boolean | undefined + BASE_URL: string + MODE: string + DEV: boolean + PROD: boolean + SSR: boolean +} From 38a8deb8872086aef7e187405809d1480db17c6e Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Wed, 9 Feb 2022 16:44:37 +0300 Subject: [PATCH 5/5] fix: respect user env if provided --- packages/vitest/src/node/plugins/index.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts index 4ff21fe2e555..44ec1c91fde3 100644 --- a/packages/vitest/src/node/plugins/index.ts +++ b/packages/vitest/src/node/plugins/index.ts @@ -49,13 +49,13 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest()) options = deepMerge(options, viteConfig.test as any || {}) options.api = resolveApiConfig(options) - process.env.BASE_URL = viteConfig.base - process.env.MODE = viteConfig.mode + process.env.BASE_URL ??= viteConfig.base + process.env.MODE ??= viteConfig.mode // process.env can have only string values and will cast string on it if we pass other type, // so we are making them truthy - process.env.PROD = viteConfig.env.PROD ? '1' : '' - process.env.DEV = viteConfig.env.DEV ? '1' : '' - process.env.SSR = '1' + process.env.PROD ??= viteConfig.env.PROD ? '1' : '' + process.env.DEV ??= viteConfig.env.DEV ? '1' : '' + process.env.SSR ??= '1' // account for user env defines for (const key in viteConfig.define) {