From 776779c30be72aed70345454260a57e39d511dcc Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Fri, 2 Jun 2023 18:10:06 +0200 Subject: [PATCH] chore: inject react-refresh --- packages/vitest/package.json | 1 + packages/vitest/setup/react-refresh.js | 8 +++++ .../src/node/plugins/commonPluginsHandler.ts | 29 +++++++++++++++++++ packages/vitest/src/node/plugins/index.ts | 2 ++ packages/vitest/src/node/plugins/workspace.ts | 2 ++ packages/vitest/src/runtime/execute.ts | 1 + packages/vitest/src/runtime/loader.ts | 5 ++-- packages/vitest/src/types/rpc.ts | 1 + packages/vitest/src/utils/config-helpers.ts | 22 ++++++++++++++ packages/web-worker/src/utils.ts | 6 ++-- 10 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 packages/vitest/setup/react-refresh.js create mode 100644 packages/vitest/src/node/plugins/commonPluginsHandler.ts diff --git a/packages/vitest/package.json b/packages/vitest/package.json index 25f4fb23e3fd..59dcb44f1fdf 100644 --- a/packages/vitest/package.json +++ b/packages/vitest/package.json @@ -83,6 +83,7 @@ }, "files": [ "dist", + "setup", "bin", "*.d.ts", "*.d.cts", diff --git a/packages/vitest/setup/react-refresh.js b/packages/vitest/setup/react-refresh.js new file mode 100644 index 000000000000..d1095c2f3475 --- /dev/null +++ b/packages/vitest/setup/react-refresh.js @@ -0,0 +1,8 @@ +if (typeof window !== 'undefined') { + const { default: RefreshRuntime } = await import('/@react-refresh') + + RefreshRuntime.injectIntoGlobalHook(window) + window.$RefreshReg$ = () => {} + window.$RefreshSig$ = () => type => type + window.__vite_plugin_react_preamble_installed__ = true +} diff --git a/packages/vitest/src/node/plugins/commonPluginsHandler.ts b/packages/vitest/src/node/plugins/commonPluginsHandler.ts new file mode 100644 index 000000000000..abfdec984328 --- /dev/null +++ b/packages/vitest/src/node/plugins/commonPluginsHandler.ts @@ -0,0 +1,29 @@ +import type { Plugin } from 'vite' +import { resolve } from 'pathe' +import { hasVitePlugin } from '../../utils/config-helpers' +import { distDir } from '../../paths' + +export function CommonPluginsHandler(): Plugin { + return { + name: 'vitest:common-plugins-enforcer', + enforce: 'post', + config: { + order: 'post', + async handler(config) { + const plugins = (config.plugins || []) + const hasReact = await hasVitePlugin(plugins, 'vite:react-babel') + if (hasReact) { + return { + test: { + deps: { + inline: [/vitest\/setup\/react-refresh.js/], + }, + // Since this is an official plugin, it should be OK to inline reac-refresh HRM logic + setupFiles: [resolve(distDir, '../setup/react-refresh.js')], + }, + } + } + }, + }, + } +} diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts index a43dab037c6f..4e7f7414eb23 100644 --- a/packages/vitest/src/node/plugins/index.ts +++ b/packages/vitest/src/node/plugins/index.ts @@ -14,6 +14,7 @@ import { CoverageTransform } from './coverageTransform' import { MocksPlugin } from './mocks' import { resolveOptimizerConfig } from './utils' import { VitestResolver } from './vitestResolver' +import { CommonPluginsHandler } from './commonPluginsHandler' export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('test')): Promise { const userConfig = deepMerge({}, options) as UserConfig @@ -210,6 +211,7 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('t : null, MocksPlugin(), VitestResolver(ctx), + CommonPluginsHandler(), ] .filter(notNullish) } diff --git a/packages/vitest/src/node/plugins/workspace.ts b/packages/vitest/src/node/plugins/workspace.ts index f9fd4dda3da7..6d3d94a0f9b1 100644 --- a/packages/vitest/src/node/plugins/workspace.ts +++ b/packages/vitest/src/node/plugins/workspace.ts @@ -12,6 +12,7 @@ import { GlobalSetupPlugin } from './globalSetup' import { MocksPlugin } from './mocks' import { resolveOptimizerConfig } from './utils' import { VitestResolver } from './vitestResolver' +import { CommonPluginsHandler } from './commonPluginsHandler' interface WorkspaceOptions extends UserWorkspaceConfig { root?: string @@ -152,5 +153,6 @@ export function WorkspaceVitestPlugin(project: WorkspaceProject, options: Worksp GlobalSetupPlugin(project, project.ctx.logger), MocksPlugin(), VitestResolver(project.ctx), + CommonPluginsHandler(), ] } diff --git a/packages/vitest/src/runtime/execute.ts b/packages/vitest/src/runtime/execute.ts index ec150ddf5f54..0a222e423a71 100644 --- a/packages/vitest/src/runtime/execute.ts +++ b/packages/vitest/src/runtime/execute.ts @@ -81,6 +81,7 @@ export async function startViteNode(ctx: ContextRPC) { }) const environment = await loadEnvironment(ctx.environment.name, executor) + ctx.environment.environment = environment transformMode = environment.transformMode ?? 'ssr' const { run } = await import(pathToFileURL(resolve(distDir, 'entry.js')).href) diff --git a/packages/vitest/src/runtime/loader.ts b/packages/vitest/src/runtime/loader.ts index f226ff761bbb..91bcd2d739ce 100644 --- a/packages/vitest/src/runtime/loader.ts +++ b/packages/vitest/src/runtime/loader.ts @@ -44,13 +44,14 @@ export const resolve: Resolver = async (url, context, next) => { const { parentURL } = context const state = getWorkerState() const resolver = state?.rpc.resolveId + const environment = state?.ctx.environment.environment - if (!parentURL || isNodeBuiltin(url) || !resolver) + if (!parentURL || isNodeBuiltin(url) || !resolver || !environment) return next(url, context, next) const id = normalizeModuleId(url) const importer = normalizeModuleId(parentURL) - const resolved = await resolver(id, importer, state.ctx.environment.name) + const resolved = await resolver(id, importer, environment.transformMode ?? 'ssr') let result: ResolveResult let filepath: string diff --git a/packages/vitest/src/types/rpc.ts b/packages/vitest/src/types/rpc.ts index 536eb3fc4274..9a14b253ab66 100644 --- a/packages/vitest/src/types/rpc.ts +++ b/packages/vitest/src/types/rpc.ts @@ -34,6 +34,7 @@ export interface RunnerRPC { export interface ContextTestEnvironment { name: VitestEnvironment + environment?: Environment options: EnvironmentOptions | null } diff --git a/packages/vitest/src/utils/config-helpers.ts b/packages/vitest/src/utils/config-helpers.ts index bd5f0b50fc97..a5d496a7ab7b 100644 --- a/packages/vitest/src/utils/config-helpers.ts +++ b/packages/vitest/src/utils/config-helpers.ts @@ -1,3 +1,4 @@ +import type { PluginOption } from 'vite' import type { BenchmarkBuiltinReporters, BuiltinReporters } from '../node/reporters' interface PotentialConfig { @@ -13,3 +14,24 @@ export function getOutputFile(config: PotentialConfig | undefined, reporter: Bui return config.outputFile[reporter] } + +async function isVitePlugin(plugin: PluginOption, name: string): Promise { + if (!plugin) + return false + if (Array.isArray(plugin)) + return hasVitePlugin(plugin, name) + if (plugin instanceof Promise) + return isVitePlugin(await plugin, name) + if (typeof plugin === 'object') + return plugin.name === name + return false +} + +export async function hasVitePlugin(plugins: PluginOption[], name: string): Promise { + for (const plugin of plugins) { + if (await isVitePlugin(plugin, name)) + return true + } + + return false +} diff --git a/packages/web-worker/src/utils.ts b/packages/web-worker/src/utils.ts index 9a59d4101e5c..758b357a46b4 100644 --- a/packages/web-worker/src/utils.ts +++ b/packages/web-worker/src/utils.ts @@ -61,14 +61,14 @@ export function createMessageEvent(data: any, transferOrOptions: StructuredSeria } export function getRunnerOptions(): any { - const { config, ctx, rpc, mockMap, moduleCache } = getWorkerState() + const { config, rpc, mockMap, moduleCache } = getWorkerState() return { fetchModule(id: string) { - return rpc.fetch(id, ctx.environment.name) + return rpc.fetch(id, 'web') }, resolveId(id: string, importer?: string) { - return rpc.resolveId(id, importer, ctx.environment.name) + return rpc.resolveId(id, importer, 'web') }, moduleCache, mockMap,