Comparing version 2.1.2 to 2.1.3
@@ -5,3 +5,3 @@ export { collectTests, processError, startTests } from '@vitest/runner'; | ||
import { S as SerializedConfig, a as SerializedCoverageConfig } from './chunks/config.Crbj2GAb.js'; | ||
import { C as CoverageProvider, a as CoverageProviderModule } from './chunks/reporters.DAfKSDh5.js'; | ||
import { C as CoverageProvider, b as CoverageProviderModule } from './chunks/reporters.C4ZHgdxQ.js'; | ||
import * as spy$1 from '@vitest/spy'; | ||
@@ -11,3 +11,3 @@ import 'node:vm'; | ||
import 'vite-node'; | ||
import './chunks/worker.Chrs-_NL.js'; | ||
import './chunks/worker.B6RjTtbk.js'; | ||
import '@vitest/snapshot'; | ||
@@ -14,0 +14,0 @@ import './chunks/environment.CzISCQ7o.js'; |
export { collectTests, processError, startTests } from '@vitest/runner'; | ||
export { l as loadDiffConfig, a as loadSnapshotSerializers, s as setupCommonEnv } from './chunks/setup-common.DF96bIYE.js'; | ||
export { l as loadDiffConfig, a as loadSnapshotSerializers, s as setupCommonEnv } from './chunks/setup-common.BKyF15v_.js'; | ||
export { g as getCoverageProvider, a as startCoverageInsideWorker, s as stopCoverageInsideWorker, t as takeCoverageInsideWorker } from './chunks/coverage.zlNdAMHK.js'; | ||
@@ -4,0 +4,0 @@ export { s as SpyModule } from './chunks/spy.Cf_4R5Oe.js'; |
@@ -1,2 +0,2 @@ | ||
import { c as createCLI } from './chunks/cac.B9PaPYY1.js'; | ||
import { c as createCLI } from './chunks/cac.BSMVokHR.js'; | ||
import 'pathe'; | ||
@@ -3,0 +3,0 @@ import 'events'; |
@@ -1,5 +0,5 @@ | ||
import './chunks/vite.8fk186v-.js'; | ||
import { ConfigEnv, UserConfig } from 'vite'; | ||
export { ConfigEnv, Plugin, UserConfig, mergeConfig } from 'vite'; | ||
import { R as ResolvedCoverageOptions, b as CoverageV8Options, U as UserWorkspaceConfig, c as UserProjectConfigFn, d as UserProjectConfigExport, W as WorkspaceProjectConfiguration } from './chunks/reporters.DAfKSDh5.js'; | ||
import './chunks/vite.YH7MrecS.js'; | ||
import { UserConfig as UserConfig$1, ConfigEnv } from 'vite'; | ||
export { ConfigEnv, Plugin, UserConfig as ViteUserConfig, mergeConfig } from 'vite'; | ||
import { R as ResolvedCoverageOptions, c as CoverageV8Options, U as UserWorkspaceConfig, d as UserProjectConfigFn, e as UserProjectConfigExport, W as WorkspaceProjectConfiguration } from './chunks/reporters.C4ZHgdxQ.js'; | ||
import '@vitest/runner'; | ||
@@ -74,8 +74,13 @@ import '@vitest/pretty-format'; | ||
type UserConfigFnObject = (env: ConfigEnv) => UserConfig; | ||
type UserConfigFnPromise = (env: ConfigEnv) => Promise<UserConfig>; | ||
type UserConfigFn = (env: ConfigEnv) => UserConfig | Promise<UserConfig>; | ||
type UserConfigExport = UserConfig | Promise<UserConfig> | UserConfigFnObject | UserConfigFnPromise | UserConfigFn; | ||
declare function defineConfig(config: UserConfig): UserConfig; | ||
declare function defineConfig(config: Promise<UserConfig>): Promise<UserConfig>; | ||
/** | ||
* @deprecated Use `ViteUserConfig` instead | ||
*/ | ||
type UserConfig = UserConfig$1; | ||
type UserConfigFnObject = (env: ConfigEnv) => UserConfig$1; | ||
type UserConfigFnPromise = (env: ConfigEnv) => Promise<UserConfig$1>; | ||
type UserConfigFn = (env: ConfigEnv) => UserConfig$1 | Promise<UserConfig$1>; | ||
type UserConfigExport = UserConfig$1 | Promise<UserConfig$1> | UserConfigFnObject | UserConfigFnPromise | UserConfigFn; | ||
declare function defineConfig(config: UserConfig$1): UserConfig$1; | ||
declare function defineConfig(config: Promise<UserConfig$1>): Promise<UserConfig$1>; | ||
declare function defineConfig(config: UserConfigFnObject): UserConfigFnObject; | ||
@@ -89,2 +94,2 @@ declare function defineConfig(config: UserConfigExport): UserConfigExport; | ||
export { type UserConfigExport, type UserConfigFn, type UserConfigFnObject, type UserConfigFnPromise, UserProjectConfigExport, UserProjectConfigFn, UserWorkspaceConfig, WorkspaceProjectConfiguration, configDefaults, coverageConfigDefaults, defaultBrowserPort, defaultExclude, defaultInclude, defineConfig, defineProject, defineWorkspace, extraInlineDeps }; | ||
export { type UserConfig, type UserConfigExport, type UserConfigFn, type UserConfigFnObject, type UserConfigFnPromise, UserProjectConfigExport, UserProjectConfigFn, UserWorkspaceConfig, WorkspaceProjectConfiguration, configDefaults, coverageConfigDefaults, defaultBrowserPort, defaultExclude, defaultInclude, defineConfig, defineProject, defineWorkspace, extraInlineDeps }; |
import * as vite from 'vite'; | ||
import { B as BaseCoverageOptions, R as ResolvedCoverageOptions, V as Vitest } from './chunks/reporters.DAfKSDh5.js'; | ||
import { A as AfterSuiteRunMeta } from './chunks/environment.CzISCQ7o.js'; | ||
import { R as ResolvedCoverageOptions, V as Vitest, a as ReportContext } from './chunks/reporters.C4ZHgdxQ.js'; | ||
import '@vitest/runner'; | ||
@@ -9,3 +10,2 @@ import '@vitest/pretty-format'; | ||
import 'vite-node'; | ||
import './chunks/environment.CzISCQ7o.js'; | ||
import 'node:stream'; | ||
@@ -133,35 +133,72 @@ import 'vite-node/client'; | ||
} | ||
declare class BaseCoverageProvider { | ||
/** | ||
* Holds info about raw coverage results that are stored on file system: | ||
* | ||
* ```json | ||
* "project-a": { | ||
* "web": { | ||
* "tests/math.test.ts": "coverage-1.json", | ||
* "tests/utils.test.ts": "coverage-2.json", | ||
* // ^^^^^^^^^^^^^^^ Raw coverage on file system | ||
* }, | ||
* "ssr": { ... }, | ||
* "browser": { ... }, | ||
* }, | ||
* "project-b": ... | ||
* ``` | ||
*/ | ||
type CoverageFiles = Map<NonNullable<AfterSuiteRunMeta['projectName']> | symbol, Record<AfterSuiteRunMeta['transformMode'], { | ||
[TestFilenames: string]: string; | ||
}>>; | ||
declare class BaseCoverageProvider<Options extends ResolvedCoverageOptions<'istanbul' | 'v8'>> { | ||
ctx: Vitest; | ||
readonly name: 'v8' | 'istanbul'; | ||
version: string; | ||
options: Options; | ||
coverageFiles: CoverageFiles; | ||
pendingPromises: Promise<void>[]; | ||
coverageFilesDirectory: string; | ||
_initialize(ctx: Vitest): void; | ||
createCoverageMap(): CoverageMap; | ||
generateReports(_: CoverageMap, __: boolean | undefined): Promise<void>; | ||
parseConfigModule(_: string): Promise<{ | ||
generate: () => { | ||
code: string; | ||
}; | ||
}>; | ||
resolveOptions(): Options; | ||
clean(clean?: boolean): Promise<void>; | ||
onAfterSuiteRun({ coverage, transformMode, projectName, testFiles }: AfterSuiteRunMeta): void; | ||
readCoverageFiles<CoverageType>({ onFileRead, onFinished, onDebug }: { | ||
/** Callback invoked with a single coverage result */ | ||
onFileRead: (data: CoverageType) => void; | ||
/** Callback invoked once all results of a project for specific transform mode are read */ | ||
onFinished: (project: Vitest['projects'][number], transformMode: AfterSuiteRunMeta['transformMode']) => Promise<void>; | ||
onDebug: ((...logs: any[]) => void) & { | ||
enabled: boolean; | ||
}; | ||
}): Promise<void>; | ||
cleanAfterRun(): Promise<void>; | ||
onTestFailure(): Promise<void>; | ||
reportCoverage(coverageMap: unknown, { allTestsRun }: ReportContext): Promise<void>; | ||
reportThresholds(coverageMap: CoverageMap, allTestsRun: boolean | undefined): Promise<void>; | ||
/** | ||
* Check if current coverage is above configured thresholds and bump the thresholds if needed | ||
* Constructs collected coverage and users' threshold options into separate sets | ||
* where each threshold set holds their own coverage maps. Threshold set is either | ||
* for specific files defined by glob pattern or global for all other files. | ||
*/ | ||
updateThresholds({ thresholds: allThresholds, perFile, configurationFile, onUpdate, }: { | ||
thresholds: ResolvedThreshold[]; | ||
perFile?: boolean; | ||
configurationFile: unknown; | ||
onUpdate: () => void; | ||
}): void; | ||
private resolveThresholds; | ||
/** | ||
* Check collected coverage against configured thresholds. Sets exit code to 1 when thresholds not reached. | ||
*/ | ||
checkThresholds({ thresholds: allThresholds, perFile, onError, }: { | ||
thresholds: ResolvedThreshold[]; | ||
perFile?: boolean; | ||
onError: (error: string) => void; | ||
}): void; | ||
private checkThresholds; | ||
/** | ||
* Constructs collected coverage and users' threshold options into separate sets | ||
* where each threshold set holds their own coverage maps. Threshold set is either | ||
* for specific files defined by glob pattern or global for all other files. | ||
* Check if current coverage is above configured thresholds and bump the thresholds if needed | ||
*/ | ||
resolveThresholds({ coverageMap, thresholds, createCoverageMap, root, }: { | ||
coverageMap: CoverageMap; | ||
thresholds: NonNullable<BaseCoverageOptions['thresholds']>; | ||
createCoverageMap: () => CoverageMap; | ||
root: string; | ||
}): ResolvedThreshold[]; | ||
/** | ||
* Resolve reporters from various configuration options | ||
*/ | ||
resolveReporters(configReporters: NonNullable<BaseCoverageOptions['reporter']>): ResolvedCoverageOptions['reporter']; | ||
updateThresholds({ thresholds: allThresholds, onUpdate, configurationFile }: { | ||
thresholds: ResolvedThreshold[]; | ||
configurationFile: unknown; | ||
onUpdate: () => void; | ||
}): Promise<void>; | ||
mergeReports(coverageMaps: unknown[]): Promise<void>; | ||
hasTerminalReporter(reporters: ResolvedCoverageOptions['reporter']): boolean; | ||
@@ -168,0 +205,0 @@ toSlices<T>(array: T[], size: number): T[][]; |
@@ -1,5 +0,6 @@ | ||
import { relative } from 'pathe'; | ||
import { m as mm, r as resolveCoverageReporters } from './chunks/resolveConfig.D1DENLPF.js'; | ||
import { existsSync, promises, readdirSync, writeFileSync } from 'node:fs'; | ||
import { resolve, relative } from 'pathe'; | ||
import { c as coverageConfigDefaults, r as resolveCoverageReporters, m as mm } from './chunks/resolveConfig.Dha6ilPI.js'; | ||
import c from 'tinyrainbow'; | ||
import 'node:path'; | ||
import 'node:fs'; | ||
import 'node:fs/promises'; | ||
@@ -12,3 +13,2 @@ import 'node:process'; | ||
import 'node:util'; | ||
import 'tinyrainbow'; | ||
import './chunks/constants.fzPh7AOq.js'; | ||
@@ -46,96 +46,174 @@ import 'node:os'; | ||
const GLOBAL_THRESHOLDS_KEY = "global"; | ||
const DEFAULT_PROJECT = Symbol.for("default-project"); | ||
let uniqueId = 0; | ||
class BaseCoverageProvider { | ||
/** | ||
* Check if current coverage is above configured thresholds and bump the thresholds if needed | ||
*/ | ||
updateThresholds({ | ||
thresholds: allThresholds, | ||
perFile, | ||
configurationFile, | ||
onUpdate | ||
}) { | ||
let updatedThresholds = false; | ||
const config = resolveConfig(configurationFile); | ||
assertConfigurationModule(config); | ||
for (const { coverageMap, thresholds, name } of allThresholds) { | ||
const summaries = perFile ? coverageMap.files().map( | ||
(file) => coverageMap.fileCoverageFor(file).toSummary() | ||
) : [coverageMap.getCoverageSummary()]; | ||
const thresholdsToUpdate = []; | ||
for (const key of THRESHOLD_KEYS) { | ||
const threshold = thresholds[key] ?? 100; | ||
const actual = Math.min( | ||
...summaries.map((summary) => summary[key].pct) | ||
); | ||
if (actual > threshold) { | ||
thresholdsToUpdate.push([key, actual]); | ||
} | ||
ctx; | ||
name; | ||
version; | ||
options; | ||
coverageFiles = /* @__PURE__ */ new Map(); | ||
pendingPromises = []; | ||
coverageFilesDirectory; | ||
_initialize(ctx) { | ||
this.ctx = ctx; | ||
if (ctx.version !== this.version) { | ||
ctx.logger.warn( | ||
c.yellow( | ||
`Loaded ${c.inverse(c.yellow(` vitest@${ctx.version} `))} and ${c.inverse(c.yellow(` @vitest/coverage-${this.name}@${this.version} `))}. | ||
Running mixed versions is not supported and may lead into bugs | ||
Update your dependencies and make sure the versions match.` | ||
) | ||
); | ||
} | ||
const config = ctx.config.coverage; | ||
this.options = { | ||
...coverageConfigDefaults, | ||
// User's options | ||
...config, | ||
// Resolved fields | ||
provider: this.name, | ||
reportsDirectory: resolve( | ||
ctx.config.root, | ||
config.reportsDirectory || coverageConfigDefaults.reportsDirectory | ||
), | ||
reporter: resolveCoverageReporters( | ||
config.reporter || coverageConfigDefaults.reporter | ||
), | ||
thresholds: config.thresholds && { | ||
...config.thresholds, | ||
lines: config.thresholds["100"] ? 100 : config.thresholds.lines, | ||
branches: config.thresholds["100"] ? 100 : config.thresholds.branches, | ||
functions: config.thresholds["100"] ? 100 : config.thresholds.functions, | ||
statements: config.thresholds["100"] ? 100 : config.thresholds.statements | ||
} | ||
if (thresholdsToUpdate.length === 0) { | ||
continue; | ||
} | ||
updatedThresholds = true; | ||
for (const [threshold, newValue] of thresholdsToUpdate) { | ||
if (name === GLOBAL_THRESHOLDS_KEY) { | ||
config.test.coverage.thresholds[threshold] = newValue; | ||
} else { | ||
const glob = config.test.coverage.thresholds[name]; | ||
glob[threshold] = newValue; | ||
} | ||
} | ||
}; | ||
const shard = this.ctx.config.shard; | ||
const tempDirectory = `.tmp${shard ? `-${shard.index}-${shard.count}` : ""}`; | ||
this.coverageFilesDirectory = resolve( | ||
this.options.reportsDirectory, | ||
tempDirectory | ||
); | ||
} | ||
createCoverageMap() { | ||
throw new Error("BaseReporter's createCoverageMap was not overwritten"); | ||
} | ||
async generateReports(_, __) { | ||
throw new Error("BaseReporter's generateReports was not overwritten"); | ||
} | ||
async parseConfigModule(_) { | ||
throw new Error("BaseReporter's parseConfigModule was not overwritten"); | ||
} | ||
resolveOptions() { | ||
return this.options; | ||
} | ||
async clean(clean = true) { | ||
if (clean && existsSync(this.options.reportsDirectory)) { | ||
await promises.rm(this.options.reportsDirectory, { | ||
recursive: true, | ||
force: true, | ||
maxRetries: 10 | ||
}); | ||
} | ||
if (updatedThresholds) { | ||
console.log( | ||
"Updating thresholds to configuration file. You may want to push with updated coverage thresholds." | ||
); | ||
onUpdate(); | ||
if (existsSync(this.coverageFilesDirectory)) { | ||
await promises.rm(this.coverageFilesDirectory, { | ||
recursive: true, | ||
force: true, | ||
maxRetries: 10 | ||
}); | ||
} | ||
await promises.mkdir(this.coverageFilesDirectory, { recursive: true }); | ||
this.coverageFiles = /* @__PURE__ */ new Map(); | ||
this.pendingPromises = []; | ||
} | ||
/** | ||
* Check collected coverage against configured thresholds. Sets exit code to 1 when thresholds not reached. | ||
*/ | ||
checkThresholds({ | ||
thresholds: allThresholds, | ||
perFile, | ||
onError | ||
}) { | ||
for (const { coverageMap, thresholds, name } of allThresholds) { | ||
if (thresholds.branches === void 0 && thresholds.functions === void 0 && thresholds.lines === void 0 && thresholds.statements === void 0) { | ||
continue; | ||
} | ||
const summaries = perFile ? coverageMap.files().map((file) => ({ | ||
file, | ||
summary: coverageMap.fileCoverageFor(file).toSummary() | ||
})) : [ | ||
{ | ||
file: null, | ||
summary: coverageMap.getCoverageSummary() | ||
} | ||
]; | ||
for (const { summary, file } of summaries) { | ||
for (const thresholdKey of [ | ||
"lines", | ||
"functions", | ||
"statements", | ||
"branches" | ||
]) { | ||
const threshold = thresholds[thresholdKey]; | ||
if (threshold !== void 0) { | ||
const coverage = summary.data[thresholdKey].pct; | ||
if (coverage < threshold) { | ||
process.exitCode = 1; | ||
let errorMessage = `ERROR: Coverage for ${thresholdKey} (${coverage}%) does not meet ${name === GLOBAL_THRESHOLDS_KEY ? name : `"${name}"`} threshold (${threshold}%)`; | ||
if (perFile && file) { | ||
errorMessage += ` for ${relative("./", file).replace( | ||
/\\/g, | ||
"/" | ||
)}`; | ||
} | ||
onError(errorMessage); | ||
} | ||
onAfterSuiteRun({ coverage, transformMode, projectName, testFiles }) { | ||
if (!coverage) { | ||
return; | ||
} | ||
if (transformMode !== "web" && transformMode !== "ssr" && transformMode !== "browser") { | ||
throw new Error(`Invalid transform mode: ${transformMode}`); | ||
} | ||
let entry = this.coverageFiles.get(projectName || DEFAULT_PROJECT); | ||
if (!entry) { | ||
entry = { web: {}, ssr: {}, browser: {} }; | ||
this.coverageFiles.set(projectName || DEFAULT_PROJECT, entry); | ||
} | ||
const testFilenames = testFiles.join(); | ||
const filename = resolve( | ||
this.coverageFilesDirectory, | ||
`coverage-${uniqueId++}.json` | ||
); | ||
entry[transformMode][testFilenames] = filename; | ||
const promise = promises.writeFile(filename, JSON.stringify(coverage), "utf-8"); | ||
this.pendingPromises.push(promise); | ||
} | ||
async readCoverageFiles({ onFileRead, onFinished, onDebug }) { | ||
let index = 0; | ||
const total = this.pendingPromises.length; | ||
await Promise.all(this.pendingPromises); | ||
this.pendingPromises = []; | ||
for (const [projectName, coveragePerProject] of this.coverageFiles.entries()) { | ||
for (const [transformMode, coverageByTestfiles] of Object.entries(coveragePerProject)) { | ||
const filenames = Object.values(coverageByTestfiles); | ||
const project = this.ctx.getProjectByName(projectName); | ||
for (const chunk of this.toSlices(filenames, this.options.processingConcurrency)) { | ||
if (onDebug.enabled) { | ||
index += chunk.length; | ||
onDebug("Covered files %d/%d", index, total); | ||
} | ||
await Promise.all( | ||
chunk.map(async (filename) => { | ||
const contents = await promises.readFile(filename, "utf-8"); | ||
const coverage = JSON.parse(contents); | ||
onFileRead(coverage); | ||
}) | ||
); | ||
} | ||
await onFinished(project, transformMode); | ||
} | ||
} | ||
} | ||
async cleanAfterRun() { | ||
this.coverageFiles = /* @__PURE__ */ new Map(); | ||
await promises.rm(this.coverageFilesDirectory, { recursive: true }); | ||
if (readdirSync(this.options.reportsDirectory).length === 0) { | ||
await promises.rm(this.options.reportsDirectory, { recursive: true }); | ||
} | ||
} | ||
async onTestFailure() { | ||
if (!this.options.reportOnFailure) { | ||
await this.cleanAfterRun(); | ||
} | ||
} | ||
async reportCoverage(coverageMap, { allTestsRun }) { | ||
await this.generateReports( | ||
coverageMap || this.createCoverageMap(), | ||
allTestsRun | ||
); | ||
const keepResults = !this.options.cleanOnRerun && this.ctx.config.watch; | ||
if (!keepResults) { | ||
await this.cleanAfterRun(); | ||
} | ||
} | ||
async reportThresholds(coverageMap, allTestsRun) { | ||
const resolvedThresholds = this.resolveThresholds(coverageMap); | ||
this.checkThresholds(resolvedThresholds); | ||
if (this.options.thresholds?.autoUpdate && allTestsRun) { | ||
if (!this.ctx.server.config.configFile) { | ||
throw new Error( | ||
'Missing configurationFile. The "coverage.thresholds.autoUpdate" can only be enabled when configuration file is used.' | ||
); | ||
} | ||
const configFilePath = this.ctx.server.config.configFile; | ||
const configModule = await this.parseConfigModule(configFilePath); | ||
await this.updateThresholds({ | ||
thresholds: resolvedThresholds, | ||
configurationFile: configModule, | ||
onUpdate: () => writeFileSync( | ||
configFilePath, | ||
configModule.generate().code, | ||
"utf-8" | ||
) | ||
}); | ||
} | ||
} | ||
/** | ||
@@ -146,14 +224,7 @@ * Constructs collected coverage and users' threshold options into separate sets | ||
*/ | ||
resolveThresholds({ | ||
coverageMap, | ||
thresholds, | ||
createCoverageMap, | ||
root | ||
}) { | ||
resolveThresholds(coverageMap) { | ||
const resolvedThresholds = []; | ||
const files = coverageMap.files(); | ||
const globalCoverageMap = createCoverageMap(); | ||
for (const key of Object.keys( | ||
thresholds | ||
)) { | ||
const globalCoverageMap = this.createCoverageMap(); | ||
for (const key of Object.keys(this.options.thresholds)) { | ||
if (key === "perFile" || key === "autoUpdate" || key === "100" || THRESHOLD_KEYS.includes(key)) { | ||
@@ -163,6 +234,6 @@ continue; | ||
const glob = key; | ||
const globThresholds = resolveGlobThresholds(thresholds[glob]); | ||
const globCoverageMap = createCoverageMap(); | ||
const globThresholds = resolveGlobThresholds(this.options.thresholds[glob]); | ||
const globCoverageMap = this.createCoverageMap(); | ||
const matchingFiles = files.filter( | ||
(file) => mm.isMatch(relative(root, file), glob) | ||
(file) => mm.isMatch(relative(this.ctx.config.root, file), glob) | ||
); | ||
@@ -187,6 +258,6 @@ for (const file of matchingFiles) { | ||
thresholds: { | ||
branches: thresholds.branches, | ||
functions: thresholds.functions, | ||
lines: thresholds.lines, | ||
statements: thresholds.statements | ||
branches: this.options.thresholds?.branches, | ||
functions: this.options.thresholds?.functions, | ||
lines: this.options.thresholds?.lines, | ||
statements: this.options.thresholds?.statements | ||
} | ||
@@ -197,7 +268,77 @@ }); | ||
/** | ||
* Resolve reporters from various configuration options | ||
* Check collected coverage against configured thresholds. Sets exit code to 1 when thresholds not reached. | ||
*/ | ||
resolveReporters(configReporters) { | ||
return resolveCoverageReporters(configReporters); | ||
checkThresholds(allThresholds) { | ||
for (const { coverageMap, thresholds, name } of allThresholds) { | ||
if (thresholds.branches === void 0 && thresholds.functions === void 0 && thresholds.lines === void 0 && thresholds.statements === void 0) { | ||
continue; | ||
} | ||
const summaries = this.options.thresholds?.perFile ? coverageMap.files().map((file) => ({ | ||
file, | ||
summary: coverageMap.fileCoverageFor(file).toSummary() | ||
})) : [{ file: null, summary: coverageMap.getCoverageSummary() }]; | ||
for (const { summary, file } of summaries) { | ||
for (const thresholdKey of THRESHOLD_KEYS) { | ||
const threshold = thresholds[thresholdKey]; | ||
if (threshold !== void 0) { | ||
const coverage = summary.data[thresholdKey].pct; | ||
if (coverage < threshold) { | ||
process.exitCode = 1; | ||
let errorMessage = `ERROR: Coverage for ${thresholdKey} (${coverage}%) does not meet ${name === GLOBAL_THRESHOLDS_KEY ? name : `"${name}"`} threshold (${threshold}%)`; | ||
if (this.options.thresholds?.perFile && file) { | ||
errorMessage += ` for ${relative("./", file).replace(/\\/g, "/")}`; | ||
} | ||
this.ctx.logger.error(errorMessage); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
/** | ||
* Check if current coverage is above configured thresholds and bump the thresholds if needed | ||
*/ | ||
async updateThresholds({ thresholds: allThresholds, onUpdate, configurationFile }) { | ||
let updatedThresholds = false; | ||
const config = resolveConfig(configurationFile); | ||
assertConfigurationModule(config); | ||
for (const { coverageMap, thresholds, name } of allThresholds) { | ||
const summaries = this.options.thresholds?.perFile ? coverageMap.files().map( | ||
(file) => coverageMap.fileCoverageFor(file).toSummary() | ||
) : [coverageMap.getCoverageSummary()]; | ||
const thresholdsToUpdate = []; | ||
for (const key of THRESHOLD_KEYS) { | ||
const threshold = thresholds[key] ?? 100; | ||
const actual = Math.min( | ||
...summaries.map((summary) => summary[key].pct) | ||
); | ||
if (actual > threshold) { | ||
thresholdsToUpdate.push([key, actual]); | ||
} | ||
} | ||
if (thresholdsToUpdate.length === 0) { | ||
continue; | ||
} | ||
updatedThresholds = true; | ||
for (const [threshold, newValue] of thresholdsToUpdate) { | ||
if (name === GLOBAL_THRESHOLDS_KEY) { | ||
config.test.coverage.thresholds[threshold] = newValue; | ||
} else { | ||
const glob = config.test.coverage.thresholds[name]; | ||
glob[threshold] = newValue; | ||
} | ||
} | ||
} | ||
if (updatedThresholds) { | ||
this.ctx.logger.log("Updating thresholds to configuration file. You may want to push with updated coverage thresholds."); | ||
onUpdate(); | ||
} | ||
} | ||
async mergeReports(coverageMaps) { | ||
const coverageMap = this.createCoverageMap(); | ||
for (const coverage of coverageMaps) { | ||
coverageMap.merge(coverage); | ||
} | ||
await this.generateReports(coverageMap, true); | ||
} | ||
hasTerminalReporter(reporters) { | ||
@@ -204,0 +345,0 @@ return reporters.some( |
import vm from 'node:vm'; | ||
import { ViteNodeRunner } from 'vite-node/client'; | ||
import { ViteNodeRunnerOptions } from 'vite-node'; | ||
import { R as RuntimeRPC, W as WorkerGlobalState } from './chunks/worker.Chrs-_NL.js'; | ||
import { R as RuntimeRPC, W as WorkerGlobalState } from './chunks/worker.B6RjTtbk.js'; | ||
import * as _vitest_mocker from '@vitest/mocker'; | ||
@@ -6,0 +6,0 @@ import { MockedModuleType } from '@vitest/mocker'; |
export { afterAll, afterEach, beforeAll, beforeEach, describe, it, onTestFailed, onTestFinished, suite, test } from '@vitest/runner'; | ||
export { b as bench } from './chunks/benchmark.C8CRJYG4.js'; | ||
import { d as distExports } from './chunks/index.mAqbj9F9.js'; | ||
export { a as assertType, g as getRunningMode, b as inject, i as isWatchMode } from './chunks/index.mAqbj9F9.js'; | ||
import { d as distExports } from './chunks/index.-d_XpZEA.js'; | ||
export { a as assertType, g as getRunningMode, b as inject, i as isWatchMode } from './chunks/index.-d_XpZEA.js'; | ||
export { i as isFirstRun, a as runOnce } from './chunks/run-once.Sxe67Wng.js'; | ||
export { c as createExpect, a as expect, v as vi, b as vitest } from './chunks/vi.DUs2eKik.js'; | ||
export { c as createExpect, a as expect, v as vi, b as vitest } from './chunks/vi.BskyZC5g.js'; | ||
import * as chai from 'chai'; | ||
@@ -8,0 +8,0 @@ export { chai }; |
@@ -5,10 +5,10 @@ import { UserConfig as UserConfig$1, Plugin, ResolvedConfig as ResolvedConfig$1, createServer as createServer$1 } from 'vite'; | ||
export { createLogger as createViteLogger, isFileServingAllowed, parseAst, parseAstAsync } from 'vite'; | ||
import { w as VitestRunMode, z as UserConfig, H as VitestOptions, V as Vitest, E as ResolvedConfig, J as WorkspaceProject, A as ApiConfig, L as Logger, K as TestSequencer, M as WorkspaceSpec, N as TestModule, O as ModuleDiagnostic } from './chunks/reporters.DAfKSDh5.js'; | ||
export { B as BaseCoverageOptions, G as BenchmarkUserOptions, a5 as BrowserBuiltinProvider, a6 as BrowserCommand, a7 as BrowserCommandContext, s as BrowserConfigOptions, ab as BrowserOrchestrator, a0 as BrowserProvider, $ as BrowserProviderInitializationOptions, a2 as BrowserProviderModule, a4 as BrowserProviderOptions, r as BrowserScript, a8 as BrowserServer, a9 as BrowserServerState, aa as BrowserServerStateContext, t as BuiltinEnvironment, a1 as CDPSession, v as CSSModuleScopeStrategy, o as CoverageIstanbulOptions, n as CoverageOptions, C as CoverageProvider, a as CoverageProviderModule, l as CoverageReporter, b as CoverageV8Options, p as CustomProviderOptions, D as DepsOptimizationOptions, ae as HTMLOptions, I as InlineConfig, ad as JUnitOptions, ac as JsonOptions, P as Pool, u as PoolOptions, Q as ProcessPool, F as ProjectConfig, k as ReportContext, a3 as ResolvedBrowserOptions, R as ResolvedCoverageOptions, ap as ResolvedProjectConfig, aj as TaskOptions, af as TestCase, ai as TestCollection, ak as TestDiagnostic, ah as TestProject, al as TestResult, an as TestResultFailed, am as TestResultPassed, ao as TestResultSkipped, _ as TestSequencerConstructor, Z as TestSpecification, ag as TestSuite, x as TransformModePatterns, g as TypeCheckCollectLineNumbers, h as TypeCheckCollectLines, j as TypeCheckContext, T as TypeCheckErrorInfo, f as TypeCheckRawErrorsMap, i as TypeCheckRootAndTarget, y as TypecheckConfig, U as UserWorkspaceConfig, e as VitestEnvironment, Y as VitestPackageInstaller, X as getFilePoolName } from './chunks/reporters.DAfKSDh5.js'; | ||
import { w as VitestRunMode, z as UserConfig, H as VitestOptions, V as Vitest, E as ResolvedConfig, J as WorkspaceProject, A as ApiConfig, L as Logger, K as TestSequencer, M as WorkspaceSpec, N as TestModule, O as ModuleDiagnostic } from './chunks/reporters.C4ZHgdxQ.js'; | ||
export { B as BaseCoverageOptions, G as BenchmarkUserOptions, a5 as BrowserBuiltinProvider, a6 as BrowserCommand, a7 as BrowserCommandContext, s as BrowserConfigOptions, ab as BrowserOrchestrator, a0 as BrowserProvider, $ as BrowserProviderInitializationOptions, a2 as BrowserProviderModule, a4 as BrowserProviderOptions, r as BrowserScript, a8 as BrowserServer, a9 as BrowserServerState, aa as BrowserServerStateContext, t as BuiltinEnvironment, a1 as CDPSession, v as CSSModuleScopeStrategy, o as CoverageIstanbulOptions, n as CoverageOptions, C as CoverageProvider, b as CoverageProviderModule, l as CoverageReporter, c as CoverageV8Options, p as CustomProviderOptions, D as DepsOptimizationOptions, ae as HTMLOptions, I as InlineConfig, ad as JUnitOptions, ac as JsonOptions, P as Pool, u as PoolOptions, Q as ProcessPool, F as ProjectConfig, a as ReportContext, a3 as ResolvedBrowserOptions, R as ResolvedCoverageOptions, ap as ResolvedProjectConfig, aj as TaskOptions, af as TestCase, ai as TestCollection, ak as TestDiagnostic, ah as TestProject, al as TestResult, an as TestResultFailed, am as TestResultPassed, ao as TestResultSkipped, _ as TestSequencerConstructor, Z as TestSpecification, ag as TestSuite, x as TransformModePatterns, h as TypeCheckCollectLineNumbers, i as TypeCheckCollectLines, k as TypeCheckContext, T as TypeCheckErrorInfo, g as TypeCheckRawErrorsMap, j as TypeCheckRootAndTarget, y as TypecheckConfig, U as UserWorkspaceConfig, f as VitestEnvironment, Y as VitestPackageInstaller, X as getFilePoolName } from './chunks/reporters.C4ZHgdxQ.js'; | ||
import { Writable } from 'node:stream'; | ||
import { P as ProvidedContext } from './chunks/environment.CzISCQ7o.js'; | ||
export { f as EnvironmentOptions, H as HappyDOMOptions, J as JSDOMOptions, O as OnServerRestartHandler } from './chunks/environment.CzISCQ7o.js'; | ||
import { R as RuntimeRPC } from './chunks/worker.Chrs-_NL.js'; | ||
import { R as RuntimeRPC } from './chunks/worker.B6RjTtbk.js'; | ||
import createDebug from 'debug'; | ||
export { W as WorkerContext } from './chunks/worker.Qtv8v5nL.js'; | ||
export { W as WorkerContext } from './chunks/worker.CcJLfX8w.js'; | ||
export { SequenceHooks, SequenceSetupFiles } from '@vitest/runner'; | ||
@@ -15,0 +15,0 @@ export { b as RuntimeConfig } from './chunks/config.Crbj2GAb.js'; |
import { createServer as createServer$1 } from 'vite'; | ||
export { createLogger as createViteLogger, isFileServingAllowed, parseAst, parseAstAsync } from 'vite'; | ||
import { f as TestModule } from './chunks/index.FcPVJkIQ.js'; | ||
export { e as TestCase, i as TestProject, g as TestSuite } from './chunks/index.FcPVJkIQ.js'; | ||
export { G as GitNotFoundError, T as TestSpecification, F as TestsNotFoundError, a as VitestPackageInstaller, V as VitestPlugin, c as createVitest, r as registerConsoleShortcuts, b as resolveFsAllow, s as startVitest } from './chunks/cli-api.CHxC4-U8.js'; | ||
export { p as parseCLI } from './chunks/cac.B9PaPYY1.js'; | ||
export { c as createMethodsRPC, g as getFilePoolName, a as resolveApiServerConfig, b as resolveConfig } from './chunks/resolveConfig.D1DENLPF.js'; | ||
import { f as TestModule } from './chunks/index.Dz2opmmU.js'; | ||
export { e as TestCase, i as TestProject, g as TestSuite } from './chunks/index.Dz2opmmU.js'; | ||
export { G as GitNotFoundError, T as TestSpecification, F as TestsNotFoundError, a as VitestPackageInstaller, V as VitestPlugin, c as createVitest, r as registerConsoleShortcuts, b as resolveFsAllow, s as startVitest } from './chunks/cli-api.btGgw3PC.js'; | ||
export { p as parseCLI } from './chunks/cac.BSMVokHR.js'; | ||
export { a as createMethodsRPC, g as getFilePoolName, b as resolveApiServerConfig, d as resolveConfig } from './chunks/resolveConfig.Dha6ilPI.js'; | ||
import createDebug from 'debug'; | ||
@@ -36,3 +36,3 @@ export { distDir, rootDir } from './path.js'; | ||
import './chunks/coverage.zlNdAMHK.js'; | ||
import './chunks/index.BpojBOif.js'; | ||
import './chunks/index.X0nbfr6-.js'; | ||
import 'node:path'; | ||
@@ -55,2 +55,3 @@ import 'node:url'; | ||
import 'url'; | ||
import 'os'; | ||
import 'path'; | ||
@@ -57,0 +58,0 @@ import 'fs'; |
@@ -1,2 +0,2 @@ | ||
export { aA as BaseReporter, ar as BasicReporter, aK as BenchmarkBuiltinReporters, aJ as BenchmarkReportsMap, aF as BuiltinReporterOptions, aE as BuiltinReporters, aq as DefaultReporter, as as DotReporter, aC as FileDiagnostic, az as GithubActionsReporter, ay as HangingProcessReporter, aw as JUnitReporter, aG as JsonAssertionResult, at as JsonReporter, aH as JsonTestResult, aI as JsonTestResults, q as Reporter, aD as ReportersMap, ax as TapFlatReporter, av as TapReporter, aj as TaskOptions, af as TestCase, ai as TestCollection, ak as TestDiagnostic, aB as TestFile, N as TestModule, ah as TestProject, al as TestResult, an as TestResultFailed, am as TestResultPassed, ao as TestResultSkipped, ag as TestSuite, au as VerboseReporter } from './chunks/reporters.DAfKSDh5.js'; | ||
export { aA as BaseReporter, ar as BasicReporter, aK as BenchmarkBuiltinReporters, aJ as BenchmarkReportsMap, aF as BuiltinReporterOptions, aE as BuiltinReporters, aq as DefaultReporter, as as DotReporter, aC as FileDiagnostic, az as GithubActionsReporter, ay as HangingProcessReporter, aw as JUnitReporter, aG as JsonAssertionResult, at as JsonReporter, aH as JsonTestResult, aI as JsonTestResults, q as Reporter, aD as ReportersMap, ax as TapFlatReporter, av as TapReporter, aj as TaskOptions, af as TestCase, ai as TestCollection, ak as TestDiagnostic, aB as TestFile, N as TestModule, ah as TestProject, al as TestResult, an as TestResultFailed, am as TestResultPassed, ao as TestResultSkipped, ag as TestSuite, au as VerboseReporter } from './chunks/reporters.C4ZHgdxQ.js'; | ||
import '@vitest/runner'; | ||
@@ -3,0 +3,0 @@ import 'vite'; |
@@ -1,2 +0,2 @@ | ||
export { B as BasicReporter, h as BenchmarkReportsMap, D as DefaultReporter, a as DotReporter, G as GithubActionsReporter, H as HangingProcessReporter, b as JUnitReporter, J as JsonReporter, R as ReportersMap, c as TapFlatReporter, T as TapReporter, e as TestCase, d as TestFile, f as TestModule, g as TestSuite, V as VerboseReporter } from './chunks/index.FcPVJkIQ.js'; | ||
export { B as BasicReporter, h as BenchmarkReportsMap, D as DefaultReporter, a as DotReporter, G as GithubActionsReporter, H as HangingProcessReporter, b as JUnitReporter, J as JsonReporter, R as ReportersMap, c as TapFlatReporter, T as TapReporter, e as TestCase, d as TestFile, f as TestModule, g as TestSuite, V as VerboseReporter } from './chunks/index.Dz2opmmU.js'; | ||
import 'node:fs'; | ||
@@ -3,0 +3,0 @@ import 'tinyrainbow'; |
import { setState, GLOBAL_EXPECT, getState } from '@vitest/expect'; | ||
import { g as getSnapshotClient, c as createExpect, v as vi } from './chunks/vi.DUs2eKik.js'; | ||
import { g as getSnapshotClient, c as createExpect, v as vi } from './chunks/vi.BskyZC5g.js'; | ||
import 'pathe'; | ||
@@ -4,0 +4,0 @@ import { g as getTestName } from './chunks/tasks.BZnCS9aT.js'; |
import * as v8 from 'v8'; | ||
import { S as SerializedConfig } from './chunks/config.Crbj2GAb.js'; | ||
import { W as WorkerContext } from './chunks/worker.Qtv8v5nL.js'; | ||
import { B as BirpcOptions, R as RuntimeRPC, C as ContextRPC, W as WorkerGlobalState } from './chunks/worker.Chrs-_NL.js'; | ||
import { W as WorkerContext } from './chunks/worker.CcJLfX8w.js'; | ||
import { B as BirpcOptions, R as RuntimeRPC, C as ContextRPC, W as WorkerGlobalState } from './chunks/worker.B6RjTtbk.js'; | ||
import { Awaitable } from '@vitest/utils'; | ||
@@ -6,0 +6,0 @@ import '@vitest/pretty-format'; |
export { c as createForksRpcOptions, a as createThreadsRpcOptions, u as unwrapSerializableConfig } from './chunks/utils.Cn0zI1t3.js'; | ||
export { p as provideWorkerState } from './chunks/utils.Ck2hJTRs.js'; | ||
export { collect as collectVitestWorkerTests, run as runVitestWorker } from './worker.js'; | ||
export { r as runVmTests } from './chunks/vm.CPXwWp4C.js'; | ||
export { r as runBaseTests } from './chunks/base.tiemDJX6.js'; | ||
export { r as runVmTests } from './chunks/vm.DB_hLchi.js'; | ||
export { r as runBaseTests } from './chunks/base.BO5Jx7vw.js'; | ||
import '@vitest/utils'; | ||
@@ -20,3 +20,3 @@ import 'node:url'; | ||
import 'node:vm'; | ||
import './chunks/console.DI3gHgtH.js'; | ||
import './chunks/console.CfT1Wjed.js'; | ||
import 'node:stream'; | ||
@@ -23,0 +23,0 @@ import 'node:path'; |
import v8 from 'node:v8'; | ||
import { c as createForksRpcOptions, u as unwrapSerializableConfig } from '../chunks/utils.Cn0zI1t3.js'; | ||
import { r as runBaseTests } from '../chunks/base.tiemDJX6.js'; | ||
import { r as runBaseTests } from '../chunks/base.BO5Jx7vw.js'; | ||
import '@vitest/utils'; | ||
@@ -5,0 +5,0 @@ import 'vite-node/client'; |
@@ -8,7 +8,7 @@ import { createRequire } from 'node:module'; | ||
import { KNOWN_ASSET_TYPES } from 'vite-node/constants'; | ||
import { s as setupChaiConfig, r as resolveTestRunner, a as resolveSnapshotEnvironment } from '../chunks/index.Ckn0Cw1h.js'; | ||
import { s as setupChaiConfig, r as resolveTestRunner, a as resolveSnapshotEnvironment } from '../chunks/index.4GFF2h22.js'; | ||
import { a as startCoverageInsideWorker, s as stopCoverageInsideWorker } from '../chunks/coverage.zlNdAMHK.js'; | ||
import { V as VitestIndex } from '../chunks/index.mAqbj9F9.js'; | ||
import { V as VitestIndex } from '../chunks/index.-d_XpZEA.js'; | ||
import { g as getWorkerState } from '../chunks/utils.Ck2hJTRs.js'; | ||
import { s as setupCommonEnv } from '../chunks/setup-common.DF96bIYE.js'; | ||
import { s as setupCommonEnv } from '../chunks/setup-common.BKyF15v_.js'; | ||
import { c as closeInspector } from '../chunks/inspector.70d6emsh.js'; | ||
@@ -28,3 +28,3 @@ import 'chai'; | ||
import '../chunks/run-once.Sxe67Wng.js'; | ||
import '../chunks/vi.DUs2eKik.js'; | ||
import '../chunks/vi.BskyZC5g.js'; | ||
import '../chunks/_commonjsHelpers.BFTU3MAI.js'; | ||
@@ -31,0 +31,0 @@ import '@vitest/expect'; |
@@ -1,2 +0,2 @@ | ||
import { r as runBaseTests } from '../chunks/base.tiemDJX6.js'; | ||
import { r as runBaseTests } from '../chunks/base.BO5Jx7vw.js'; | ||
import { a as createThreadsRpcOptions } from '../chunks/utils.Cn0zI1t3.js'; | ||
@@ -3,0 +3,0 @@ import 'vite-node/client'; |
import v8 from 'node:v8'; | ||
import { c as createForksRpcOptions, u as unwrapSerializableConfig } from '../chunks/utils.Cn0zI1t3.js'; | ||
import { r as runVmTests } from '../chunks/vm.CPXwWp4C.js'; | ||
import { r as runVmTests } from '../chunks/vm.DB_hLchi.js'; | ||
import '@vitest/utils'; | ||
@@ -8,3 +8,3 @@ import 'node:vm'; | ||
import 'pathe'; | ||
import '../chunks/console.DI3gHgtH.js'; | ||
import '../chunks/console.CfT1Wjed.js'; | ||
import 'node:stream'; | ||
@@ -11,0 +11,0 @@ import 'node:console'; |
import { a as createThreadsRpcOptions } from '../chunks/utils.Cn0zI1t3.js'; | ||
import { r as runVmTests } from '../chunks/vm.CPXwWp4C.js'; | ||
import { r as runVmTests } from '../chunks/vm.DB_hLchi.js'; | ||
import '@vitest/utils'; | ||
@@ -7,3 +7,3 @@ import 'node:vm'; | ||
import 'pathe'; | ||
import '../chunks/console.DI3gHgtH.js'; | ||
import '../chunks/console.CfT1Wjed.js'; | ||
import 'node:stream'; | ||
@@ -10,0 +10,0 @@ import 'node:console'; |
{ | ||
"name": "vitest", | ||
"type": "module", | ||
"version": "2.1.2", | ||
"version": "2.1.3", | ||
"description": "Next generation testing framework powered by Vite", | ||
@@ -125,4 +125,4 @@ "author": "Anthony Fu <anthonyfu117@hotmail.com>", | ||
"jsdom": "*", | ||
"@vitest/browser": "2.1.2", | ||
"@vitest/ui": "2.1.2" | ||
"@vitest/ui": "2.1.3", | ||
"@vitest/browser": "2.1.3" | ||
}, | ||
@@ -161,10 +161,10 @@ "peerDependenciesMeta": { | ||
"why-is-node-running": "^2.3.0", | ||
"@vitest/expect": "2.1.2", | ||
"@vitest/pretty-format": "^2.1.2", | ||
"@vitest/mocker": "2.1.2", | ||
"@vitest/snapshot": "2.1.2", | ||
"@vitest/runner": "2.1.2", | ||
"@vitest/utils": "2.1.2", | ||
"@vitest/spy": "2.1.2", | ||
"vite-node": "2.1.2" | ||
"@vitest/expect": "2.1.3", | ||
"@vitest/pretty-format": "^2.1.3", | ||
"@vitest/runner": "2.1.3", | ||
"@vitest/mocker": "2.1.3", | ||
"@vitest/snapshot": "2.1.3", | ||
"@vitest/utils": "2.1.3", | ||
"vite-node": "2.1.3", | ||
"@vitest/spy": "2.1.3" | ||
}, | ||
@@ -191,2 +191,3 @@ "devDependencies": { | ||
"expect-type": "^0.19.0", | ||
"fast-glob": "3.3.2", | ||
"find-up": "^6.3.0", | ||
@@ -203,3 +204,2 @@ "flatted": "^3.3.1", | ||
"strip-literal": "^2.1.0", | ||
"tinyglobby": "^0.2.6", | ||
"ws": "^8.18.0" | ||
@@ -206,0 +206,0 @@ }, |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
1684834
47043
5
+ Added@types/node@22.7.6(transitive)
+ Added@vitest/browser@2.1.3(transitive)
+ Added@vitest/expect@2.1.3(transitive)
+ Added@vitest/mocker@2.1.3(transitive)
+ Added@vitest/runner@2.1.3(transitive)
+ Added@vitest/snapshot@2.1.3(transitive)
+ Added@vitest/spy@2.1.3(transitive)
+ Added@vitest/ui@2.1.3(transitive)
+ Added@vitest/utils@2.1.3(transitive)
+ Addedvite-node@2.1.3(transitive)
- Removed@types/node@22.7.7(transitive)
- Removed@vitest/browser@2.1.2(transitive)
- Removed@vitest/expect@2.1.2(transitive)
- Removed@vitest/mocker@2.1.2(transitive)
- Removed@vitest/pretty-format@2.1.2(transitive)
- Removed@vitest/runner@2.1.2(transitive)
- Removed@vitest/snapshot@2.1.2(transitive)
- Removed@vitest/spy@2.1.2(transitive)
- Removed@vitest/ui@2.1.2(transitive)
- Removed@vitest/utils@2.1.2(transitive)
- Removedvite-node@2.1.2(transitive)
Updated@vitest/expect@2.1.3
Updated@vitest/mocker@2.1.3
Updated@vitest/pretty-format@^2.1.3
Updated@vitest/runner@2.1.3
Updated@vitest/snapshot@2.1.3
Updated@vitest/spy@2.1.3
Updated@vitest/utils@2.1.3
Updatedvite-node@2.1.3