vitest 3.0.8 → 3.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/browser.d.ts +12 -23
  2. package/dist/browser.js +2 -2
  3. package/dist/chunks/{base.XvKTsMeK.js → base.DV59CbtV.js} +1 -1
  4. package/dist/chunks/{benchmark.Cdu9hjj4.js → benchmark.DL72EVN-.js} +1 -1
  5. package/dist/chunks/{benchmark.CFFwLv-O.d.ts → benchmark.d.BwvBVTda.d.ts} +11 -11
  6. package/dist/chunks/{cac.VN5q-TPC.js → cac.CeVHgzve.js} +5 -5
  7. package/dist/chunks/{cli-api.Dis64jtY.js → cli-api.Ckwz_xSb.js} +13 -8
  8. package/dist/chunks/config.d.DevWltVl.d.ts +218 -0
  9. package/dist/chunks/{constants.fzPh7AOq.js → constants.DTYd6dNH.js} +1 -1
  10. package/dist/chunks/{coverage.DnNIv-kJ.js → coverage.A3sS5-Wm.js} +1 -29
  11. package/dist/chunks/coverage.d.S9RMNXIe.d.ts +35 -0
  12. package/dist/chunks/{resolveConfig.L1_HR0_0.js → coverage.gV8doR2Y.js} +496 -127
  13. package/dist/chunks/{creator.2CFRE1Yx.js → creator.BsBnpTzI.js} +1 -1
  14. package/dist/chunks/defaults.C2Ndd9wx.js +119 -0
  15. package/dist/chunks/env.D4Lgay0q.js +8 -0
  16. package/dist/chunks/environment.d.C8UItCbf.d.ts +170 -0
  17. package/dist/chunks/global.d.Cg2sEPIm.d.ts +127 -0
  18. package/dist/chunks/{globals.CydvVTgC.js → globals.BEpDe-k3.js} +4 -4
  19. package/dist/chunks/{index.B7vJpkTD.js → index.B8tIoLPT.js} +6 -1
  20. package/dist/chunks/{index.CNRemkXW.js → index.D7Ny8f_s.js} +2 -2
  21. package/dist/chunks/{index.BmFgJtkv.js → index.uXkkC4xl.js} +1 -2
  22. package/dist/chunks/{mocker.cRtM890J.d.ts → mocker.d.BE_2ls6u.d.ts} +6 -6
  23. package/dist/chunks/reporters.d.CqBhtcTq.d.ts +3006 -0
  24. package/dist/chunks/{runBaseTests.DnaAUBKD.js → runBaseTests.BVrL_ow3.js} +8 -8
  25. package/dist/chunks/{setup-common.Uaw6Zgv9.js → setup-common.CPvtqi8q.js} +25 -2
  26. package/dist/chunks/{suite.qtkXWc6R.d.ts → suite.d.FvehnV49.d.ts} +1 -1
  27. package/dist/chunks/{typechecker.cZ0LjdSi.js → typechecker.BlF3eHsb.js} +2 -7
  28. package/dist/chunks/{vi.B5EKKJdE.js → vi.nSCvwQ7l.js} +3 -3
  29. package/dist/chunks/vite.d.BUZTGxQ3.d.ts +11 -0
  30. package/dist/chunks/{worker.BmVno_ab.d.ts → worker.d.C58isfFm.d.ts} +62 -62
  31. package/dist/chunks/{worker.BT4v-DKx.d.ts → worker.d.CSFlSYJg.d.ts} +2 -2
  32. package/dist/cli.js +2 -2
  33. package/dist/config.d.ts +48 -45
  34. package/dist/config.js +6 -123
  35. package/dist/coverage.d.ts +82 -79
  36. package/dist/coverage.js +19 -469
  37. package/dist/environments.d.ts +11 -11
  38. package/dist/execute.d.ts +109 -109
  39. package/dist/index.d.ts +414 -412
  40. package/dist/index.js +3 -3
  41. package/dist/node.d.ts +51 -48
  42. package/dist/node.js +13 -10
  43. package/dist/reporters.d.ts +7 -4
  44. package/dist/reporters.js +3 -2
  45. package/dist/runners.d.ts +28 -28
  46. package/dist/runners.js +2 -3
  47. package/dist/snapshot.d.ts +2 -2
  48. package/dist/suite.d.ts +2 -2
  49. package/dist/suite.js +1 -1
  50. package/dist/workers/forks.js +1 -1
  51. package/dist/workers/runVmTests.js +8 -8
  52. package/dist/workers/threads.js +1 -1
  53. package/dist/workers.d.ts +13 -13
  54. package/dist/workers.js +1 -1
  55. package/package.json +11 -11
  56. package/dist/chunks/config.BCv-fVdT.d.ts +0 -215
  57. package/dist/chunks/environment.d8YfPkTm.d.ts +0 -173
  58. package/dist/chunks/global.CnI8_G5V.d.ts +0 -133
  59. package/dist/chunks/reporters.66aFHiyX.d.ts +0 -3051
  60. package/dist/chunks/vite.BCQa3xFG.d.ts +0 -11
@@ -1,33 +1,36 @@
1
+ import fs, { statSync, realpathSync, promises as promises$1, mkdirSync, existsSync, readdirSync, writeFileSync } from 'node:fs';
2
+ import { g as getDefaultExportFromCjs } from './_commonjsHelpers.BFTU3MAI.js';
3
+ import require$$0 from 'util';
4
+ import require$$0$1 from 'path';
5
+ import { relative, resolve, dirname, isAbsolute, join, normalize } from 'pathe';
6
+ import c from 'tinyrainbow';
7
+ import { c as configDefaults, e as benchmarkConfigDefaults, a as coverageConfigDefaults } from './defaults.C2Ndd9wx.js';
1
8
  import crypto from 'node:crypto';
2
9
  import { slash, createDefer, shuffle, toArray } from '@vitest/utils';
3
- import fs, { statSync, realpathSync, promises as promises$1, mkdirSync } from 'node:fs';
4
- import { writeFile } from 'node:fs/promises';
10
+ import { writeFile, rename, stat, unlink } from 'node:fs/promises';
5
11
  import { builtinModules, createRequire } from 'node:module';
6
12
  import p, { win32, resolve as resolve$1 } from 'node:path';
7
13
  import process$1 from 'node:process';
8
14
  import { fileURLToPath as fileURLToPath$1, pathToFileURL as pathToFileURL$1, URL as URL$1 } from 'node:url';
9
- import { relative, resolve, dirname, isAbsolute, join, normalize } from 'pathe';
10
15
  import assert from 'node:assert';
11
16
  import v8 from 'node:v8';
12
17
  import { format, inspect } from 'node:util';
13
- import c from 'tinyrainbow';
14
- import { e as extraInlineDeps, a as defaultBrowserPort, b as defaultInspectPort, d as defaultPort } from './constants.fzPh7AOq.js';
18
+ import { e as extraInlineDeps, d as defaultBrowserPort, b as defaultInspectPort, a as defaultPort } from './constants.DTYd6dNH.js';
19
+ import { a as isWindows } from './env.D4Lgay0q.js';
15
20
  import * as nodeos from 'node:os';
16
21
  import nodeos__default from 'node:os';
17
- import { w as wrapSerializableConfig, a as Typechecker, b as isWindows } from './typechecker.cZ0LjdSi.js';
18
- import { isCI, provider } from 'std-env';
19
22
  import { isatty } from 'node:tty';
20
- import { g as getDefaultExportFromCjs } from './_commonjsHelpers.BFTU3MAI.js';
21
- import require$$0 from 'util';
22
- import require$$0$1 from 'path';
23
23
  import { version } from 'vite';
24
24
  import EventEmitter from 'node:events';
25
25
  import { c as createBirpc } from './index.68735LiX.js';
26
26
  import Tinypool$1, { Tinypool } from 'tinypool';
27
+ import { w as wrapSerializableConfig, a as Typechecker } from './typechecker.BlF3eHsb.js';
27
28
  import { MessageChannel } from 'node:worker_threads';
28
29
  import { hasFailed } from '@vitest/runner/utils';
29
30
  import { rootDir } from '../path.js';
30
31
  import { slash as slash$1 } from 'vite-node/utils';
32
+ import { isCI, provider } from 'std-env';
33
+ import { r as resolveCoverageProviderModule } from './coverage.A3sS5-Wm.js';
31
34
 
32
35
  function groupBy(collection, iteratee) {
33
36
  return collection.reduce((acc, item) => {
@@ -2302,120 +2305,6 @@ function resolvePackage(name, options = {}) {
2302
2305
  }
2303
2306
  }
2304
2307
 
2305
- const defaultInclude = ["**/*.{test,spec}.?(c|m)[jt]s?(x)"];
2306
- const defaultExclude = [
2307
- "**/node_modules/**",
2308
- "**/dist/**",
2309
- "**/cypress/**",
2310
- "**/.{idea,git,cache,output,temp}/**",
2311
- "**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*"
2312
- ];
2313
- const benchmarkConfigDefaults = {
2314
- include: ["**/*.{bench,benchmark}.?(c|m)[jt]s?(x)"],
2315
- exclude: defaultExclude,
2316
- includeSource: [],
2317
- reporters: ["default"],
2318
- includeSamples: false
2319
- };
2320
- const defaultCoverageExcludes = [
2321
- "coverage/**",
2322
- "dist/**",
2323
- "**/node_modules/**",
2324
- "**/[.]**",
2325
- "packages/*/test?(s)/**",
2326
- "**/*.d.ts",
2327
- "**/virtual:*",
2328
- "**/__x00__*",
2329
- "**/\0*",
2330
- "cypress/**",
2331
- "test?(s)/**",
2332
- "test?(-*).?(c|m)[jt]s?(x)",
2333
- "**/*{.,-}{test,spec,bench,benchmark}?(-d).?(c|m)[jt]s?(x)",
2334
- "**/__tests__/**",
2335
- "**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*",
2336
- "**/vitest.{workspace,projects}.[jt]s?(on)",
2337
- "**/.{eslint,mocha,prettier}rc.{?(c|m)js,yml}"
2338
- ];
2339
- const coverageConfigDefaults = {
2340
- provider: "v8",
2341
- enabled: false,
2342
- all: true,
2343
- clean: true,
2344
- cleanOnRerun: true,
2345
- reportsDirectory: "./coverage",
2346
- exclude: defaultCoverageExcludes,
2347
- reportOnFailure: false,
2348
- reporter: [
2349
- ["text", {}],
2350
- ["html", {}],
2351
- ["clover", {}],
2352
- ["json", {}]
2353
- ],
2354
- extension: [
2355
- ".js",
2356
- ".cjs",
2357
- ".mjs",
2358
- ".ts",
2359
- ".mts",
2360
- ".tsx",
2361
- ".jsx",
2362
- ".vue",
2363
- ".svelte",
2364
- ".marko",
2365
- ".astro"
2366
- ],
2367
- allowExternal: false,
2368
- excludeAfterRemap: false,
2369
- ignoreEmptyLines: true,
2370
- processingConcurrency: Math.min(
2371
- 20,
2372
- nodeos__default.availableParallelism?.() ?? nodeos__default.cpus().length
2373
- )
2374
- };
2375
- const fakeTimersDefaults = {
2376
- loopLimit: 1e4,
2377
- shouldClearNativeTimers: true
2378
- };
2379
- const configDefaults = Object.freeze({
2380
- allowOnly: !isCI,
2381
- isolate: true,
2382
- watch: !isCI,
2383
- globals: false,
2384
- environment: "node",
2385
- pool: "forks",
2386
- clearMocks: false,
2387
- restoreMocks: false,
2388
- mockReset: false,
2389
- unstubGlobals: false,
2390
- unstubEnvs: false,
2391
- include: defaultInclude,
2392
- exclude: defaultExclude,
2393
- teardownTimeout: 1e4,
2394
- forceRerunTriggers: ["**/package.json/**", "**/{vitest,vite}.config.*/**"],
2395
- update: false,
2396
- reporters: [],
2397
- silent: false,
2398
- hideSkippedTests: false,
2399
- api: false,
2400
- ui: false,
2401
- uiBase: "/__vitest__/",
2402
- open: !isCI,
2403
- css: {
2404
- include: []
2405
- },
2406
- coverage: coverageConfigDefaults,
2407
- fakeTimers: fakeTimersDefaults,
2408
- maxConcurrency: 5,
2409
- dangerouslyIgnoreUnhandledErrors: false,
2410
- typecheck: {
2411
- checker: "tsc",
2412
- include: ["**/*.{test,spec}-d.?(c|m)[jt]s?(x)"],
2413
- exclude: defaultExclude
2414
- },
2415
- slowTestThreshold: 300,
2416
- disableConsoleIntercept: false
2417
- });
2418
-
2419
2308
  function getWorkersCountByPercentage(percent) {
2420
2309
  const maxWorkersCount = nodeos__default.availableParallelism?.() ?? nodeos__default.cpus().length;
2421
2310
  const workersCountByPercentage = Math.round(Number.parseInt(percent) / 100 * maxWorkersCount);
@@ -6650,7 +6539,7 @@ function createMethodsRPC(project, options = {}) {
6650
6539
  }
6651
6540
  promises.set(
6652
6541
  tmp,
6653
- writeFile(tmp, code, "utf-8").finally(() => promises.delete(tmp))
6542
+ atomicWriteFile(tmp, code).catch(() => writeFile(tmp, code, "utf-8")).finally(() => promises.delete(tmp))
6654
6543
  );
6655
6544
  await promises.get(tmp);
6656
6545
  Object.assign(result, { id: tmp });
@@ -6721,6 +6610,21 @@ function handleRollupError(e) {
6721
6610
  }
6722
6611
  throw e;
6723
6612
  }
6613
+ async function atomicWriteFile(realFilePath, data) {
6614
+ const dir = dirname(realFilePath);
6615
+ const tmpFilePath = join(dir, `.tmp-${Date.now()}-${Math.random().toString(36).slice(2)}`);
6616
+ try {
6617
+ await writeFile(tmpFilePath, data, "utf-8");
6618
+ await rename(tmpFilePath, realFilePath);
6619
+ } finally {
6620
+ try {
6621
+ if (await stat(tmpFilePath)) {
6622
+ await unlink(tmpFilePath);
6623
+ }
6624
+ } catch {
6625
+ }
6626
+ }
6627
+ }
6724
6628
 
6725
6629
  function createChildProcessChannel$1(project, collect = false) {
6726
6630
  const emitter = new EventEmitter();
@@ -7875,7 +7779,7 @@ function resolveInlineWorkerOption(value) {
7875
7779
  return Number(value);
7876
7780
  }
7877
7781
  }
7878
- function resolveConfig(vitest, options, viteConfig) {
7782
+ function resolveConfig$1(vitest, options, viteConfig) {
7879
7783
  const mode = vitest.mode;
7880
7784
  const logger = vitest.logger;
7881
7785
  if (options.dom) {
@@ -8500,4 +8404,469 @@ function isPlaywrightChromiumOnly(vitest, config) {
8500
8404
  return true;
8501
8405
  }
8502
8406
 
8503
- export { BaseSequencer as B, RandomSequencer as R, VitestCache as V, resolveConfig as a, resolveApiServerConfig as b, coverageConfigDefaults as c, createMethodsRPC as d, configDefaults as e, isBrowserEnabled as f, getFilePoolName as g, hash as h, isPackageExists as i, groupBy as j, createPool as k, mm as m, resolveCoverageReporters as r, stdout as s, wildcardPatternToRegExp as w };
8407
+ const THRESHOLD_KEYS = [
8408
+ "lines",
8409
+ "functions",
8410
+ "statements",
8411
+ "branches"
8412
+ ];
8413
+ const GLOBAL_THRESHOLDS_KEY = "global";
8414
+ const DEFAULT_PROJECT = Symbol.for("default-project");
8415
+ let uniqueId = 0;
8416
+ async function getCoverageProvider(options, loader) {
8417
+ const coverageModule = await resolveCoverageProviderModule(options, loader);
8418
+ if (coverageModule) {
8419
+ return coverageModule.getProvider();
8420
+ }
8421
+ return null;
8422
+ }
8423
+ class BaseCoverageProvider {
8424
+ ctx;
8425
+ name;
8426
+ version;
8427
+ options;
8428
+ coverageFiles = /* @__PURE__ */ new Map();
8429
+ pendingPromises = [];
8430
+ coverageFilesDirectory;
8431
+ _initialize(ctx) {
8432
+ this.ctx = ctx;
8433
+ if (ctx.version !== this.version) {
8434
+ ctx.logger.warn(
8435
+ c.yellow(
8436
+ `Loaded ${c.inverse(c.yellow(` vitest@${ctx.version} `))} and ${c.inverse(c.yellow(` @vitest/coverage-${this.name}@${this.version} `))}.
8437
+ Running mixed versions is not supported and may lead into bugs
8438
+ Update your dependencies and make sure the versions match.`
8439
+ )
8440
+ );
8441
+ }
8442
+ const config = ctx.config.coverage;
8443
+ this.options = {
8444
+ ...coverageConfigDefaults,
8445
+ // User's options
8446
+ ...config,
8447
+ // Resolved fields
8448
+ provider: this.name,
8449
+ reportsDirectory: resolve(
8450
+ ctx.config.root,
8451
+ config.reportsDirectory || coverageConfigDefaults.reportsDirectory
8452
+ ),
8453
+ reporter: resolveCoverageReporters(
8454
+ config.reporter || coverageConfigDefaults.reporter
8455
+ ),
8456
+ thresholds: config.thresholds && {
8457
+ ...config.thresholds,
8458
+ lines: config.thresholds["100"] ? 100 : config.thresholds.lines,
8459
+ branches: config.thresholds["100"] ? 100 : config.thresholds.branches,
8460
+ functions: config.thresholds["100"] ? 100 : config.thresholds.functions,
8461
+ statements: config.thresholds["100"] ? 100 : config.thresholds.statements
8462
+ }
8463
+ };
8464
+ const shard = this.ctx.config.shard;
8465
+ const tempDirectory = `.tmp${shard ? `-${shard.index}-${shard.count}` : ""}`;
8466
+ this.coverageFilesDirectory = resolve(
8467
+ this.options.reportsDirectory,
8468
+ tempDirectory
8469
+ );
8470
+ }
8471
+ createCoverageMap() {
8472
+ throw new Error("BaseReporter's createCoverageMap was not overwritten");
8473
+ }
8474
+ async generateReports(_, __) {
8475
+ throw new Error("BaseReporter's generateReports was not overwritten");
8476
+ }
8477
+ async parseConfigModule(_) {
8478
+ throw new Error("BaseReporter's parseConfigModule was not overwritten");
8479
+ }
8480
+ resolveOptions() {
8481
+ return this.options;
8482
+ }
8483
+ async clean(clean = true) {
8484
+ if (clean && existsSync(this.options.reportsDirectory)) {
8485
+ await promises$1.rm(this.options.reportsDirectory, {
8486
+ recursive: true,
8487
+ force: true,
8488
+ maxRetries: 10
8489
+ });
8490
+ }
8491
+ if (existsSync(this.coverageFilesDirectory)) {
8492
+ await promises$1.rm(this.coverageFilesDirectory, {
8493
+ recursive: true,
8494
+ force: true,
8495
+ maxRetries: 10
8496
+ });
8497
+ }
8498
+ await promises$1.mkdir(this.coverageFilesDirectory, { recursive: true });
8499
+ this.coverageFiles = /* @__PURE__ */ new Map();
8500
+ this.pendingPromises = [];
8501
+ }
8502
+ onAfterSuiteRun({ coverage, transformMode, projectName, testFiles }) {
8503
+ if (!coverage) {
8504
+ return;
8505
+ }
8506
+ if (transformMode !== "web" && transformMode !== "ssr" && transformMode !== "browser") {
8507
+ throw new Error(`Invalid transform mode: ${transformMode}`);
8508
+ }
8509
+ let entry = this.coverageFiles.get(projectName || DEFAULT_PROJECT);
8510
+ if (!entry) {
8511
+ entry = { web: {}, ssr: {}, browser: {} };
8512
+ this.coverageFiles.set(projectName || DEFAULT_PROJECT, entry);
8513
+ }
8514
+ const testFilenames = testFiles.join();
8515
+ const filename = resolve(
8516
+ this.coverageFilesDirectory,
8517
+ `coverage-${uniqueId++}.json`
8518
+ );
8519
+ entry[transformMode][testFilenames] = filename;
8520
+ const promise = promises$1.writeFile(filename, JSON.stringify(coverage), "utf-8");
8521
+ this.pendingPromises.push(promise);
8522
+ }
8523
+ async readCoverageFiles({ onFileRead, onFinished, onDebug }) {
8524
+ let index = 0;
8525
+ const total = this.pendingPromises.length;
8526
+ await Promise.all(this.pendingPromises);
8527
+ this.pendingPromises = [];
8528
+ for (const [projectName, coveragePerProject] of this.coverageFiles.entries()) {
8529
+ for (const [transformMode, coverageByTestfiles] of Object.entries(coveragePerProject)) {
8530
+ const filenames = Object.values(coverageByTestfiles);
8531
+ const project = this.ctx.getProjectByName(projectName);
8532
+ for (const chunk of this.toSlices(filenames, this.options.processingConcurrency)) {
8533
+ if (onDebug.enabled) {
8534
+ index += chunk.length;
8535
+ onDebug("Covered files %d/%d", index, total);
8536
+ }
8537
+ await Promise.all(
8538
+ chunk.map(async (filename) => {
8539
+ const contents = await promises$1.readFile(filename, "utf-8");
8540
+ const coverage = JSON.parse(contents);
8541
+ onFileRead(coverage);
8542
+ })
8543
+ );
8544
+ }
8545
+ await onFinished(project, transformMode);
8546
+ }
8547
+ }
8548
+ }
8549
+ async cleanAfterRun() {
8550
+ this.coverageFiles = /* @__PURE__ */ new Map();
8551
+ await promises$1.rm(this.coverageFilesDirectory, { recursive: true });
8552
+ if (readdirSync(this.options.reportsDirectory).length === 0) {
8553
+ await promises$1.rm(this.options.reportsDirectory, { recursive: true });
8554
+ }
8555
+ }
8556
+ async onTestFailure() {
8557
+ if (!this.options.reportOnFailure) {
8558
+ await this.cleanAfterRun();
8559
+ }
8560
+ }
8561
+ async reportCoverage(coverageMap, { allTestsRun }) {
8562
+ await this.generateReports(
8563
+ coverageMap || this.createCoverageMap(),
8564
+ allTestsRun
8565
+ );
8566
+ const keepResults = !this.options.cleanOnRerun && this.ctx.config.watch;
8567
+ if (!keepResults) {
8568
+ await this.cleanAfterRun();
8569
+ }
8570
+ }
8571
+ async reportThresholds(coverageMap, allTestsRun) {
8572
+ const resolvedThresholds = this.resolveThresholds(coverageMap);
8573
+ this.checkThresholds(resolvedThresholds);
8574
+ if (this.options.thresholds?.autoUpdate && allTestsRun) {
8575
+ if (!this.ctx.server.config.configFile) {
8576
+ throw new Error(
8577
+ 'Missing configurationFile. The "coverage.thresholds.autoUpdate" can only be enabled when configuration file is used.'
8578
+ );
8579
+ }
8580
+ const configFilePath = this.ctx.server.config.configFile;
8581
+ const configModule = await this.parseConfigModule(configFilePath);
8582
+ await this.updateThresholds({
8583
+ thresholds: resolvedThresholds,
8584
+ configurationFile: configModule,
8585
+ onUpdate: () => writeFileSync(
8586
+ configFilePath,
8587
+ configModule.generate().code,
8588
+ "utf-8"
8589
+ )
8590
+ });
8591
+ }
8592
+ }
8593
+ /**
8594
+ * Constructs collected coverage and users' threshold options into separate sets
8595
+ * where each threshold set holds their own coverage maps. Threshold set is either
8596
+ * for specific files defined by glob pattern or global for all other files.
8597
+ */
8598
+ resolveThresholds(coverageMap) {
8599
+ const resolvedThresholds = [];
8600
+ const files = coverageMap.files();
8601
+ const globalCoverageMap = this.createCoverageMap();
8602
+ for (const key of Object.keys(this.options.thresholds)) {
8603
+ if (key === "perFile" || key === "autoUpdate" || key === "100" || THRESHOLD_KEYS.includes(key)) {
8604
+ continue;
8605
+ }
8606
+ const glob = key;
8607
+ const globThresholds = resolveGlobThresholds(this.options.thresholds[glob]);
8608
+ const globCoverageMap = this.createCoverageMap();
8609
+ const matchingFiles = files.filter(
8610
+ (file) => mm.isMatch(relative(this.ctx.config.root, file), glob)
8611
+ );
8612
+ for (const file of matchingFiles) {
8613
+ const fileCoverage = coverageMap.fileCoverageFor(file);
8614
+ globCoverageMap.addFileCoverage(fileCoverage);
8615
+ }
8616
+ resolvedThresholds.push({
8617
+ name: glob,
8618
+ coverageMap: globCoverageMap,
8619
+ thresholds: globThresholds
8620
+ });
8621
+ }
8622
+ for (const file of files) {
8623
+ const fileCoverage = coverageMap.fileCoverageFor(file);
8624
+ globalCoverageMap.addFileCoverage(fileCoverage);
8625
+ }
8626
+ resolvedThresholds.unshift({
8627
+ name: GLOBAL_THRESHOLDS_KEY,
8628
+ coverageMap: globalCoverageMap,
8629
+ thresholds: {
8630
+ branches: this.options.thresholds?.branches,
8631
+ functions: this.options.thresholds?.functions,
8632
+ lines: this.options.thresholds?.lines,
8633
+ statements: this.options.thresholds?.statements
8634
+ }
8635
+ });
8636
+ return resolvedThresholds;
8637
+ }
8638
+ /**
8639
+ * Check collected coverage against configured thresholds. Sets exit code to 1 when thresholds not reached.
8640
+ */
8641
+ checkThresholds(allThresholds) {
8642
+ for (const { coverageMap, thresholds, name } of allThresholds) {
8643
+ if (thresholds.branches === void 0 && thresholds.functions === void 0 && thresholds.lines === void 0 && thresholds.statements === void 0) {
8644
+ continue;
8645
+ }
8646
+ const summaries = this.options.thresholds?.perFile ? coverageMap.files().map((file) => ({
8647
+ file,
8648
+ summary: coverageMap.fileCoverageFor(file).toSummary()
8649
+ })) : [{ file: null, summary: coverageMap.getCoverageSummary() }];
8650
+ for (const { summary, file } of summaries) {
8651
+ for (const thresholdKey of THRESHOLD_KEYS) {
8652
+ const threshold = thresholds[thresholdKey];
8653
+ if (threshold === void 0) {
8654
+ continue;
8655
+ }
8656
+ if (threshold >= 0) {
8657
+ const coverage = summary.data[thresholdKey].pct;
8658
+ if (coverage < threshold) {
8659
+ process.exitCode = 1;
8660
+ let errorMessage = `ERROR: Coverage for ${thresholdKey} (${coverage}%) does not meet ${name === GLOBAL_THRESHOLDS_KEY ? name : `"${name}"`} threshold (${threshold}%)`;
8661
+ if (this.options.thresholds?.perFile && file) {
8662
+ errorMessage += ` for ${relative("./", file).replace(/\\/g, "/")}`;
8663
+ }
8664
+ this.ctx.logger.error(errorMessage);
8665
+ }
8666
+ } else {
8667
+ const uncovered = summary.data[thresholdKey].total - summary.data[thresholdKey].covered;
8668
+ const absoluteThreshold = threshold * -1;
8669
+ if (uncovered > absoluteThreshold) {
8670
+ process.exitCode = 1;
8671
+ let errorMessage = `ERROR: Uncovered ${thresholdKey} (${uncovered}) exceed ${name === GLOBAL_THRESHOLDS_KEY ? name : `"${name}"`} threshold (${absoluteThreshold})`;
8672
+ if (this.options.thresholds?.perFile && file) {
8673
+ errorMessage += ` for ${relative("./", file).replace(/\\/g, "/")}`;
8674
+ }
8675
+ this.ctx.logger.error(errorMessage);
8676
+ }
8677
+ }
8678
+ }
8679
+ }
8680
+ }
8681
+ }
8682
+ /**
8683
+ * Check if current coverage is above configured thresholds and bump the thresholds if needed
8684
+ */
8685
+ async updateThresholds({ thresholds: allThresholds, onUpdate, configurationFile }) {
8686
+ let updatedThresholds = false;
8687
+ const config = resolveConfig(configurationFile);
8688
+ assertConfigurationModule(config);
8689
+ for (const { coverageMap, thresholds, name } of allThresholds) {
8690
+ const summaries = this.options.thresholds?.perFile ? coverageMap.files().map(
8691
+ (file) => coverageMap.fileCoverageFor(file).toSummary()
8692
+ ) : [coverageMap.getCoverageSummary()];
8693
+ const thresholdsToUpdate = [];
8694
+ for (const key of THRESHOLD_KEYS) {
8695
+ const threshold = thresholds[key] ?? 100;
8696
+ if (threshold >= 0) {
8697
+ const actual = Math.min(
8698
+ ...summaries.map((summary) => summary[key].pct)
8699
+ );
8700
+ if (actual > threshold) {
8701
+ thresholdsToUpdate.push([key, actual]);
8702
+ }
8703
+ } else {
8704
+ const absoluteThreshold = threshold * -1;
8705
+ const actual = Math.max(
8706
+ ...summaries.map((summary) => summary[key].total - summary[key].covered)
8707
+ );
8708
+ if (actual < absoluteThreshold) {
8709
+ const updatedThreshold = actual === 0 ? 100 : actual * -1;
8710
+ thresholdsToUpdate.push([key, updatedThreshold]);
8711
+ }
8712
+ }
8713
+ }
8714
+ if (thresholdsToUpdate.length === 0) {
8715
+ continue;
8716
+ }
8717
+ updatedThresholds = true;
8718
+ for (const [threshold, newValue] of thresholdsToUpdate) {
8719
+ if (name === GLOBAL_THRESHOLDS_KEY) {
8720
+ config.test.coverage.thresholds[threshold] = newValue;
8721
+ } else {
8722
+ const glob = config.test.coverage.thresholds[name];
8723
+ glob[threshold] = newValue;
8724
+ }
8725
+ }
8726
+ }
8727
+ if (updatedThresholds) {
8728
+ this.ctx.logger.log("Updating thresholds to configuration file. You may want to push with updated coverage thresholds.");
8729
+ onUpdate();
8730
+ }
8731
+ }
8732
+ async mergeReports(coverageMaps) {
8733
+ const coverageMap = this.createCoverageMap();
8734
+ for (const coverage of coverageMaps) {
8735
+ coverageMap.merge(coverage);
8736
+ }
8737
+ await this.generateReports(coverageMap, true);
8738
+ }
8739
+ hasTerminalReporter(reporters) {
8740
+ return reporters.some(
8741
+ ([reporter]) => reporter === "text" || reporter === "text-summary" || reporter === "text-lcov" || reporter === "teamcity"
8742
+ );
8743
+ }
8744
+ toSlices(array, size) {
8745
+ return array.reduce((chunks, item) => {
8746
+ const index = Math.max(0, chunks.length - 1);
8747
+ const lastChunk = chunks[index] || [];
8748
+ chunks[index] = lastChunk;
8749
+ if (lastChunk.length >= size) {
8750
+ chunks.push([item]);
8751
+ } else {
8752
+ lastChunk.push(item);
8753
+ }
8754
+ return chunks;
8755
+ }, []);
8756
+ }
8757
+ createUncoveredFileTransformer(ctx) {
8758
+ const servers = [
8759
+ ...ctx.projects.map((project) => ({
8760
+ root: project.config.root,
8761
+ isBrowserEnabled: project.isBrowserEnabled(),
8762
+ vitenode: project.vitenode
8763
+ })),
8764
+ // Check core last as it will match all files anyway
8765
+ { root: ctx.config.root, vitenode: ctx.vitenode, isBrowserEnabled: ctx.getRootProject().isBrowserEnabled() }
8766
+ ];
8767
+ return async function transformFile(filename) {
8768
+ let lastError;
8769
+ for (const { root, vitenode, isBrowserEnabled } of servers) {
8770
+ if (!filename.startsWith(root) && !filename.startsWith(`/${root}`)) {
8771
+ continue;
8772
+ }
8773
+ if (isBrowserEnabled) {
8774
+ const result = await vitenode.transformRequest(filename, void 0, "web").catch(() => null);
8775
+ if (result) {
8776
+ return result;
8777
+ }
8778
+ }
8779
+ try {
8780
+ return await vitenode.transformRequest(filename);
8781
+ } catch (error) {
8782
+ lastError = error;
8783
+ }
8784
+ }
8785
+ throw lastError;
8786
+ };
8787
+ }
8788
+ }
8789
+ function resolveGlobThresholds(thresholds) {
8790
+ if (!thresholds || typeof thresholds !== "object") {
8791
+ return {};
8792
+ }
8793
+ if (100 in thresholds && thresholds[100] === true) {
8794
+ return {
8795
+ lines: 100,
8796
+ branches: 100,
8797
+ functions: 100,
8798
+ statements: 100
8799
+ };
8800
+ }
8801
+ return {
8802
+ lines: "lines" in thresholds && typeof thresholds.lines === "number" ? thresholds.lines : void 0,
8803
+ branches: "branches" in thresholds && typeof thresholds.branches === "number" ? thresholds.branches : void 0,
8804
+ functions: "functions" in thresholds && typeof thresholds.functions === "number" ? thresholds.functions : void 0,
8805
+ statements: "statements" in thresholds && typeof thresholds.statements === "number" ? thresholds.statements : void 0
8806
+ };
8807
+ }
8808
+ function assertConfigurationModule(config) {
8809
+ try {
8810
+ if (typeof config.test.coverage.thresholds !== "object") {
8811
+ throw new TypeError(
8812
+ "Expected config.test.coverage.thresholds to be an object"
8813
+ );
8814
+ }
8815
+ } catch (error) {
8816
+ const message = error instanceof Error ? error.message : String(error);
8817
+ throw new Error(
8818
+ `Unable to parse thresholds from configuration file: ${message}`
8819
+ );
8820
+ }
8821
+ }
8822
+ function resolveConfig(configModule) {
8823
+ const mod = configModule.exports.default;
8824
+ try {
8825
+ if (mod.$type === "object") {
8826
+ return mod;
8827
+ }
8828
+ let config = resolveDefineConfig(mod);
8829
+ if (config) {
8830
+ return config;
8831
+ }
8832
+ if (mod.$type === "function-call" && mod.$callee === "mergeConfig") {
8833
+ config = resolveMergeConfig(mod);
8834
+ if (config) {
8835
+ return config;
8836
+ }
8837
+ }
8838
+ } catch (error) {
8839
+ throw new Error(error instanceof Error ? error.message : String(error));
8840
+ }
8841
+ throw new Error(
8842
+ "Failed to update coverage thresholds. Configuration file is too complex."
8843
+ );
8844
+ }
8845
+ function resolveDefineConfig(mod) {
8846
+ if (mod.$type === "function-call" && mod.$callee === "defineConfig") {
8847
+ if (mod.$args[0].$type === "object") {
8848
+ return mod.$args[0];
8849
+ }
8850
+ if (mod.$args[0].$type === "arrow-function-expression") {
8851
+ if (mod.$args[0].$body.$type === "object") {
8852
+ return mod.$args[0].$body;
8853
+ }
8854
+ const config = resolveMergeConfig(mod.$args[0].$body);
8855
+ if (config) {
8856
+ return config;
8857
+ }
8858
+ }
8859
+ }
8860
+ }
8861
+ function resolveMergeConfig(mod) {
8862
+ if (mod.$type === "function-call" && mod.$callee === "mergeConfig") {
8863
+ for (const arg of mod.$args) {
8864
+ const config = resolveDefineConfig(arg);
8865
+ if (config) {
8866
+ return config;
8867
+ }
8868
+ }
8869
+ }
8870
+ }
8871
+
8872
+ export { BaseCoverageProvider as B, RandomSequencer as R, VitestCache as V, resolveApiServerConfig as a, BaseSequencer as b, createMethodsRPC as c, isBrowserEnabled as d, groupBy as e, getCoverageProvider as f, getFilePoolName as g, hash as h, isPackageExists as i, createPool as j, mm as m, resolveConfig$1 as r, stdout as s, wildcardPatternToRegExp as w };
@@ -5,7 +5,7 @@ import { detectPackageManager, installPackage } from './index.Bw6JxgX8.js';
5
5
  import { p as prompt, f as findUp } from './index.DBIGubLC.js';
6
6
  import { x } from 'tinyexec';
7
7
  import c from 'tinyrainbow';
8
- import { c as configFiles } from './constants.fzPh7AOq.js';
8
+ import { c as configFiles } from './constants.DTYd6dNH.js';
9
9
  import 'node:process';
10
10
  import 'node:url';
11
11
  import './_commonjsHelpers.BFTU3MAI.js';