Skip to content

Commit

Permalink
Revert "feat!: remove transformMode option"
Browse files Browse the repository at this point in the history
This reverts commit 7983d53.
  • Loading branch information
sheremet-va committed Jun 1, 2023
1 parent 7983d53 commit b6c4a6c
Show file tree
Hide file tree
Showing 23 changed files with 121 additions and 152 deletions.
36 changes: 36 additions & 0 deletions docs/config/index.md
Expand Up @@ -1117,6 +1117,42 @@ Will call [`vi.unstubAllEnvs`](/api/vi#vi-unstuballenvs) before each test.

Will call [`vi.unstubAllGlobals`](/api/vi#vi-unstuballglobals) before each test.

### transformMode

- **Type:** `{ web?, ssr? }`

Determine the transform method of modules

#### transformMode.ssr

- **Type:** `RegExp[]`
- **Default:** `[/\.([cm]?[jt]sx?|json)$/]`

Use SSR transform pipeline for the specified files.<br>
Vite plugins will receive `ssr: true` flag when processing those files.

#### transformMode&#46;web

- **Type:** `RegExp[]`
- **Default:** *modules other than those specified in `transformMode.ssr`*

First do a normal transform pipeline (targeting browser), then do a SSR rewrite to run the code in Node.<br>
Vite plugins will receive `ssr: false` flag when processing those files.

When you use JSX as component models other than React (e.g. Vue JSX or SolidJS), you might want to config as following to make `.tsx` / `.jsx` transformed as client-side components:

```ts
import { defineConfig } from 'vitest/config'

export default defineConfig({
test: {
transformMode: {
web: [/\.[jt]sx$/],
},
},
})
```

### snapshotFormat<NonProjectOption />

- **Type:** `PrettyFormatOptions`
Expand Down
3 changes: 3 additions & 0 deletions examples/solid/vite.config.mjs
Expand Up @@ -7,6 +7,9 @@ import solid from 'vite-plugin-solid'
export default defineConfig({
test: {
environment: 'jsdom',
transformMode: {
web: [/.[jt]sx?/],
},
threads: false,
isolate: false,
},
Expand Down
3 changes: 3 additions & 0 deletions examples/vue-jsx/vite.config.ts
Expand Up @@ -7,5 +7,8 @@ export default defineConfig({
test: {
globals: true,
environment: 'jsdom',
transformMode: {
web: [/.[tj]sx$/],
},
},
})
1 change: 0 additions & 1 deletion packages/vitest/src/integrations/env/edge-runtime.ts
Expand Up @@ -4,7 +4,6 @@ import { populateGlobal } from './utils'

export default <Environment>({
name: 'edge-runtime',
transformMode: 'ssr',
async setup(global) {
const { EdgeVM } = await importModule('@edge-runtime/vm') as typeof import('@edge-runtime/vm')
const vm = new EdgeVM({
Expand Down
1 change: 0 additions & 1 deletion packages/vitest/src/integrations/env/happy-dom.ts
Expand Up @@ -4,7 +4,6 @@ import { populateGlobal } from './utils'

export default <Environment>({
name: 'happy-dom',
transformMode: 'web',
async setup(global) {
// happy-dom v3 introduced a breaking change to Window, but
// provides GlobalWindow as a way to use previous behaviour
Expand Down
22 changes: 1 addition & 21 deletions packages/vitest/src/integrations/env/index.ts
@@ -1,6 +1,4 @@
import type { BuiltinEnvironment, VitestEnvironment } from '../../types/config'
import type { VitestExecutor } from '../../node'
import type { Environment } from '../../types'
import type { VitestEnvironment } from '../../types/config'
import node from './node'
import jsdom from './jsdom'
import happy from './happy-dom'
Expand All @@ -21,28 +19,10 @@ export const envPackageNames: Record<Exclude<keyof typeof environments, 'node'>,
'edge-runtime': '@edge-runtime/vm',
}

function isBuiltinEnvironment(env: VitestEnvironment): env is BuiltinEnvironment {
return env in environments
}

export function getEnvPackageName(env: VitestEnvironment) {
if (env === 'node')
return null
if (env in envPackageNames)
return (envPackageNames as any)[env]
return `vitest-environment-${env}`
}

export async function loadEnvironment(name: VitestEnvironment, executor: VitestExecutor): Promise<Environment> {
if (isBuiltinEnvironment(name))
return environments[name]
const packageId = (name[0] === '.' || name[0] === '/') ? name : `vitest-environment-${name}`
const pkg = await executor.executeId(packageId)
if (!pkg || !pkg.default || typeof pkg.default !== 'object' || typeof pkg.default.setup !== 'function') {
throw new Error(
`Environment "${name}" is not a valid environment. `
+ `Package "vitest-environment-${name}" should have default export with "setup" method.`,
)
}
return pkg.default
}
1 change: 0 additions & 1 deletion packages/vitest/src/integrations/env/jsdom.ts
Expand Up @@ -28,7 +28,6 @@ function catchWindowErrors(window: Window) {

export default <Environment>({
name: 'jsdom',
transformMode: 'web',
async setup(global, { jsdom = {} }) {
const {
CookieJar,
Expand Down
1 change: 0 additions & 1 deletion packages/vitest/src/integrations/env/node.ts
Expand Up @@ -3,7 +3,6 @@ import type { Environment } from '../../types'

export default <Environment>({
name: 'node',
transformMode: 'ssr',
async setup(global) {
global.console.Console = Console
return {
Expand Down
7 changes: 5 additions & 2 deletions packages/vitest/src/node/pools/rpc.ts
@@ -1,5 +1,6 @@
import type { RawSourceMap } from 'vite-node'
import type { RuntimeRPC } from '../../types'
import { getEnvironmentTransformMode } from '../../utils/base'
import type { WorkspaceProject } from '../workspace'

export function createMethodsRPC(project: WorkspaceProject): RuntimeRPC {
Expand All @@ -24,10 +25,12 @@ export function createMethodsRPC(project: WorkspaceProject): RuntimeRPC {
const r = await project.vitenode.transformRequest(id)
return r?.map as RawSourceMap | undefined
},
fetch(id, transformMode) {
fetch(id, environment) {
const transformMode = getEnvironmentTransformMode(project.config, environment)
return project.vitenode.fetchModule(id, transformMode)
},
resolveId(id, importer, transformMode) {
resolveId(id, importer, environment) {
const transformMode = getEnvironmentTransformMode(project.config, environment)
return project.vitenode.resolveId(id, importer, transformMode)
},
onPathsCollected(paths) {
Expand Down
8 changes: 4 additions & 4 deletions packages/vitest/src/runtime/child.ts
Expand Up @@ -10,7 +10,7 @@ import { rpcDone } from './rpc'
import { setupInspect } from './inspector'

function init(ctx: ChildContext) {
const { config, environment } = ctx
const { config } = ctx

process.env.VITEST_WORKER_ID = '1'
process.env.VITEST_POOL_ID = '1'
Expand All @@ -21,7 +21,7 @@ function init(ctx: ChildContext) {
})

// @ts-expect-error untyped global
globalThis.__vitest_environment__ = environment.name
globalThis.__vitest_environment__ = config.environment
// @ts-expect-error I know what I am doing :P
globalThis.__vitest_worker__ = {
ctx,
Expand Down Expand Up @@ -76,8 +76,8 @@ export async function run(ctx: ChildContext) {

try {
init(ctx)
const { run, executor, environment } = await startViteNode(ctx)
await run(ctx.files, ctx.config, { ...ctx.environment, environment }, executor)
const { run, executor } = await startViteNode(ctx)
await run(ctx.files, ctx.config, ctx.environment, executor)
await rpcDone()
}
finally {
Expand Down
8 changes: 4 additions & 4 deletions packages/vitest/src/runtime/entry.ts
Expand Up @@ -2,7 +2,7 @@ import { performance } from 'node:perf_hooks'
import type { VitestRunner, VitestRunnerConstructor } from '@vitest/runner'
import { startTests } from '@vitest/runner'
import { resolve } from 'pathe'
import type { ResolvedConfig, ResolvedTestEnvironment } from '../types'
import type { ContextTestEnvironment, ResolvedConfig } from '../types'
import { getWorkerState, resetModules } from '../utils'
import { vi } from '../integrations/vi'
import { distDir } from '../paths'
Expand Down Expand Up @@ -89,7 +89,7 @@ async function getTestRunner(config: ResolvedConfig, executor: VitestExecutor):
}

// browser shouldn't call this!
export async function run(files: string[], config: ResolvedConfig, environment: ResolvedTestEnvironment, executor: VitestExecutor): Promise<void> {
export async function run(files: string[], config: ResolvedConfig, environment: ContextTestEnvironment, executor: VitestExecutor): Promise<void> {
const workerState = getWorkerState()

await setupGlobalEnv(config)
Expand All @@ -104,11 +104,11 @@ export async function run(files: string[], config: ResolvedConfig, environment:
workerState.durations.prepare = performance.now() - workerState.durations.prepare

// @ts-expect-error untyped global
globalThis.__vitest_environment__ = environment.name
globalThis.__vitest_environment__ = environment

workerState.durations.environment = performance.now()

await withEnv(environment, environment.options || config.environmentOptions || {}, async () => {
await withEnv(environment.name, environment.options || config.environmentOptions || {}, executor, async () => {
workerState.durations.environment = performance.now() - workerState.durations.environment

for (const file of files) {
Expand Down
17 changes: 5 additions & 12 deletions packages/vitest/src/runtime/execute.ts
Expand Up @@ -6,9 +6,8 @@ import { normalize, relative, resolve } from 'pathe'
import { processError } from '@vitest/runner/utils'
import type { MockMap } from '../types/mocker'
import { getCurrentEnvironment, getWorkerState } from '../utils/global'
import type { ContextRPC, Environment, ResolvedConfig, ResolvedTestEnvironment } from '../types'
import type { ContextRPC, ContextTestEnvironment, ResolvedConfig } from '../types'
import { distDir } from '../paths'
import { loadEnvironment } from '../integrations/env'
import { VitestMocker } from './mocker'
import { rpc } from './rpc'

Expand All @@ -26,9 +25,8 @@ export async function createVitestExecutor(options: ExecuteOptions) {
}

let _viteNode: {
run: (files: string[], config: ResolvedConfig, environment: ResolvedTestEnvironment, executor: VitestExecutor) => Promise<void>
run: (files: string[], config: ResolvedConfig, environment: ContextTestEnvironment, executor: VitestExecutor) => Promise<void>
executor: VitestExecutor
environment: Environment
}

export const moduleCache = new ModuleCacheMap()
Expand Down Expand Up @@ -63,14 +61,12 @@ export async function startViteNode(ctx: ContextRPC) {
process.on('uncaughtException', e => catchError(e, 'Uncaught Exception'))
process.on('unhandledRejection', e => catchError(e, 'Unhandled Rejection'))

let transformMode: 'ssr' | 'web' = 'ssr'

const executor = await createVitestExecutor({
fetchModule(id) {
return rpc().fetch(id, transformMode)
return rpc().fetch(id, ctx.environment.name)
},
resolveId(id, importer) {
return rpc().resolveId(id, importer, transformMode)
return rpc().resolveId(id, importer, ctx.environment.name)
},
moduleCache,
mockMap,
Expand All @@ -80,12 +76,9 @@ export async function startViteNode(ctx: ContextRPC) {
base: config.base,
})

const environment = await loadEnvironment(ctx.environment.name, executor)
transformMode = environment.transformMode ?? 'ssr'

const { run } = await import(pathToFileURL(resolve(distDir, 'entry.js')).href)

_viteNode = { run, executor, environment }
_viteNode = { run, executor }

return _viteNode
}
Expand Down
27 changes: 21 additions & 6 deletions packages/vitest/src/runtime/setup.node.ts
Expand Up @@ -2,14 +2,16 @@ import { createRequire } from 'node:module'
import { isatty } from 'node:tty'
import { installSourcemapsSupport } from 'vite-node/source-map'
import { createColors, setupColors } from '@vitest/utils'
import type { EnvironmentOptions, ResolvedConfig, ResolvedTestEnvironment } from '../types'
import { environments } from '../integrations/env'
import type { Environment, ResolvedConfig } from '../types'
import { VitestSnapshotEnvironment } from '../integrations/snapshot/environments/node'
import { getSafeTimers, getWorkerState } from '../utils'
import * as VitestIndex from '../index'
import { RealDate } from '../integrations/mock/date'
import { expect } from '../integrations/chai'
import { rpc } from './rpc'
import { setupCommonEnv } from './setup.common'
import type { VitestExecutor } from './execute'

// this should only be used in Node
let globalSetup = false
Expand Down Expand Up @@ -155,17 +157,30 @@ export async function setupConsoleLogSpy() {
})
}

async function loadEnvironment(name: string, executor: VitestExecutor) {
const pkg = await executor.executeId(`vitest-environment-${name}`)
if (!pkg || !pkg.default || typeof pkg.default !== 'object' || typeof pkg.default.setup !== 'function') {
throw new Error(
`Environment "${name}" is not a valid environment. `
+ `Package "vitest-environment-${name}" should have default export with "setup" method.`,
)
}
return pkg.default
}

export async function withEnv(
{ environment, name }: ResolvedTestEnvironment,
options: EnvironmentOptions,
name: ResolvedConfig['environment'],
options: ResolvedConfig['environmentOptions'],
executor: VitestExecutor,
fn: () => Promise<void>,
) {
const config: Environment = (environments as any)[name] || await loadEnvironment(name, executor)
// @ts-expect-error untyped global
globalThis.__vitest_environment__ = name
globalThis.__vitest_environment__ = config.name || name
expect.setState({
environment: name,
environment: config.name || name || 'node',
})
const env = await environment.setup(globalThis, options)
const env = await config.setup(globalThis, options)
try {
await fn()
}
Expand Down
6 changes: 3 additions & 3 deletions packages/vitest/src/runtime/worker.ts
Expand Up @@ -24,7 +24,7 @@ function init(ctx: WorkerContext) {
})

// @ts-expect-error untyped global
globalThis.__vitest_environment__ = config.environment.name
globalThis.__vitest_environment__ = config.environment
// @ts-expect-error I know what I am doing :P
globalThis.__vitest_worker__ = {
ctx,
Expand Down Expand Up @@ -62,8 +62,8 @@ export async function run(ctx: WorkerContext) {

try {
init(ctx)
const { run, executor, environment } = await startViteNode(ctx)
await run(ctx.files, ctx.config, { ...ctx.environment, environment }, executor)
const { run, executor } = await startViteNode(ctx)
await run(ctx.files, ctx.config, ctx.environment, executor)
await rpcDone()
}
finally {
Expand Down
21 changes: 21 additions & 0 deletions packages/vitest/src/types/config.ts
Expand Up @@ -438,6 +438,27 @@ export interface InlineConfig {
*/
uiBase?: string

/**
* Determine the transform method of modules
*/
transformMode?: {
/**
* Use SSR transform pipeline for the specified files.
* Vite plugins will receive `ssr: true` flag when processing those files.
*
* @default [/\.([cm]?[jt]sx?|json)$/]
*/
ssr?: RegExp[]
/**
* First do a normal transform pipeline (targeting browser),
* then then do a SSR rewrite to run the code in Node.
* Vite plugins will receive `ssr: false` flag when processing those files.
*
* @default other than `ssr`
*/
web?: RegExp[]
}

/**
* Format options for snapshot testing.
*/
Expand Down
1 change: 0 additions & 1 deletion packages/vitest/src/types/general.ts
Expand Up @@ -23,7 +23,6 @@ export interface EnvironmentReturn {

export interface Environment {
name: string
transformMode?: 'web' | 'ssr'
setup(global: any, options: Record<string, any>): Awaitable<EnvironmentReturn>
}

Expand Down

0 comments on commit b6c4a6c

Please sign in to comment.