diff --git a/docs/guide/browser/context.md b/docs/guide/browser/context.md index 7ef22cd13fd5..097dd4f87d7d 100644 --- a/docs/guide/browser/context.md +++ b/docs/guide/browser/context.md @@ -67,7 +67,7 @@ export const page: { /** * Serialized test config. */ - config: ResolvedConfig + config: SerializedConfig /** * Change the size of iframe's viewport. */ diff --git a/packages/browser/context.d.ts b/packages/browser/context.d.ts index 7ea085dc1a3c..6f755e3aa260 100644 --- a/packages/browser/context.d.ts +++ b/packages/browser/context.d.ts @@ -1,4 +1,4 @@ -import type { ResolvedConfig } from 'vitest' +import type { SerializedConfig } from 'vitest' export type BufferEncoding = | 'ascii' @@ -253,7 +253,7 @@ export interface BrowserPage { /** * Serialized test config. */ - config: ResolvedConfig + config: SerializedConfig /** * Change the size of iframe's viewport. */ diff --git a/packages/browser/src/client/orchestrator.ts b/packages/browser/src/client/orchestrator.ts index 589856491dd2..975048373c40 100644 --- a/packages/browser/src/client/orchestrator.ts +++ b/packages/browser/src/client/orchestrator.ts @@ -1,8 +1,8 @@ -import type { ResolvedConfig } from 'vitest' import { channel, client } from '@vitest/browser/client' import { generateHash } from '@vitest/runner/utils' import { type GlobalChannelIncomingEvent, type IframeChannelEvent, type IframeChannelIncomingEvent, globalChannel } from '@vitest/browser/client' import { relative } from 'pathe' +import type { SerializedConfig } from 'vitest' import { getBrowserState, getConfig } from './utils' import { getUiAPI } from './ui' import { createModuleMocker } from './tester/msw' @@ -230,7 +230,7 @@ async function done() { await client.rpc.finishBrowserTests(getBrowserState().contextId) } -async function getContainer(config: ResolvedConfig): Promise { +async function getContainer(config: SerializedConfig): Promise { if (config.browser.ui) { const element = document.querySelector('#tester-ui') if (!element) { diff --git a/packages/browser/src/client/tester/runner.ts b/packages/browser/src/client/tester/runner.ts index ff4212c73ff2..90eab69ce85a 100644 --- a/packages/browser/src/client/tester/runner.ts +++ b/packages/browser/src/client/tester/runner.ts @@ -1,5 +1,5 @@ import type { CancelReason, File, Suite, Task, TaskResultPack, VitestRunner } from '@vitest/runner' -import type { ResolvedConfig, WorkerGlobalState } from 'vitest' +import type { SerializedConfig, WorkerGlobalState } from 'vitest' import type { VitestExecutor } from 'vitest/execute' import { NodeBenchmarkRunner, VitestTestRunner } from 'vitest/runners' import { loadDiffConfig, loadSnapshotSerializers, takeCoverageInsideWorker } from 'vitest/browser' @@ -12,7 +12,7 @@ import { rpc } from './rpc' import type { VitestBrowserClientMocker } from './mocker' interface BrowserRunnerOptions { - config: ResolvedConfig + config: SerializedConfig } export const browserHashMap = new Map< @@ -25,13 +25,13 @@ interface CoverageHandler { } export function createBrowserRunner( - runnerClass: { new (config: ResolvedConfig): VitestRunner }, + runnerClass: { new (config: SerializedConfig): VitestRunner }, mocker: VitestBrowserClientMocker, state: WorkerGlobalState, coverageModule: CoverageHandler | null, ): { new (options: BrowserRunnerOptions): VitestRunner } { return class BrowserTestRunner extends runnerClass implements VitestRunner { - public config: ResolvedConfig + public config: SerializedConfig hashMap = browserHashMap public sourceMapCache = new Map() @@ -140,7 +140,7 @@ let cachedRunner: VitestRunner | null = null export async function initiateRunner( state: WorkerGlobalState, mocker: VitestBrowserClientMocker, - config: ResolvedConfig, + config: SerializedConfig, ) { if (cachedRunner) { return cachedRunner diff --git a/packages/browser/src/client/utils.ts b/packages/browser/src/client/utils.ts index 457cb495bd1f..01480e6620c4 100644 --- a/packages/browser/src/client/utils.ts +++ b/packages/browser/src/client/utils.ts @@ -1,4 +1,4 @@ -import type { ResolvedConfig, WorkerGlobalState } from 'vitest' +import type { SerializedConfig, WorkerGlobalState } from 'vitest' export async function importId(id: string) { const name = `/@id/${id}`.replace(/\\/g, '/') @@ -10,7 +10,7 @@ export async function importFs(id: string) { return getBrowserState().wrapModule(() => import(/* @vite-ignore */ name)) } -export function getConfig(): ResolvedConfig { +export function getConfig(): SerializedConfig { return getBrowserState().config } @@ -18,7 +18,7 @@ export interface BrowserRunnerState { files: string[] runningFiles: string[] moduleCache: WorkerGlobalState['moduleCache'] - config: ResolvedConfig + config: SerializedConfig provider: string viteConfig: { root: string diff --git a/packages/browser/src/node/commands/screenshot.ts b/packages/browser/src/node/commands/screenshot.ts index d81b0932b7d9..6426a5650689 100644 --- a/packages/browser/src/node/commands/screenshot.ts +++ b/packages/browser/src/node/commands/screenshot.ts @@ -1,8 +1,7 @@ import { mkdir } from 'node:fs/promises' import { normalize } from 'node:path' -import type { BrowserCommand } from 'vitest/node' +import type { BrowserCommand, ResolvedConfig } from 'vitest/node' import { basename, dirname, relative, resolve } from 'pathe' -import type { ResolvedConfig } from 'vitest' import type { ScreenshotOptions } from '../../../context' import { PlaywrightBrowserProvider } from '../providers/playwright' import { WebdriverBrowserProvider } from '../providers/webdriver' diff --git a/packages/browser/src/node/resolveMock.ts b/packages/browser/src/node/resolveMock.ts index 6326883d9cb3..fc41c8ebf894 100644 --- a/packages/browser/src/node/resolveMock.ts +++ b/packages/browser/src/node/resolveMock.ts @@ -2,9 +2,8 @@ import { existsSync, readFileSync, readdirSync } from 'node:fs' import { builtinModules } from 'node:module' import { basename, dirname, extname, isAbsolute, join, resolve } from 'pathe' import type { PartialResolvedId } from 'rollup' -import type { ResolvedConfig } from 'vitest' +import type { ResolvedConfig, WorkspaceProject } from 'vitest/node' import type { ResolvedConfig as ViteConfig } from 'vite' -import type { WorkspaceProject } from 'vitest/node' export async function resolveMock( project: WorkspaceProject, diff --git a/packages/browser/src/node/server.ts b/packages/browser/src/node/server.ts index ca7bc8173d6a..b3ac794344a3 100644 --- a/packages/browser/src/node/server.ts +++ b/packages/browser/src/node/server.ts @@ -11,8 +11,8 @@ import type { import { join, resolve } from 'pathe' import type { ErrorWithDiff } from '@vitest/utils' import { slash } from '@vitest/utils' -import type { ResolvedConfig } from 'vitest' import { type StackTraceParserOptions, parseErrorStacktrace, parseStacktrace } from '@vitest/utils/source-map' +import type { SerializedConfig } from 'vitest' import { BrowserServerState } from './state' import { getBrowserProvider } from './utils' import { BrowserServerCDPHandler } from './cdp' @@ -224,7 +224,7 @@ export class BrowserServer implements IBrowserServer { } } -function wrapConfig(config: ResolvedConfig): ResolvedConfig { +function wrapConfig(config: SerializedConfig): SerializedConfig { return { ...config, // workaround RegExp serialization diff --git a/packages/browser/src/node/serverOrchestrator.ts b/packages/browser/src/node/serverOrchestrator.ts index cffe6c21d3c8..cad63b0c591d 100644 --- a/packages/browser/src/node/serverOrchestrator.ts +++ b/packages/browser/src/node/serverOrchestrator.ts @@ -17,14 +17,13 @@ export async function resolveOrchestrator( const files = server.state.getContext(contextId!)?.files ?? [] - const config = server.getSerializableConfig() const injectorJs = typeof server.injectorJs === 'string' ? server.injectorJs : await server.injectorJs const injector = replacer(injectorJs, { __VITEST_PROVIDER__: JSON.stringify(server.provider.name), - __VITEST_CONFIG__: JSON.stringify(config), + __VITEST_CONFIG__: JSON.stringify(server.getSerializableConfig()), __VITEST_VITE_CONFIG__: JSON.stringify({ root: server.vite.config.root, }), diff --git a/packages/browser/src/node/serverTester.ts b/packages/browser/src/node/serverTester.ts index 427b0e733139..517c69892812 100644 --- a/packages/browser/src/node/serverTester.ts +++ b/packages/browser/src/node/serverTester.ts @@ -38,11 +38,9 @@ export async function resolveTester( ? server.injectorJs : await server.injectorJs - const config = server.getSerializableConfig() - const injector = replacer(injectorJs, { __VITEST_PROVIDER__: JSON.stringify(server.provider.name), - __VITEST_CONFIG__: JSON.stringify(config), + __VITEST_CONFIG__: JSON.stringify(server.getSerializableConfig()), __VITEST_FILES__: JSON.stringify(files), __VITEST_VITE_CONFIG__: JSON.stringify({ root: server.vite.config.root, @@ -57,7 +55,7 @@ export async function resolveTester( const testerScripts = await server.formatScripts( project.config.browser.testerScripts, ) - const clientScript = `` + const clientScript = `` const stateJs = typeof server.stateJs === 'string' ? server.stateJs : await server.stateJs diff --git a/packages/runner/src/types/runner.ts b/packages/runner/src/types/runner.ts index 3c237fae1e9e..8fa28abb680c 100644 --- a/packages/runner/src/types/runner.ts +++ b/packages/runner/src/types/runner.ts @@ -14,8 +14,8 @@ import type { export interface VitestRunnerConfig { root: string - setupFiles: string[] | string - name: string + setupFiles: string[] + name?: string passWithNoTests: boolean testNamePattern?: RegExp allowOnly?: boolean diff --git a/packages/runner/src/utils/collect.ts b/packages/runner/src/utils/collect.ts index 376994ca9b0f..5f992fef962e 100644 --- a/packages/runner/src/utils/collect.ts +++ b/packages/runner/src/utils/collect.ts @@ -117,7 +117,7 @@ export function calculateSuiteHash(parent: Suite): void { export function createFileTask( filepath: string, root: string, - projectName: string, + projectName: string | undefined, pool?: string, ): File { const path = relative(root, filepath) diff --git a/packages/ui/client/composables/client/index.ts b/packages/ui/client/composables/client/index.ts index 56ed67f154b5..f590b38dcf97 100644 --- a/packages/ui/client/composables/client/index.ts +++ b/packages/ui/client/composables/client/index.ts @@ -1,6 +1,6 @@ import { createClient, getTasks } from '@vitest/ws-client' import type { WebSocketStatus } from '@vueuse/core' -import type { File, ResolvedConfig, TaskResultPack } from 'vitest' +import type { File, SerializedConfig, TaskResultPack } from 'vitest' import { reactive as reactiveVue } from 'vue' import { createFileTask } from '@vitest/runner/utils' import type { BrowserRunnerState } from '../../../types' @@ -45,7 +45,7 @@ export const client = (function createVitestClient() { } })() -export const config = shallowRef({} as any) +export const config = shallowRef({} as any) export const status = ref('CONNECTING') export const current = computed(() => { diff --git a/packages/ui/client/composables/client/static.ts b/packages/ui/client/composables/client/static.ts index abf3e778fc95..cc32711984fa 100644 --- a/packages/ui/client/composables/client/static.ts +++ b/packages/ui/client/composables/client/static.ts @@ -3,7 +3,7 @@ import type { VitestClient } from '@vitest/ws-client' import type { File, ModuleGraphData, - ResolvedConfig, + SerializedConfig, WebSocketEvents, WebSocketHandlers, } from 'vitest' @@ -14,7 +14,7 @@ import { StateManager } from '../../../../vitest/src/node/state' interface HTMLReportMetadata { paths: string[] files: File[] - config: ResolvedConfig + config: SerializedConfig moduleGraph: Record> unhandledErrors: unknown[] // filename -> source diff --git a/packages/ui/client/composables/navigation.ts b/packages/ui/client/composables/navigation.ts index c5cf8e28af44..353f73ef50e0 100644 --- a/packages/ui/client/composables/navigation.ts +++ b/packages/ui/client/composables/navigation.ts @@ -12,9 +12,7 @@ export const coverageConfigured = computed(() => coverage.value?.enabled) export const coverageEnabled = computed(() => { return ( coverageConfigured.value - && coverage.value.reporter - .map(([reporterName]) => reporterName) - .includes('html') + && !!coverage.value.htmlReporter ) }) export const detailSizes = useLocalStorage<[left: number, right: number]>( @@ -31,16 +29,10 @@ export const detailSizes = useLocalStorage<[left: number, right: number]>( export const coverageUrl = computed(() => { if (coverageEnabled.value) { const idx = coverage.value!.reportsDirectory.lastIndexOf('/') - const htmlReporter = coverage.value!.reporter.find((reporter) => { - if (reporter[0] !== 'html') { - return undefined - } - - return reporter - }) - return htmlReporter && 'subdir' in htmlReporter[1] + const htmlReporterSubdir = coverage.value!.htmlReporter?.subdir + return htmlReporterSubdir ? `/${coverage.value!.reportsDirectory.slice(idx + 1)}/${ - htmlReporter[1].subdir + htmlReporterSubdir }/index.html` : `/${coverage.value!.reportsDirectory.slice(idx + 1)}/index.html` } diff --git a/packages/ui/node/reporter.ts b/packages/ui/node/reporter.ts index 1389affefca9..7398b9c7578b 100644 --- a/packages/ui/node/reporter.ts +++ b/packages/ui/node/reporter.ts @@ -10,7 +10,7 @@ import type { File, ModuleGraphData, Reporter, - ResolvedConfig, + SerializedConfig, Vitest, } from 'vitest' import type { HTMLOptions } from 'vitest/node' @@ -35,7 +35,7 @@ function getOutputFile(config: PotentialConfig | undefined) { interface HTMLReportData { paths: string[] files: File[] - config: ResolvedConfig + config: SerializedConfig moduleGraph: Record> unhandledErrors: unknown[] // filename -> source @@ -63,7 +63,7 @@ export default class HTMLReporter implements Reporter { const result: HTMLReportData = { paths: this.ctx.state.getPaths(), files: this.ctx.state.getFiles(), - config: this.ctx.config, + config: this.ctx.getCoreWorkspaceProject().getSerializableConfig(), unhandledErrors: this.ctx.state.getUnhandledErrors(), moduleGraph: {}, sources: {}, diff --git a/packages/ui/types.ts b/packages/ui/types.ts index b90b49d89ef8..172d11eb9819 100644 --- a/packages/ui/types.ts +++ b/packages/ui/types.ts @@ -1,4 +1,4 @@ -import type { ResolvedConfig } from 'vitest' +import type { SerializedConfig } from 'vitest' export interface WSMessage { /** @@ -16,7 +16,7 @@ export type RunState = 'idle' | 'running' export interface BrowserRunnerState { files: string[] - config: ResolvedConfig + config: SerializedConfig type: 'orchestrator' wrapModule: (module: () => T) => T } diff --git a/packages/vitest/src/api/setup.ts b/packages/vitest/src/api/setup.ts index 69ee138e9b3a..c743b7afe436 100644 --- a/packages/vitest/src/api/setup.ts +++ b/packages/vitest/src/api/setup.ts @@ -83,7 +83,7 @@ export function setup(ctx: Vitest, _server?: ViteDevServer) { await ctx.rerunFiles(files) }, getConfig() { - return ctx.config + return ctx.getCoreWorkspaceProject().getSerializableConfig() }, async getTransformResult(projectName: string, id, browser = false) { const project = ctx.getProjectByName(projectName) diff --git a/packages/vitest/src/api/types.ts b/packages/vitest/src/api/types.ts index 749225e99103..3394b94ed6cd 100644 --- a/packages/vitest/src/api/types.ts +++ b/packages/vitest/src/api/types.ts @@ -4,7 +4,8 @@ import type { File, ModuleGraphData, Reporter, - ResolvedConfig, + SerializableSpec, + SerializedConfig, TaskResultPack, } from '../types' @@ -16,9 +17,9 @@ export interface WebSocketHandlers { onCollected: (files?: File[]) => Promise onTaskUpdate: (packs: TaskResultPack[]) => void getFiles: () => File[] - getTestFiles: () => Promise<[{ name: string; root: string }, file: string][]> + getTestFiles: () => Promise getPaths: () => string[] - getConfig: () => ResolvedConfig + getConfig: () => SerializedConfig getModuleGraph: ( projectName: string, id: string, diff --git a/packages/vitest/src/defaults.ts b/packages/vitest/src/defaults.ts index cd412103235e..96ff8cb7b3a6 100644 --- a/packages/vitest/src/defaults.ts +++ b/packages/vitest/src/defaults.ts @@ -106,6 +106,8 @@ const config = { clearMocks: false, restoreMocks: false, mockReset: false, + unstubGlobals: false, + unstubEnvs: false, include: defaultInclude, exclude: defaultExclude, teardownTimeout: 10000, diff --git a/packages/vitest/src/integrations/coverage.ts b/packages/vitest/src/integrations/coverage.ts index 499bf6168802..cbc6eb6dbcb1 100644 --- a/packages/vitest/src/integrations/coverage.ts +++ b/packages/vitest/src/integrations/coverage.ts @@ -1,5 +1,5 @@ +import type { SerializedCoverageConfig } from '../runtime/config' import type { - CoverageOptions, CoverageProvider, CoverageProviderModule, } from '../types' @@ -14,7 +14,7 @@ export const CoverageProviderMap: Record = { } async function resolveCoverageProviderModule( - options: CoverageOptions | undefined, + options: SerializedCoverageConfig | undefined, loader: Loader, ) { if (!options?.enabled || !options.provider) { @@ -40,7 +40,7 @@ async function resolveCoverageProviderModule( let customProviderModule try { - customProviderModule = await loader.executeId(options.customProviderModule) + customProviderModule = await loader.executeId(options.customProviderModule!) } catch (error) { throw new Error( @@ -59,7 +59,7 @@ async function resolveCoverageProviderModule( } export async function getCoverageProvider( - options: CoverageOptions | undefined, + options: SerializedCoverageConfig | undefined, loader: Loader, ): Promise { const coverageModule = await resolveCoverageProviderModule(options, loader) @@ -72,7 +72,7 @@ export async function getCoverageProvider( } export async function startCoverageInsideWorker( - options: CoverageOptions | undefined, + options: SerializedCoverageConfig | undefined, loader: Loader, ) { const coverageModule = await resolveCoverageProviderModule(options, loader) @@ -85,7 +85,7 @@ export async function startCoverageInsideWorker( } export async function takeCoverageInsideWorker( - options: CoverageOptions | undefined, + options: SerializedCoverageConfig | undefined, loader: Loader, ) { const coverageModule = await resolveCoverageProviderModule(options, loader) @@ -98,7 +98,7 @@ export async function takeCoverageInsideWorker( } export async function stopCoverageInsideWorker( - options: CoverageOptions | undefined, + options: SerializedCoverageConfig | undefined, loader: Loader, ) { const coverageModule = await resolveCoverageProviderModule(options, loader) diff --git a/packages/vitest/src/integrations/snapshot/environments/resolveSnapshotEnvironment.ts b/packages/vitest/src/integrations/snapshot/environments/resolveSnapshotEnvironment.ts index 80251008a1e1..9951bda91475 100644 --- a/packages/vitest/src/integrations/snapshot/environments/resolveSnapshotEnvironment.ts +++ b/packages/vitest/src/integrations/snapshot/environments/resolveSnapshotEnvironment.ts @@ -1,9 +1,9 @@ import type { SnapshotEnvironment } from '@vitest/snapshot/environment' import type { VitestExecutor } from '../../../runtime/execute' -import type { ResolvedConfig } from '../../../types' +import type { SerializedConfig } from '../../../runtime/config' export async function resolveSnapshotEnvironment( - config: ResolvedConfig, + config: SerializedConfig, executor: VitestExecutor, ): Promise { if (!config.snapshotEnvironment) { diff --git a/packages/vitest/src/integrations/vi.ts b/packages/vitest/src/integrations/vi.ts index 51828778e0f4..1f49ed2019c3 100644 --- a/packages/vitest/src/integrations/vi.ts +++ b/packages/vitest/src/integrations/vi.ts @@ -2,7 +2,7 @@ import type { FakeTimerInstallOpts } from '@sinonjs/fake-timers' import { assertTypes, createSimpleStackTrace } from '@vitest/utils' import { parseSingleStack } from '../utils/source-map' import type { VitestMocker } from '../runtime/mocker' -import type { ResolvedConfig, RuntimeConfig } from '../types' +import type { RuntimeOptions, SerializedConfig } from '../runtime/config' import type { MockFactoryWithHelper } from '../types/mocker' import { getWorkerState } from '../utils/global' import { resetModules, waitForImportsToResolve } from '../utils/modules' @@ -373,7 +373,7 @@ export interface VitestUtils { /** * Updates runtime config. You can only change values that are used when executing tests. */ - setConfig: (config: RuntimeConfig) => void + setConfig: (config: RuntimeOptions) => void /** * If config was changed with `vi.setConfig`, this will reset it to the original state. @@ -383,7 +383,7 @@ export interface VitestUtils { function createVitest(): VitestUtils { let _mockedDate: Date | null = null - let _config: null | ResolvedConfig = null + let _config: null | SerializedConfig = null function _mocker(): VitestMocker { // @ts-expect-error injected by vite-nide @@ -712,7 +712,7 @@ function createVitest(): VitestUtils { return waitForImportsToResolve() }, - setConfig(config: RuntimeConfig) { + setConfig(config: RuntimeOptions) { if (!_config) { _config = { ...workerState.config } } diff --git a/packages/vitest/src/node/cache/results.ts b/packages/vitest/src/node/cache/results.ts index 20fb68dde2c1..84f2e09794a6 100644 --- a/packages/vitest/src/node/cache/results.ts +++ b/packages/vitest/src/node/cache/results.ts @@ -1,6 +1,7 @@ import fs from 'node:fs' import { dirname, relative, resolve } from 'pathe' -import type { File, ResolvedConfig } from '../../types' +import type { File } from '../../types' +import type { ResolvedConfig } from '../../types/config' export interface SuiteResultCache { failed: boolean diff --git a/packages/vitest/src/node/config.ts b/packages/vitest/src/node/config/resolveConfig.ts similarity index 97% rename from packages/vitest/src/node/config.ts rename to packages/vitest/src/node/config/resolveConfig.ts index a3a0cd1e0257..44728cfe7cda 100644 --- a/packages/vitest/src/node/config.ts +++ b/packages/vitest/src/node/config/resolveConfig.ts @@ -7,23 +7,23 @@ import type { ResolvedConfig, UserConfig, VitestRunMode, -} from '../types' +} from '../../types/config' import { defaultBrowserPort, defaultInspectPort, defaultPort, extraInlineDeps, -} from '../constants' -import { benchmarkConfigDefaults, configDefaults } from '../defaults' -import { isCI, stdProvider, toArray } from '../utils' -import type { BuiltinPool, ForksOptions, PoolOptions, ThreadsOptions } from '../types/pool-options' -import { getWorkersCountByPercentage } from '../utils/workers' -import { VitestCache } from './cache' -import { BaseSequencer } from './sequencers/BaseSequencer' -import { RandomSequencer } from './sequencers/RandomSequencer' -import type { BenchmarkBuiltinReporters } from './reporters' -import { builtinPools } from './pool' -import type { Logger } from './logger' +} from '../../constants' +import { benchmarkConfigDefaults, configDefaults } from '../../defaults' +import { isCI, stdProvider, toArray } from '../../utils' +import type { BuiltinPool, ForksOptions, PoolOptions, ThreadsOptions } from '../../types/pool-options' +import { getWorkersCountByPercentage } from '../../utils/workers' +import { VitestCache } from '../cache' +import { BaseSequencer } from '../sequencers/BaseSequencer' +import { RandomSequencer } from '../sequencers/RandomSequencer' +import type { BenchmarkBuiltinReporters } from '../reporters' +import { builtinPools } from '../pool' +import type { Logger } from '../logger' function resolvePath(path: string, root: string) { return normalize( diff --git a/packages/vitest/src/node/config/serializeConfig.ts b/packages/vitest/src/node/config/serializeConfig.ts new file mode 100644 index 000000000000..9d1e0b0ef6a5 --- /dev/null +++ b/packages/vitest/src/node/config/serializeConfig.ts @@ -0,0 +1,161 @@ +import type { ResolvedConfig as ViteConfig } from 'vite' +import type { ResolvedConfig, SerializedConfig } from '../../types/config' + +export function serializeConfig( + config: ResolvedConfig, + coreConfig: ResolvedConfig, + viteConfig: ViteConfig | undefined, +): SerializedConfig { + const optimizer = config.deps?.optimizer + const poolOptions = config.poolOptions + + // Resolve from server.config to avoid comparing against default value + const isolate = viteConfig?.test?.isolate + + return { + // TODO: remove functions from environmentOptions + environmentOptions: config.environmentOptions, + mode: config.mode, + isolate: config.isolate, + base: config.base, + logHeapUsage: config.logHeapUsage, + runner: config.runner, + bail: config.bail, + defines: config.defines, + chaiConfig: config.chaiConfig, + setupFiles: config.setupFiles, + allowOnly: config.allowOnly, + testTimeout: config.testTimeout, + testNamePattern: config.testNamePattern, + hookTimeout: config.hookTimeout, + clearMocks: config.clearMocks, + mockReset: config.mockReset, + restoreMocks: config.restoreMocks, + unstubEnvs: config.unstubEnvs, + unstubGlobals: config.unstubGlobals, + maxConcurrency: config.maxConcurrency, + pool: config.pool, + expect: config.expect, + snapshotSerializers: config.snapshotSerializers, + diff: config.diff, + retry: config.retry, + disableConsoleIntercept: config.disableConsoleIntercept, + root: config.root, + name: config.name, + globals: config.globals, + snapshotEnvironment: config.snapshotEnvironment, + passWithNoTests: config.passWithNoTests, + coverage: ((coverage) => { + const htmlReporter = coverage.reporter.find(([reporterName]) => reporterName === 'html') as [ + 'html', + { subdir?: string }, + ] | undefined + const subdir = htmlReporter && htmlReporter[1]?.subdir + return { + reportsDirectory: coverage.reportsDirectory, + provider: coverage.provider, + enabled: coverage.enabled, + htmlReporter: htmlReporter + ? { subdir } + : undefined, + customProviderModule: 'customProviderModule' in coverage + ? coverage.customProviderModule + : undefined, + } + })(config.coverage), + fakeTimers: config.fakeTimers, + poolOptions: { + forks: { + singleFork: + poolOptions?.forks?.singleFork + ?? coreConfig.poolOptions?.forks?.singleFork + ?? false, + isolate: + poolOptions?.forks?.isolate + ?? isolate + ?? coreConfig.poolOptions?.forks?.isolate + ?? true, + }, + threads: { + singleThread: + poolOptions?.threads?.singleThread + ?? coreConfig.poolOptions?.threads?.singleThread + ?? false, + isolate: + poolOptions?.threads?.isolate + ?? isolate + ?? coreConfig.poolOptions?.threads?.isolate + ?? true, + }, + vmThreads: { + singleThread: + poolOptions?.vmThreads?.singleThread + ?? coreConfig.poolOptions?.vmThreads?.singleThread + ?? false, + }, + vmForks: { + singleFork: + poolOptions?.vmForks?.singleFork + ?? coreConfig.poolOptions?.vmForks?.singleFork + ?? false, + }, + }, + deps: { + web: config.deps.web || {}, + optimizer: { + web: { + enabled: optimizer?.web?.enabled ?? true, + }, + ssr: { + enabled: optimizer?.ssr?.enabled ?? true, + }, + }, + interopDefault: config.deps.interopDefault, + moduleDirectories: config.deps.moduleDirectories, + }, + snapshotOptions: { + // TODO: store it differently, not on the config + snapshotEnvironment: undefined!, + updateSnapshot: coreConfig.snapshotOptions.updateSnapshot, + snapshotFormat: { + ...coreConfig.snapshotOptions.snapshotFormat, + compareKeys: undefined, + }, + expand: + config.snapshotOptions.expand + ?? coreConfig.snapshotOptions.expand, + }, + sequence: { + shuffle: coreConfig.sequence.shuffle, + concurrent: coreConfig.sequence.concurrent, + seed: coreConfig.sequence.seed, + hooks: coreConfig.sequence.hooks, + setupFiles: coreConfig.sequence.setupFiles, + }, + inspect: coreConfig.inspect, + inspectBrk: coreConfig.inspectBrk, + inspector: coreConfig.inspector, + watch: config.watch, + includeTaskLocation: + config.includeTaskLocation + ?? coreConfig.includeTaskLocation, + env: { + ...viteConfig?.env, + ...config.env, + }, + browser: ((browser) => { + return { + name: browser.name, + headless: browser.headless, + isolate: browser.isolate, + fileParallelism: browser.fileParallelism, + ui: browser.ui, + viewport: browser.viewport, + screenshotFailures: browser.screenshotFailures, + } + })(config.browser), + standalone: config.standalone, + printConsoleTrace: + config.printConsoleTrace ?? coreConfig.printConsoleTrace, + } +} diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts index 8d3b88e2dd6e..b4f328ed7d41 100644 --- a/packages/vitest/src/node/core.ts +++ b/packages/vitest/src/node/core.ts @@ -18,11 +18,12 @@ import { getCoverageProvider } from '../integrations/coverage' import { CONFIG_NAMES, configFiles, workspacesFiles as workspaceFiles } from '../constants' import { rootDir } from '../paths' import { WebSocketReporter } from '../api/setup' +import type { SerializedCoverageConfig } from '../runtime/config' import { createPool } from './pool' import type { ProcessPool, WorkspaceSpec } from './pool' import { createBenchmarkReporters, createReporters } from './reporters/utils' import { StateManager } from './state' -import { resolveConfig } from './config' +import { resolveConfig } from './config/resolveConfig' import { Logger } from './logger' import { VitestCache } from './cache' import { WorkspaceProject, initializeProject } from './workspace' @@ -396,7 +397,10 @@ export class Vitest { if (this.coverageProvider !== undefined) { return } - this.coverageProvider = await getCoverageProvider(this.config.coverage, this.runner) + this.coverageProvider = await getCoverageProvider( + this.config.coverage as unknown as SerializedCoverageConfig, + this.runner, + ) if (this.coverageProvider) { await this.coverageProvider.initialize(this) this.config.coverage = this.coverageProvider.resolveOptions() diff --git a/packages/vitest/src/node/index.ts b/packages/vitest/src/node/index.ts index 4c903849511f..77883c113e4c 100644 --- a/packages/vitest/src/node/index.ts +++ b/packages/vitest/src/node/index.ts @@ -12,7 +12,7 @@ export { getFilePoolName } from './pool' export { VitestPackageInstaller } from './packageInstaller' export { createDebugger } from '../utils/debugger' export { resolveFsAllow } from './plugins/utils' -export { resolveApiServerConfig, resolveConfig } from './config' +export { resolveApiServerConfig, resolveConfig } from './config/resolveConfig' export { GitNotFoundError, FilesNotFoundError as TestsNotFoundError } from './errors' @@ -39,6 +39,7 @@ export type { BrowserServerState, BrowserServerStateContext, BrowserOrchestrator, + BrowserConfigOptions, } from '../types/browser' export type { JsonOptions } from './reporters/json' export type { JUnitOptions } from './reporters/junit' @@ -46,3 +47,27 @@ export type { HTMLOptions } from './reporters/html' export { isFileServingAllowed, createServer, parseAst, parseAstAsync } from 'vite' export type * as Vite from 'vite' + +export type { + SequenceHooks, + SequenceSetupFiles, + BuiltinEnvironment, + VitestEnvironment, + Pool, + PoolOptions, + CSSModuleScopeStrategy, + ApiConfig, + JSDOMOptions, + HappyDOMOptions, + EnvironmentOptions, + VitestRunMode, + DepsOptimizationOptions, + TransformModePatterns, + InlineConfig, + TypecheckConfig, + UserConfig, + ResolvedConfig, + ProjectConfig, + UserWorkspaceConfig, + RuntimeConfig, +} from '../types/config' diff --git a/packages/vitest/src/node/plugins/cssEnabler.ts b/packages/vitest/src/node/plugins/cssEnabler.ts index b9f7e4bcbc2a..6cfebe072b06 100644 --- a/packages/vitest/src/node/plugins/cssEnabler.ts +++ b/packages/vitest/src/node/plugins/cssEnabler.ts @@ -1,7 +1,7 @@ import { relative } from 'pathe' import type { Plugin as VitePlugin } from 'vite' import { generateCssFilenameHash } from '../../integrations/css/css-modules' -import type { CSSModuleScopeStrategy, ResolvedConfig } from '../../types' +import type { CSSModuleScopeStrategy, ResolvedConfig } from '../../types/config' import { toArray } from '../../utils' const cssLangs = '\\.(?:css|less|sass|scss|styl|stylus|pcss|postcss)(?:$|\\?)' diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts index dcf6a28987ae..dcbc807b125d 100644 --- a/packages/vitest/src/node/plugins/index.ts +++ b/packages/vitest/src/node/plugins/index.ts @@ -1,14 +1,14 @@ import type { UserConfig as ViteConfig, Plugin as VitePlugin } from 'vite' import { relative } from 'pathe' import { configDefaults, coverageConfigDefaults } from '../../defaults' -import type { ResolvedConfig, UserConfig } from '../../types' +import type { ResolvedConfig, UserConfig } from '../../types/config' import { deepMerge, notNullish, removeUndefinedValues, toArray, } from '../../utils' -import { resolveApiServerConfig } from '../config' +import { resolveApiServerConfig } from '../config/resolveConfig' import { Vitest } from '../core' import { generateScopedClassName } from '../../integrations/css/css-modules' import { defaultPort } from '../../constants' diff --git a/packages/vitest/src/node/plugins/utils.ts b/packages/vitest/src/node/plugins/utils.ts index 84094af2754c..10bc534c0b08 100644 --- a/packages/vitest/src/node/plugins/utils.ts +++ b/packages/vitest/src/node/plugins/utils.ts @@ -5,7 +5,7 @@ import type { UserConfig as ViteConfig, } from 'vite' import { dirname } from 'pathe' -import type { DepsOptimizationOptions, InlineConfig } from '../../types' +import type { DepsOptimizationOptions, InlineConfig } from '../../types/config' import { VitestCache } from '../cache' import { rootDir } from '../../paths' diff --git a/packages/vitest/src/node/plugins/workspace.ts b/packages/vitest/src/node/plugins/workspace.ts index ff1c79716d4e..7dc2cd3f1ca5 100644 --- a/packages/vitest/src/node/plugins/workspace.ts +++ b/packages/vitest/src/node/plugins/workspace.ts @@ -5,7 +5,7 @@ import { configDefaults } from '../../defaults' import { generateScopedClassName } from '../../integrations/css/css-modules' import { deepMerge } from '../../utils/base' import type { WorkspaceProject } from '../workspace' -import type { ResolvedConfig, UserWorkspaceConfig } from '../../types' +import type { ResolvedConfig, UserWorkspaceConfig } from '../../types/config' import { CoverageTransform } from './coverageTransform' import { CSSEnablerPlugin } from './cssEnabler' import { SsrReplacerPlugin } from './ssrReplacer' diff --git a/packages/vitest/src/node/pools/forks.ts b/packages/vitest/src/node/pools/forks.ts index 5d54d911bef7..797106d99326 100644 --- a/packages/vitest/src/node/pools/forks.ts +++ b/packages/vitest/src/node/pools/forks.ts @@ -7,7 +7,6 @@ import { createBirpc } from 'birpc' import type { ContextRPC, ContextTestEnvironment, - ResolvedConfig, RunnerRPC, RuntimeRPC, Vitest, @@ -17,6 +16,7 @@ import type { WorkspaceProject } from '../workspace' import { envsOrder, groupFilesByEnv } from '../../utils/test-helpers' import { wrapSerializableConfig } from '../../utils/config-helpers' import { groupBy, resolve } from '../../utils' +import type { SerializedConfig } from '../../types/config' import { createMethodsRPC } from './rpc' function createChildProcessChannel(project: WorkspaceProject) { @@ -103,7 +103,7 @@ export function createForksPool( async function runFiles( project: WorkspaceProject, - config: ResolvedConfig, + config: SerializedConfig, files: string[], environment: ContextTestEnvironment, invalidates: string[] = [], @@ -156,8 +156,8 @@ export function createForksPool( // Cancel pending tasks from pool when possible ctx.onCancel(() => pool.cancelPendingTasks()) - const configs = new Map() - const getConfig = (project: WorkspaceProject): ResolvedConfig => { + const configs = new Map() + const getConfig = (project: WorkspaceProject): SerializedConfig => { if (configs.has(project)) { return configs.get(project)! } diff --git a/packages/vitest/src/node/pools/threads.ts b/packages/vitest/src/node/pools/threads.ts index 0fcf5c02ab97..02f28bb3f989 100644 --- a/packages/vitest/src/node/pools/threads.ts +++ b/packages/vitest/src/node/pools/threads.ts @@ -6,7 +6,6 @@ import Tinypool from 'tinypool' import { resolve } from 'pathe' import type { ContextTestEnvironment, - ResolvedConfig, RunnerRPC, RuntimeRPC, Vitest, @@ -16,6 +15,7 @@ import type { PoolProcessOptions, ProcessPool, RunWithFiles } from '../pool' import { envsOrder, groupFilesByEnv } from '../../utils/test-helpers' import { AggregateError, groupBy } from '../../utils/base' import type { WorkspaceProject } from '../workspace' +import type { SerializedConfig } from '../../types/config' import { createMethodsRPC } from './rpc' function createWorkerChannel(project: WorkspaceProject) { @@ -97,7 +97,7 @@ export function createThreadsPool( async function runFiles( project: WorkspaceProject, - config: ResolvedConfig, + config: SerializedConfig, files: string[], environment: ContextTestEnvironment, invalidates: string[] = [], @@ -154,8 +154,8 @@ export function createThreadsPool( // Cancel pending tasks from pool when possible ctx.onCancel(() => pool.cancelPendingTasks()) - const configs = new Map() - const getConfig = (project: WorkspaceProject): ResolvedConfig => { + const configs = new Map() + const getConfig = (project: WorkspaceProject): SerializedConfig => { if (configs.has(project)) { return configs.get(project)! } diff --git a/packages/vitest/src/node/pools/vmForks.ts b/packages/vitest/src/node/pools/vmForks.ts index c34bdb990bab..03ff54ea7f39 100644 --- a/packages/vitest/src/node/pools/vmForks.ts +++ b/packages/vitest/src/node/pools/vmForks.ts @@ -20,6 +20,7 @@ import { AggregateError } from '../../utils/base' import type { WorkspaceProject } from '../workspace' import { getWorkerMemoryLimit, stringToBytes } from '../../utils/memory-limit' import { wrapSerializableConfig } from '../../utils/config-helpers' +import type { SerializedConfig } from '../../types/config' import { createMethodsRPC } from './rpc' const suppressWarningsPath = resolve(rootDir, './suppress-warnings.cjs') @@ -113,7 +114,7 @@ export function createVmForksPool( async function runFiles( project: WorkspaceProject, - config: ResolvedConfig, + config: SerializedConfig, files: string[], environment: ContextTestEnvironment, invalidates: string[] = [], @@ -166,8 +167,8 @@ export function createVmForksPool( // Cancel pending tasks from pool when possible ctx.onCancel(() => pool.cancelPendingTasks()) - const configs = new Map() - const getConfig = (project: WorkspaceProject): ResolvedConfig => { + const configs = new Map() + const getConfig = (project: WorkspaceProject): SerializedConfig => { if (configs.has(project)) { return configs.get(project)! } diff --git a/packages/vitest/src/node/pools/vmThreads.ts b/packages/vitest/src/node/pools/vmThreads.ts index 09654cf2f574..2758c81396d2 100644 --- a/packages/vitest/src/node/pools/vmThreads.ts +++ b/packages/vitest/src/node/pools/vmThreads.ts @@ -18,6 +18,7 @@ import { groupFilesByEnv } from '../../utils/test-helpers' import { AggregateError } from '../../utils/base' import type { WorkspaceProject } from '../workspace' import { getWorkerMemoryLimit, stringToBytes } from '../../utils/memory-limit' +import type { SerializedConfig } from '../../types/config' import { createMethodsRPC } from './rpc' const suppressWarningsPath = resolve(rootDir, './suppress-warnings.cjs') @@ -103,7 +104,7 @@ export function createVmThreadsPool( async function runFiles( project: WorkspaceProject, - config: ResolvedConfig, + config: SerializedConfig, files: string[], environment: ContextTestEnvironment, invalidates: string[] = [], @@ -160,8 +161,8 @@ export function createVmThreadsPool( // Cancel pending tasks from pool when possible ctx.onCancel(() => pool.cancelPendingTasks()) - const configs = new Map() - const getConfig = (project: WorkspaceProject): ResolvedConfig => { + const configs = new Map() + const getConfig = (project: WorkspaceProject): SerializedConfig => { if (configs.has(project)) { return configs.get(project)! } diff --git a/packages/vitest/src/node/workspace.ts b/packages/vitest/src/node/workspace.ts index cda8f54a7d5d..f004ed187810 100644 --- a/packages/vitest/src/node/workspace.ts +++ b/packages/vitest/src/node/workspace.ts @@ -20,22 +20,25 @@ import { ViteNodeRunner } from 'vite-node/client' import { ViteNodeServer } from 'vite-node/server' import type { ProvidedContext, + Vitest, +} from '../types' +import type { ResolvedConfig, UserConfig, UserWorkspaceConfig, - Vitest, -} from '../types' +} from '../types/config' import type { Typechecker } from '../typecheck/typechecker' import { deepMerge, nanoid } from '../utils/base' import { setup } from '../api/setup' import type { BrowserServer } from '../types/browser' -import { isBrowserEnabled, resolveConfig } from './config' +import { isBrowserEnabled, resolveConfig } from './config/resolveConfig' import { WorkspaceVitestPlugin } from './plugins/workspace' import { createViteServer } from './vite' import type { GlobalSetupFile } from './globalSetup' import { loadGlobalSetupFiles } from './globalSetup' import { MocksPlugins } from './plugins/mocks' import { CoverageTransform } from './plugins/coverageTransform' +import { serializeConfig } from './config/serializeConfig' interface InitializeProjectOptions extends UserWorkspaceConfig { workspaceConfigPath: string @@ -408,103 +411,16 @@ export class WorkspaceProject { } getSerializableConfig(method: 'run' | 'collect' = 'run') { - const optimizer = this.config.deps?.optimizer - const poolOptions = this.config.poolOptions - - // Resolve from server.config to avoid comparing against default value - const isolate = this.server?.config?.test?.isolate - - const config = deepMerge( - { - ...this.config, - - poolOptions: { - forks: { - singleFork: - poolOptions?.forks?.singleFork - ?? this.ctx.config.poolOptions?.forks?.singleFork - ?? false, - isolate: - poolOptions?.forks?.isolate - ?? isolate - ?? this.ctx.config.poolOptions?.forks?.isolate - ?? true, - }, - threads: { - singleThread: - poolOptions?.threads?.singleThread - ?? this.ctx.config.poolOptions?.threads?.singleThread - ?? false, - isolate: - poolOptions?.threads?.isolate - ?? isolate - ?? this.ctx.config.poolOptions?.threads?.isolate - ?? true, - }, - vmThreads: { - singleThread: - poolOptions?.vmThreads?.singleThread - ?? this.ctx.config.poolOptions?.vmThreads?.singleThread - ?? false, - }, - }, - - reporters: [], - deps: { - ...this.config.deps, - optimizer: { - web: { - enabled: optimizer?.web?.enabled ?? true, - }, - ssr: { - enabled: optimizer?.ssr?.enabled ?? true, - }, - }, - }, - snapshotOptions: { - ...this.ctx.config.snapshotOptions, - expand: - this.config.snapshotOptions.expand - ?? this.ctx.config.snapshotOptions.expand, - resolveSnapshotPath: undefined, - }, - onConsoleLog: undefined!, - onStackTrace: undefined!, - sequence: { - ...this.ctx.config.sequence, - sequencer: undefined!, - }, - benchmark: { - ...this.config.benchmark, - reporters: [], - }, - inspect: this.ctx.config.inspect, - inspectBrk: this.ctx.config.inspectBrk, - inspector: this.ctx.config.inspector, - alias: [], - includeTaskLocation: - this.config.includeTaskLocation - ?? this.ctx.config.includeTaskLocation, - env: { - ...this.server?.config.env, - ...this.config.env, - }, - browser: { - ...this.config.browser, - orchestratorScripts: [], - testerScripts: [], - commands: {}, - }, - printConsoleTrace: - this.config.printConsoleTrace ?? this.ctx.config.printConsoleTrace, - }, - this.ctx.configOverride || ({} as any), - ) as ResolvedConfig + // TODO: call `serializeConfig` only once + const config = deepMerge(serializeConfig( + this.config, + this.ctx.config, + this.server?.config, + ), (this.ctx.configOverride || {})) // disable heavy features when collecting because they are not needed if (method === 'collect') { - config.coverage.enabled = false - if (config.browser.provider && config.browser.provider !== 'preview') { + if (this.config.browser.provider && this.config.browser.provider !== 'preview') { config.browser.headless = true } config.snapshotSerializers = [] diff --git a/packages/vitest/src/runtime/config.ts b/packages/vitest/src/runtime/config.ts new file mode 100644 index 000000000000..68fad48c6798 --- /dev/null +++ b/packages/vitest/src/runtime/config.ts @@ -0,0 +1,160 @@ +import type { FakeTimerInstallOpts } from '@sinonjs/fake-timers' +import type { PrettyFormatOptions } from '@vitest/pretty-format' +import type { SequenceHooks, SequenceSetupFiles } from '@vitest/runner' +import type { SnapshotUpdateState } from '@vitest/snapshot' +import type { SnapshotEnvironment } from '@vitest/snapshot/types' + +/** + * Config that tests have access to. + */ +export interface SerializedConfig { + name: string | undefined + globals: boolean + base: string | undefined + snapshotEnvironment?: string + disableConsoleIntercept: boolean | undefined + runner: string | undefined + isolate: boolean + mode: 'test' | 'benchmark' + bail: number | undefined + environmentOptions?: Record + root: string + setupFiles: string[] + passWithNoTests: boolean + testNamePattern: RegExp | undefined + allowOnly: boolean + testTimeout: number + hookTimeout: number + clearMocks: boolean + mockReset: boolean + restoreMocks: boolean + unstubGlobals: boolean + unstubEnvs: boolean + // TODO: make optional + fakeTimers: FakeTimerInstallOpts + maxConcurrency: number + defines: Record + expect: { + requireAssertions?: boolean + poll?: { + timeout?: number + interval?: number + } + } + printConsoleTrace: boolean | undefined + sequence: { + shuffle?: boolean + concurrent?: boolean + seed: number + hooks: SequenceHooks + setupFiles: SequenceSetupFiles + } + poolOptions: { + forks: { + singleFork: boolean + isolate: boolean + } + threads: { + singleThread: boolean + isolate: boolean + } + vmThreads: { + singleThread: boolean + } + vmForks: { + singleFork: boolean + } + } + deps: { + web: { + transformAssets?: boolean + transformCss?: boolean + transformGlobPattern?: RegExp | RegExp[] + } + optimizer: { + web: { + enabled: boolean + } + ssr: { + enabled: boolean + } + } + interopDefault: boolean | undefined + moduleDirectories: string[] | undefined + } + snapshotOptions: { + updateSnapshot: SnapshotUpdateState + expand: boolean | undefined + snapshotFormat: PrettyFormatOptions | undefined + /** + * only exists for tests, not available in the main process + */ + snapshotEnvironment: SnapshotEnvironment + } + pool: string + snapshotSerializers: string[] + chaiConfig: { + includeStack?: boolean + showDiff?: boolean + truncateThreshold?: number + } | undefined + diff: string | undefined + retry: number + includeTaskLocation: boolean | undefined + inspect: boolean | string | undefined + inspectBrk: boolean | string | undefined + inspector: { + enabled?: boolean + port?: number + host?: string + waitForDebugger?: boolean + } + watch: boolean + env: Record + browser: { + name: string + headless: boolean + isolate: boolean + fileParallelism: boolean + ui: boolean + viewport: { + width: number + height: number + } + screenshotFailures: boolean + } + standalone: boolean + logHeapUsage: boolean | undefined + coverage: SerializedCoverageConfig +} + +export interface SerializedCoverageConfig { + provider: 'istanbul' | 'v8' | 'custom' | undefined + reportsDirectory: string + htmlReporter: { + subdir: string | undefined + } | undefined + enabled: boolean + customProviderModule: string | undefined +} + +export type RuntimeConfig = Pick< + SerializedConfig, + | 'allowOnly' + | 'testTimeout' + | 'hookTimeout' + | 'clearMocks' + | 'mockReset' + | 'restoreMocks' + | 'fakeTimers' + | 'maxConcurrency' + | 'expect' + | 'printConsoleTrace' +> & { + sequence?: { + concurrent?: boolean + hooks?: SequenceHooks + } +} + +export type RuntimeOptions = Partial diff --git a/packages/vitest/src/runtime/inspector.ts b/packages/vitest/src/runtime/inspector.ts index 0e18b60259aa..f2530e5c896c 100644 --- a/packages/vitest/src/runtime/inspector.ts +++ b/packages/vitest/src/runtime/inspector.ts @@ -1,6 +1,7 @@ import { createRequire } from 'node:module' import { pathToFileURL } from 'node:url' -import type { ContextRPC, ResolvedConfig } from '../types' +import type { ContextRPC } from '../types' +import type { SerializedConfig } from './config' const __require = createRequire(import.meta.url) let inspector: typeof import('node:inspector') @@ -54,7 +55,7 @@ export function setupInspect(ctx: ContextRPC) { } } -export function closeInspector(config: ResolvedConfig) { +export function closeInspector(config: SerializedConfig) { const keepOpen = shouldKeepOpen(config) if (inspector && !keepOpen) { @@ -63,7 +64,7 @@ export function closeInspector(config: ResolvedConfig) { } } -function shouldKeepOpen(config: ResolvedConfig) { +function shouldKeepOpen(config: SerializedConfig) { // In watch mode the inspector can persist re-runs if isolation is disabled and a single worker is used const isIsolatedSingleThread = config.pool === 'threads' diff --git a/packages/vitest/src/runtime/runBaseTests.ts b/packages/vitest/src/runtime/runBaseTests.ts index 4bcc9c04c912..3c9f8a53c98c 100644 --- a/packages/vitest/src/runtime/runBaseTests.ts +++ b/packages/vitest/src/runtime/runBaseTests.ts @@ -1,6 +1,6 @@ import { performance } from 'node:perf_hooks' import { collectTests, startTests } from '@vitest/runner' -import type { ResolvedConfig, ResolvedTestEnvironment } from '../types' +import type { ResolvedTestEnvironment } from '../types' import { getWorkerState, resetModules } from '../utils' import { vi } from '../integrations/vi' import { @@ -8,6 +8,7 @@ import { stopCoverageInsideWorker, } from '../integrations/coverage' import { setupChaiConfig } from '../integrations/chai/config' +import type { SerializedConfig } from './config' import { setupGlobalEnv, withEnv } from './setup-node' import type { VitestExecutor } from './execute' import { resolveTestRunner } from './runners' @@ -17,7 +18,7 @@ import { closeInspector } from './inspector' export async function run( method: 'run' | 'collect', files: string[], - config: ResolvedConfig, + config: SerializedConfig, environment: ResolvedTestEnvironment, executor: VitestExecutor, ): Promise { @@ -37,8 +38,7 @@ export async function run( runner.onCancel?.(reason) }) - workerState.durations.prepare - = performance.now() - workerState.durations.prepare + workerState.durations.prepare = performance.now() - workerState.durations.prepare workerState.durations.environment = performance.now() await withEnv( diff --git a/packages/vitest/src/runtime/runVmTests.ts b/packages/vitest/src/runtime/runVmTests.ts index 621022a316cc..82f17ee38465 100644 --- a/packages/vitest/src/runtime/runVmTests.ts +++ b/packages/vitest/src/runtime/runVmTests.ts @@ -10,7 +10,6 @@ import { startCoverageInsideWorker, stopCoverageInsideWorker, } from '../integrations/coverage' -import type { ResolvedConfig } from '../types' import { getWorkerState } from '../utils/global' import * as VitestIndex from '../index' import { resolveSnapshotEnvironment } from '../integrations/snapshot/environments/resolveSnapshotEnvironment' @@ -18,11 +17,12 @@ import type { VitestExecutor } from './execute' import { resolveTestRunner } from './runners' import { setupCommonEnv } from './setup-common' import { closeInspector } from './inspector' +import type { SerializedConfig } from './config' export async function run( method: 'run' | 'collect', files: string[], - config: ResolvedConfig, + config: SerializedConfig, executor: VitestExecutor, ): Promise { const workerState = getWorkerState() diff --git a/packages/vitest/src/runtime/runners/benchmark.ts b/packages/vitest/src/runtime/runners/benchmark.ts index 425ea56e8692..b7f77dc5c265 100644 --- a/packages/vitest/src/runtime/runners/benchmark.ts +++ b/packages/vitest/src/runtime/runners/benchmark.ts @@ -13,7 +13,7 @@ import type { Benchmark, BenchmarkResult, } from '../../types/benchmark' -import type { ResolvedConfig } from '../../types/config' +import type { SerializedConfig } from '../config' import type { VitestExecutor } from '../execute' function createBenchmarkResult(name: string): BenchmarkResult { @@ -150,7 +150,7 @@ async function runBenchmarkSuite(suite: Suite, runner: NodeBenchmarkRunner) { export class NodeBenchmarkRunner implements VitestRunner { private __vitest_executor!: VitestExecutor - constructor(public config: ResolvedConfig) {} + constructor(public config: SerializedConfig) {} async importTinybench() { return await import('tinybench') diff --git a/packages/vitest/src/runtime/runners/index.ts b/packages/vitest/src/runtime/runners/index.ts index cdddffa7eb74..7017e4dfd21c 100644 --- a/packages/vitest/src/runtime/runners/index.ts +++ b/packages/vitest/src/runtime/runners/index.ts @@ -1,17 +1,17 @@ import type { VitestRunner, VitestRunnerConstructor } from '@vitest/runner' import { resolve } from 'pathe' -import type { ResolvedConfig } from '../../types/config' import type { VitestExecutor } from '../execute' import { distDir } from '../../paths' import { getWorkerState } from '../../utils/global' import { rpc } from '../rpc' import { takeCoverageInsideWorker } from '../../integrations/coverage' import { loadDiffConfig, loadSnapshotSerializers } from '../setup-common' +import type { SerializedConfig } from '../config' const runnersFile = resolve(distDir, 'runners.js') async function getTestRunnerConstructor( - config: ResolvedConfig, + config: SerializedConfig, executor: VitestExecutor, ): Promise { if (!config.runner) { @@ -33,7 +33,7 @@ async function getTestRunnerConstructor( } export async function resolveTestRunner( - config: ResolvedConfig, + config: SerializedConfig, executor: VitestExecutor, ): Promise { const TestRunner = await getTestRunnerConstructor(config, executor) diff --git a/packages/vitest/src/runtime/runners/test.ts b/packages/vitest/src/runtime/runners/test.ts index c286ad1f4fbe..40d739dea011 100644 --- a/packages/vitest/src/runtime/runners/test.ts +++ b/packages/vitest/src/runtime/runners/test.ts @@ -16,7 +16,7 @@ import { getSnapshotClient } from '../../integrations/snapshot/chai' import { vi } from '../../integrations/vi' import { getNames, getTestName, getTests, getWorkerState } from '../../utils' import { createExpect } from '../../integrations/chai/index' -import type { ResolvedConfig } from '../../types/config' +import type { SerializedConfig } from '../config' import type { VitestExecutor } from '../execute' import { rpc } from '../rpc' @@ -30,7 +30,7 @@ export class VitestTestRunner implements VitestRunner { public pool = this.workerState.ctx.pool - constructor(public config: ResolvedConfig) {} + constructor(public config: SerializedConfig) {} importFile(filepath: string, source: VitestRunnerImportSource): unknown { if (source === 'setup') { @@ -191,7 +191,7 @@ export class VitestTestRunner implements VitestRunner { } } -function clearModuleMocks(config: ResolvedConfig) { +function clearModuleMocks(config: SerializedConfig) { const { clearMocks, mockReset, restoreMocks, unstubEnvs, unstubGlobals } = config diff --git a/packages/vitest/src/runtime/setup-common.ts b/packages/vitest/src/runtime/setup-common.ts index 32df032448ba..c3715e0bcacb 100644 --- a/packages/vitest/src/runtime/setup-common.ts +++ b/packages/vitest/src/runtime/setup-common.ts @@ -2,12 +2,12 @@ import { setSafeTimers } from '@vitest/utils' import { addSerializer } from '@vitest/snapshot' import type { SnapshotSerializer } from '@vitest/snapshot' import { resetRunOnceCounter } from '../integrations/run-once' -import type { ResolvedConfig } from '../types' import type { DiffOptions } from '../types/matcher-utils' import type { VitestExecutor } from './execute' +import type { SerializedConfig } from './config' let globalSetup = false -export async function setupCommonEnv(config: ResolvedConfig) { +export async function setupCommonEnv(config: SerializedConfig) { resetRunOnceCounter() setupDefines(config.defines) setupEnv(config.env) @@ -44,7 +44,7 @@ function setupEnv(env: Record) { } export async function loadDiffConfig( - config: ResolvedConfig, + config: SerializedConfig, executor: VitestExecutor, ) { if (typeof config.diff !== 'string') { @@ -68,7 +68,7 @@ export async function loadDiffConfig( } export async function loadSnapshotSerializers( - config: ResolvedConfig, + config: SerializedConfig, executor: VitestExecutor, ) { const files = config.snapshotSerializers diff --git a/packages/vitest/src/runtime/setup-node.ts b/packages/vitest/src/runtime/setup-node.ts index 100a7d302072..cf8f5bcba6c6 100644 --- a/packages/vitest/src/runtime/setup-node.ts +++ b/packages/vitest/src/runtime/setup-node.ts @@ -5,7 +5,6 @@ import { installSourcemapsSupport } from 'vite-node/source-map' import { KNOWN_ASSET_TYPES } from 'vite-node/constants' import type { EnvironmentOptions, - ResolvedConfig, ResolvedTestEnvironment, } from '../types' import { getSafeTimers, getWorkerState } from '../utils' @@ -14,11 +13,12 @@ import { expect } from '../integrations/chai' import { resolveSnapshotEnvironment } from '../integrations/snapshot/environments/resolveSnapshotEnvironment' import { setupCommonEnv } from './setup-common' import type { VitestExecutor } from './execute' +import type { SerializedConfig } from './config' // this should only be used in Node let globalSetup = false export async function setupGlobalEnv( - config: ResolvedConfig, + config: SerializedConfig, { environment }: ResolvedTestEnvironment, executor: VitestExecutor, ) { diff --git a/packages/vitest/src/runtime/workers/utils.ts b/packages/vitest/src/runtime/workers/utils.ts index 9712189d1810..869faad47816 100644 --- a/packages/vitest/src/runtime/workers/utils.ts +++ b/packages/vitest/src/runtime/workers/utils.ts @@ -1,7 +1,7 @@ import type { TinypoolWorkerMessage } from 'tinypool' import { parseRegexp } from '@vitest/utils' import type { WorkerContext } from '../../types/worker' -import type { ResolvedConfig } from '../../types/config' +import type { ResolvedConfig, SerializedConfig } from '../../types/config' import type { WorkerRpcOptions } from './types' const REGEXP_WRAP_PREFIX = '$$vitest:' @@ -48,7 +48,7 @@ export function createForksRpcOptions( /** * Reverts the wrapping done by `utils/config-helpers.ts`'s `wrapSerializableConfig` */ -export function unwrapSerializableConfig(config: ResolvedConfig) { +export function unwrapSerializableConfig(config: SerializedConfig) { if (config.testNamePattern && typeof config.testNamePattern === 'string') { const testNamePattern = config.testNamePattern as string diff --git a/packages/vitest/src/types/browser.ts b/packages/vitest/src/types/browser.ts index 4f8ed9cb85ba..853c2ead6867 100644 --- a/packages/vitest/src/types/browser.ts +++ b/packages/vitest/src/types/browser.ts @@ -240,4 +240,5 @@ export interface ResolvedBrowserOptions extends BrowserConfigOptions { width: number height: number } + screenshotFailures: boolean } diff --git a/packages/vitest/src/types/config.ts b/packages/vitest/src/types/config.ts index bfb0b849614c..47f913df1692 100644 --- a/packages/vitest/src/types/config.ts +++ b/packages/vitest/src/types/config.ts @@ -21,6 +21,7 @@ import type { Pool, PoolOptions, ResolvedPoolOptions } from './pool-options' export type { BrowserScript, BrowserConfigOptions } from './browser' export type { SequenceHooks, SequenceSetupFiles } from '@vitest/runner' +export type { SerializedConfig, RuntimeConfig } from '../runtime/config' export type BuiltinEnvironment = | 'node' @@ -955,11 +956,18 @@ export interface ResolvedConfig | 'pool' | 'cliExclude' | 'diff' + | 'setupFiles' + | 'snapshotEnvironment' + | 'bail' > { mode: VitestRunMode base?: string diff?: string + bail?: number + + setupFiles: string[] + snapshotEnvironment?: string config?: string filters?: string[] @@ -1062,23 +1070,4 @@ export type ProjectConfig = Omit< } } -export type RuntimeConfig = Pick< - UserConfig, - | 'allowOnly' - | 'testTimeout' - | 'hookTimeout' - | 'clearMocks' - | 'mockReset' - | 'restoreMocks' - | 'fakeTimers' - | 'maxConcurrency' - | 'expect' - | 'printConsoleTrace' -> & { - sequence?: { - concurrent?: boolean - hooks?: SequenceHooks - } -} - export type { UserWorkspaceConfig } from '../config' diff --git a/packages/vitest/src/types/index.ts b/packages/vitest/src/types/index.ts index eb9fe39b22e6..15380909c447 100644 --- a/packages/vitest/src/types/index.ts +++ b/packages/vitest/src/types/index.ts @@ -4,7 +4,6 @@ import './global' export { expectTypeOf, type ExpectTypeOf } from '../typecheck/expectTypeOf' export { assertType, type AssertType } from '../typecheck/assertType' export type * from '../typecheck/types' -export type * from './config' export type * from './tasks' export type * from './rpc' export type * from './reporter' @@ -33,3 +32,53 @@ export type { Assertion, ExpectPollOptions, } from '@vitest/expect' + +export type { + /** @deprecated import from `vitest/node` instead */ + BrowserScript, + /** @deprecated import from `vitest/node` instead */ + BrowserConfigOptions, + /** @deprecated import from `vitest/node` instead */ + SequenceHooks, + /** @deprecated import from `vitest/node` instead */ + SequenceSetupFiles, + /** @deprecated import from `vitest/node` instead */ + BuiltinEnvironment, + /** @deprecated import from `vitest/node` instead */ + VitestEnvironment, + /** @deprecated import from `vitest/node` instead */ + Pool, + /** @deprecated import from `vitest/node` instead */ + PoolOptions, + /** @deprecated import from `vitest/node` instead */ + CSSModuleScopeStrategy, + /** @deprecated import from `vitest/node` instead */ + ApiConfig, + /** @deprecated import from `vitest/node` instead */ + JSDOMOptions, + /** @deprecated import from `vitest/node` instead */ + HappyDOMOptions, + /** @deprecated import from `vitest/node` instead */ + EnvironmentOptions, + /** @deprecated import from `vitest/node` instead */ + VitestRunMode, + /** @deprecated import from `vitest/node` instead */ + DepsOptimizationOptions, + /** @deprecated import from `vitest/node` instead */ + TransformModePatterns, + /** @deprecated import from `vitest/node` instead */ + InlineConfig, + /** @deprecated import from `vitest/node` instead */ + TypecheckConfig, + /** @deprecated import from `vitest/node` instead */ + UserConfig, + /** @deprecated import from `vitest/node` instead */ + ResolvedConfig, + /** @deprecated import from `vitest/node` instead */ + ProjectConfig, + /** @deprecated import from `vitest/node` instead */ + UserWorkspaceConfig, + + RuntimeConfig, + SerializedConfig, +} from './config' diff --git a/packages/vitest/src/types/rpc.ts b/packages/vitest/src/types/rpc.ts index dc0e2a7e995f..c240f8a0bcad 100644 --- a/packages/vitest/src/types/rpc.ts +++ b/packages/vitest/src/types/rpc.ts @@ -3,7 +3,7 @@ import type { CancelReason } from '@vitest/runner' import type { EnvironmentOptions, Pool, - ResolvedConfig, + SerializedConfig, VitestEnvironment, } from './config' import type { Environment, UserConsoleLog } from './general' @@ -65,7 +65,7 @@ export interface ContextRPC { pool: Pool worker: string workerId: number - config: ResolvedConfig + config: SerializedConfig projectName: string files: string[] environment: ContextTestEnvironment diff --git a/packages/vitest/src/types/worker.ts b/packages/vitest/src/types/worker.ts index f23dbbc7a794..f312fbae9294 100644 --- a/packages/vitest/src/types/worker.ts +++ b/packages/vitest/src/types/worker.ts @@ -3,7 +3,7 @@ import type { CancelReason, Task } from '@vitest/runner' import type { ModuleCacheMap, ViteNodeResolveId } from 'vite-node' import type { BirpcReturn } from 'birpc' import type { MockMap } from './mocker' -import type { ResolvedConfig } from './config' +import type { SerializedConfig } from './config' import type { ContextRPC, RunnerRPC, RuntimeRPC } from './rpc' import type { Environment } from './general' @@ -26,7 +26,7 @@ export type WorkerRPC = BirpcReturn export interface WorkerGlobalState { ctx: ContextRPC - config: ResolvedConfig + config: SerializedConfig rpc: WorkerRPC current?: Task filepath?: string diff --git a/packages/vitest/src/utils/config-helpers.ts b/packages/vitest/src/utils/config-helpers.ts index d47d210c4b1b..e22f436d452b 100644 --- a/packages/vitest/src/utils/config-helpers.ts +++ b/packages/vitest/src/utils/config-helpers.ts @@ -1,4 +1,4 @@ -import type { ResolvedConfig } from '../types/config' +import type { SerializedConfig } from '../types/config' import type { BenchmarkBuiltinReporters, BuiltinReporters, @@ -26,9 +26,9 @@ export function getOutputFile( } /** - * Prepares `ResolvedConfig` for serialization, e.g. `node:v8.serialize` + * Prepares `SerializedConfig` for serialization, e.g. `node:v8.serialize` */ -export function wrapSerializableConfig(config: ResolvedConfig) { +export function wrapSerializableConfig(config: SerializedConfig) { let testNamePattern = config.testNamePattern let defines = config.defines @@ -47,5 +47,5 @@ export function wrapSerializableConfig(config: ResolvedConfig) { ...config, testNamePattern, defines, - } as ResolvedConfig + } as SerializedConfig } diff --git a/packages/vitest/src/utils/memory-limit.ts b/packages/vitest/src/utils/memory-limit.ts index 2c3fc6bb1095..28110c617e2a 100644 --- a/packages/vitest/src/utils/memory-limit.ts +++ b/packages/vitest/src/utils/memory-limit.ts @@ -6,7 +6,7 @@ */ import * as nodeos from 'node:os' -import type { ResolvedConfig } from '../types' +import type { ResolvedConfig } from '../types/config' function getDefaultThreadsCount(config: ResolvedConfig) { const numCpus diff --git a/test/config/test/flags.test.ts b/test/config/test/flags.test.ts index e43b8f5909df..b490142beb6c 100644 --- a/test/config/test/flags.test.ts +++ b/test/config/test/flags.test.ts @@ -19,7 +19,7 @@ it('correctly inherit from the cli', async () => { bail: 100, }) const project = ctx!.projects[0] - const config = project.getSerializableConfig() + const config = project.config expect(config).toMatchObject({ logHeapUsage: true, allowOnly: true, diff --git a/test/core/test/cli-test.test.ts b/test/core/test/cli-test.test.ts index 3afce7882b9a..6cb158bf69fa 100644 --- a/test/core/test/cli-test.test.ts +++ b/test/core/test/cli-test.test.ts @@ -1,6 +1,6 @@ import { expect, test } from 'vitest' import { resolveConfig as viteResolveConfig } from 'vite' -import { resolveConfig } from '../../../packages/vitest/src/node/config.js' +import { resolveConfig } from '../../../packages/vitest/src/node/config/resolveConfig.js' import { createCLI, parseCLI } from '../../../packages/vitest/src/node/cli/cac.js' const vitestCli = createCLI() diff --git a/test/coverage-test/test/threshold-100.test.ts b/test/coverage-test/test/threshold-100.test.ts index 154ae4c4ac86..8c5a3e261cab 100644 --- a/test/coverage-test/test/threshold-100.test.ts +++ b/test/coverage-test/test/threshold-100.test.ts @@ -1,23 +1,44 @@ -import { assert, expect } from 'vitest' -import { getWorkerState } from 'vitest/src/utils.js' +import { assert, expect, inject } from 'vitest' import { coverageTest, normalizeURL, runVitest, test } from '../utils' +declare module 'vitest' { + export interface ProvidedContext { + coverage: { + provider: string | undefined + thresholds: { + [key: string]: any + } + } + } +} + test('{ threshold: { 100: true }}', async () => { await runVitest({ include: [normalizeURL(import.meta.url)], coverage: { thresholds: { 100: true } }, + reporters: [ + 'verbose', + { + onInit(ctx) { + ctx.getCoreWorkspaceProject().provide('coverage', { + provider: ctx.config.coverage.provider, + thresholds: (ctx.config.coverage as any).thresholds, + }) + }, + }, + ], }, { throwOnError: false }) }) coverageTest('thresholds.100 sets global thresholds to 100', () => { - const state = getWorkerState() + const coverage = inject('coverage') - assert(state.config.coverage.provider === 'v8' || state.config.coverage.provider === 'istanbul') - assert(state.config.coverage.thresholds !== undefined) + assert(coverage.provider === 'v8' || coverage.provider === 'istanbul') + assert(coverage.thresholds !== undefined) - expect(state.config.coverage.thresholds[100]).toBe(true) - expect(state.config.coverage.thresholds.lines).toBe(100) - expect(state.config.coverage.thresholds.branches).toBe(100) - expect(state.config.coverage.thresholds.functions).toBe(100) - expect(state.config.coverage.thresholds.statements).toBe(100) + expect(coverage.thresholds[100]).toBe(true) + expect(coverage.thresholds.lines).toBe(100) + expect(coverage.thresholds.branches).toBe(100) + expect(coverage.thresholds.functions).toBe(100) + expect(coverage.thresholds.statements).toBe(100) })