Skip to content

Commit

Permalink
feat: new environmentMatchGlobs option to auto infer env based on g…
Browse files Browse the repository at this point in the history
…lob (#2714)
  • Loading branch information
antfu committed Jan 19, 2023
1 parent da7e8d5 commit 3e1429e
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 14 deletions.
2 changes: 2 additions & 0 deletions packages/vitest/src/node/config.ts
Expand Up @@ -239,6 +239,8 @@ export function resolveConfig(
...resolved.typecheck,
}

resolved.environmentMatchGlobs = (resolved.environmentMatchGlobs || []).map(i => [resolve(resolved.root, i[0]), i[1]])

if (mode === 'typecheck') {
resolved.include = resolved.typecheck.include
resolved.exclude = resolved.typecheck.exclude
Expand Down
17 changes: 16 additions & 1 deletion packages/vitest/src/runtime/entry.ts
@@ -1,4 +1,5 @@
import { promises as fs } from 'node:fs'
import mm from 'micromatch'
import type { EnvironmentOptions, ResolvedConfig, VitestEnvironment } from '../types'
import { getWorkerState, resetModules } from '../utils'
import { vi } from '../integrations/vi'
Expand Down Expand Up @@ -31,7 +32,21 @@ export async function run(files: string[], config: ResolvedConfig): Promise<void
// if calling with no-threads, this will be the whole suite
const filesWithEnv = await Promise.all(files.map(async (file) => {
const code = await fs.readFile(file, 'utf-8')
const env = code.match(/@(?:vitest|jest)-environment\s+?([\w-]+)\b/)?.[1] || config.environment || 'node'

// 1. Check for control comments in the file
let env = code.match(/@(?:vitest|jest)-environment\s+?([\w-]+)\b/)?.[1]
// 2. Check for globals
if (!env) {
for (const [glob, target] of config.environmentMatchGlobs || []) {
if (mm.isMatch(file, glob)) {
env = target
break
}
}
}
// 3. Fallback to global env
env ||= config.environment || 'node'

const envOptions = JSON.parse(code.match(/@(?:vitest|jest)-environment-options\s+?(.+)/)?.[1] || 'null')
return {
file,
Expand Down
6 changes: 6 additions & 0 deletions packages/vitest/src/runtime/setup.ts
Expand Up @@ -7,6 +7,7 @@ import { clearTimeout, getWorkerState, isNode, setTimeout, toArray } from '../ut
import * as VitestIndex from '../index'
import { resetRunOnceCounter } from '../integrations/run-once'
import { RealDate } from '../integrations/mock/date'
import { expect } from '../integrations/chai'
import { rpc } from './rpc'

let globalSetup = false
Expand Down Expand Up @@ -180,6 +181,11 @@ export async function withEnv(
fn: () => Promise<void>,
) {
const config: Environment = (environments as any)[name] || await loadEnvironment(name)
// @ts-expect-error untyped global
globalThis.__vitest_environment__ = config.name || name
expect.setState({
environment: config.name || name || 'node',
})
const env = await config.setup(globalThis, options)
try {
await fn()
Expand Down
16 changes: 16 additions & 0 deletions packages/vitest/src/types/config.ts
Expand Up @@ -138,6 +138,22 @@ export interface InlineConfig {
*/
environmentOptions?: EnvironmentOptions

/**
* Automatically assign environment based on globs. The first match will be used.
*
* Format: [glob, environment-name]
*
* @default []
* @example [
* // all tests in tests/dom will run in jsdom
* ['tests/dom/**', 'jsdom'],
* // all tests in tests/ with .edge.test.ts will run in edge-runtime
* ['**\/*.edge.test.ts', 'edge-runtime'],
* // ...
* ]
*/
environmentMatchGlobs?: [string, VitestEnvironment][]

/**
* Update snapshot
*
Expand Down
32 changes: 19 additions & 13 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions test/env-glob/package.json
@@ -0,0 +1,11 @@
{
"name": "@vitest/test-env-glob",
"private": true,
"scripts": {
"test": "vitest",
"coverage": "vitest run --coverage"
},
"devDependencies": {
"vitest": "workspace:*"
}
}
6 changes: 6 additions & 0 deletions test/env-glob/test/base.dom.test.ts
@@ -0,0 +1,6 @@
import { expect, test } from 'vitest'

test('glob on extension', () => {
expect(typeof window).not.toBe('undefined')
expect(expect.getState().environment).toBe('happy-dom')
})
6 changes: 6 additions & 0 deletions test/env-glob/test/base.test.ts
@@ -0,0 +1,6 @@
import { expect, test } from 'vitest'

test('default', () => {
expect(typeof window).toBe('undefined')
expect(expect.getState().environment).toBe('node')
})
6 changes: 6 additions & 0 deletions test/env-glob/test/dom/base.spec.ts
@@ -0,0 +1,6 @@
import { expect, test } from 'vitest'

test('glob on folder', () => {
expect(typeof window).not.toBe('undefined')
expect(expect.getState().environment).toBe('jsdom')
})
9 changes: 9 additions & 0 deletions test/env-glob/test/dom/overrides.spec.ts
@@ -0,0 +1,9 @@
import { expect, test } from 'vitest'

/**
* @vitest-environment edge-runtime
*/

test('glob on folder overrides', () => {
expect(expect.getState().environment).toBe('edge-runtime')
})
10 changes: 10 additions & 0 deletions test/env-glob/vitest.config.ts
@@ -0,0 +1,10 @@
import { defineConfig } from 'vitest/config'

export default defineConfig({
test: {
environmentMatchGlobs: [
['**/*.dom.test.ts', 'happy-dom'],
['test/dom/**', 'jsdom'],
],
},
})

0 comments on commit 3e1429e

Please sign in to comment.