vitest 3.2.0-beta.1 → 3.2.0-beta.3

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 (74) hide show
  1. package/LICENSE.md +0 -232
  2. package/dist/browser.d.ts +5 -3
  3. package/dist/browser.js +3 -4
  4. package/dist/chunks/{base.SfTiRNZf.js → base.D4119yLM.js} +4 -3
  5. package/dist/chunks/{benchmark.BoF7jW0Q.js → benchmark.Cf_PACH1.js} +1 -1
  6. package/dist/chunks/{cac.TfX2-DVH.js → cac.DWaWHIIE.js} +21 -16
  7. package/dist/chunks/{cli-api.2970Nj9J.js → cli-api.CnmEXkxs.js} +292 -59
  8. package/dist/chunks/{config.d.UqE-KR0o.d.ts → config.d.D2ROskhv.d.ts} +2 -0
  9. package/dist/chunks/{console.K1NMVOSc.js → console.Cwr-MFPV.js} +3 -2
  10. package/dist/chunks/{constants.BZZyIeIE.js → constants.DnKduX2e.js} +1 -0
  11. package/dist/chunks/{coverage.z0LVMxgb.js → coverage.C73DaDgS.js} +241 -4226
  12. package/dist/chunks/{creator.CuL7xDWI.js → creator.C8WKy2eW.js} +26 -44
  13. package/dist/chunks/{date.CDOsz-HY.js → date.ByMsSlOr.js} +25 -0
  14. package/dist/chunks/{defaults.DSxsTG0h.js → defaults.DpVH7vbg.js} +1 -0
  15. package/dist/chunks/{environment.d.D8YDy2v5.d.ts → environment.d.cL3nLXbE.d.ts} +1 -0
  16. package/dist/chunks/{execute.BpmIjFTD.js → execute.B3q-2LPV.js} +28 -5
  17. package/dist/chunks/{global.d.BCOHQEpR.d.ts → global.d.BNLIi6yo.d.ts} +13 -11
  18. package/dist/chunks/{globals.Cg4NtV4P.js → globals.CI21aWXF.js} +7 -7
  19. package/dist/chunks/{index.DFXFpH3w.js → index.2jgTs_Q5.js} +19 -1
  20. package/dist/chunks/{index.CUacZlWG.js → index.Bter3jj9.js} +954 -954
  21. package/dist/chunks/{index.DbWBPwtH.js → index.CbT4iuwc.js} +7 -4
  22. package/dist/chunks/index.D3XRDfWc.js +213 -0
  23. package/dist/chunks/{index.BPc7M5ni.js → index.DNgLEKsQ.js} +5 -15
  24. package/dist/chunks/index.JOzufsrU.js +276 -0
  25. package/dist/chunks/{index.DBIGubLC.js → index.X0nbfr6-.js} +7 -7
  26. package/dist/chunks/{inspector.DbDkSkFn.js → inspector.BFsh5KO0.js} +3 -0
  27. package/dist/chunks/{node.3xsWotC9.js → node.Be-ntJnD.js} +1 -1
  28. package/dist/chunks/{reporters.d.DGm4k1Wx.d.ts → reporters.d.Bt4IGtsa.d.ts} +41 -6
  29. package/dist/chunks/{rpc.D9_013TY.js → rpc.BKExFSRG.js} +2 -1
  30. package/dist/chunks/{runBaseTests.CguliJB5.js → runBaseTests.B_M1TTsK.js} +19 -11
  31. package/dist/chunks/{setup-common.BP6KrF_Z.js → setup-common.CF-O-dZX.js} +2 -3
  32. package/dist/chunks/typechecker.BgzF-6iO.js +954 -0
  33. package/dist/chunks/{utils.CgTj3MsC.js → utils.BlI4TC7Y.js} +1 -0
  34. package/dist/chunks/{utils.BfxieIyZ.js → utils.DPCq3gzW.js} +3 -0
  35. package/dist/chunks/{vi.BFR5YIgu.js → vi.pkoYCV6A.js} +25 -2
  36. package/dist/chunks/{vite.d.DjP_ALCZ.d.ts → vite.d.B-Kx3KCF.d.ts} +3 -1
  37. package/dist/chunks/{vm.CuLHT1BG.js → vm.DPYem2so.js} +72 -4
  38. package/dist/chunks/{worker.d.CoCI7hzP.d.ts → worker.d.BKbBp2ga.d.ts} +2 -2
  39. package/dist/chunks/{worker.d.D5Xdi-Zr.d.ts → worker.d.Bl1O4kuf.d.ts} +1 -1
  40. package/dist/cli.js +21 -2
  41. package/dist/config.cjs +2 -0
  42. package/dist/config.d.ts +7 -6
  43. package/dist/config.js +2 -2
  44. package/dist/coverage.d.ts +4 -4
  45. package/dist/coverage.js +7 -10
  46. package/dist/environments.d.ts +6 -2
  47. package/dist/environments.js +1 -1
  48. package/dist/execute.d.ts +9 -3
  49. package/dist/execute.js +1 -1
  50. package/dist/index.d.ts +25 -35
  51. package/dist/index.js +5 -6
  52. package/dist/node.d.ts +18 -10
  53. package/dist/node.js +22 -22
  54. package/dist/reporters.d.ts +4 -4
  55. package/dist/reporters.js +14 -14
  56. package/dist/runners.d.ts +1 -1
  57. package/dist/runners.js +13 -5
  58. package/dist/snapshot.js +2 -2
  59. package/dist/suite.js +2 -2
  60. package/dist/worker.js +9 -5
  61. package/dist/workers/forks.js +6 -4
  62. package/dist/workers/runVmTests.js +14 -10
  63. package/dist/workers/threads.js +4 -4
  64. package/dist/workers/vmForks.js +6 -6
  65. package/dist/workers/vmThreads.js +6 -6
  66. package/dist/workers.d.ts +4 -4
  67. package/dist/workers.js +10 -10
  68. package/package.json +22 -26
  69. package/dist/chunks/index.Bw6JxgX8.js +0 -143
  70. package/dist/chunks/run-once.Dimr7O9f.js +0 -47
  71. package/dist/chunks/typechecker.DYQbn8uK.js +0 -956
  72. package/dist/chunks/utils.8gfOgtry.js +0 -207
  73. package/dist/utils.d.ts +0 -3
  74. package/dist/utils.js +0 -2
@@ -1,9 +1,9 @@
1
1
  import * as chai from 'chai';
2
2
  import { resolve } from 'node:path';
3
- import { l as loadDiffConfig, b as loadSnapshotSerializers, t as takeCoverageInsideWorker } from './setup-common.BP6KrF_Z.js';
3
+ import { l as loadDiffConfig, b as loadSnapshotSerializers, t as takeCoverageInsideWorker } from './setup-common.CF-O-dZX.js';
4
4
  import { distDir } from '../path.js';
5
- import { r as rpc } from './rpc.D9_013TY.js';
6
- import { g as getWorkerState } from './utils.CgTj3MsC.js';
5
+ import { r as rpc } from './rpc.BKExFSRG.js';
6
+ import { g as getWorkerState } from './utils.BlI4TC7Y.js';
7
7
 
8
8
  function setupChaiConfig(config) {
9
9
  Object.assign(chai.config, config);
@@ -11,7 +11,7 @@ function setupChaiConfig(config) {
11
11
 
12
12
  async function resolveSnapshotEnvironment(config, executor) {
13
13
  if (!config.snapshotEnvironment) {
14
- const { VitestNodeSnapshotEnvironment } = await import('./node.3xsWotC9.js');
14
+ const { VitestNodeSnapshotEnvironment } = await import('./node.Be-ntJnD.js');
15
15
  return new VitestNodeSnapshotEnvironment();
16
16
  }
17
17
  const mod = await executor.executeId(config.snapshotEnvironment);
@@ -36,6 +36,7 @@ async function getTestRunnerConstructor(config, executor) {
36
36
  async function resolveTestRunner(config, executor) {
37
37
  const TestRunner = await getTestRunnerConstructor(config, executor);
38
38
  const testRunner = new TestRunner(config);
39
+ // inject private executor to every runner
39
40
  Object.defineProperty(testRunner, "__vitest_executor", {
40
41
  value: executor,
41
42
  enumerable: false,
@@ -49,6 +50,7 @@ async function resolveTestRunner(config, executor) {
49
50
  }
50
51
  const [diffOptions] = await Promise.all([loadDiffConfig(config, executor), loadSnapshotSerializers(config, executor)]);
51
52
  testRunner.config.diffOptions = diffOptions;
53
+ // patch some methods, so custom runners don't need to call RPC
52
54
  const originalOnTaskUpdate = testRunner.onTaskUpdate;
53
55
  testRunner.onTaskUpdate = async (task, events) => {
54
56
  const p = rpc().onTaskUpdate(task, events);
@@ -66,6 +68,7 @@ async function resolveTestRunner(config, executor) {
66
68
  files.forEach((file) => {
67
69
  file.prepareDuration = state.durations.prepare;
68
70
  file.environmentLoad = state.durations.environment;
71
+ // should be collected only for a single test file in a batch
69
72
  state.durations.prepare = 0;
70
73
  state.durations.environment = 0;
71
74
  });
@@ -0,0 +1,213 @@
1
+ import process from 'node:process';
2
+ import fs from 'node:fs/promises';
3
+ import path, { resolve } from 'node:path';
4
+ import { existsSync } from 'node:fs';
5
+ import { x } from 'tinyexec';
6
+
7
+ const AGENTS = [
8
+ "npm",
9
+ "yarn",
10
+ "yarn@berry",
11
+ "pnpm",
12
+ "pnpm@6",
13
+ "bun",
14
+ "deno"
15
+ ];
16
+ const LOCKS = {
17
+ "bun.lock": "bun",
18
+ "bun.lockb": "bun",
19
+ "deno.lock": "deno",
20
+ "pnpm-lock.yaml": "pnpm",
21
+ "pnpm-workspace.yaml": "pnpm",
22
+ "yarn.lock": "yarn",
23
+ "package-lock.json": "npm",
24
+ "npm-shrinkwrap.json": "npm"
25
+ };
26
+ const INSTALL_METADATA = {
27
+ "node_modules/.deno/": "deno",
28
+ "node_modules/.pnpm/": "pnpm",
29
+ "node_modules/.yarn-state.yml": "yarn",
30
+ // yarn v2+ (node-modules)
31
+ "node_modules/.yarn_integrity": "yarn",
32
+ // yarn v1
33
+ "node_modules/.package-lock.json": "npm",
34
+ ".pnp.cjs": "yarn",
35
+ // yarn v3+ (pnp)
36
+ ".pnp.js": "yarn",
37
+ // yarn v2 (pnp)
38
+ "bun.lock": "bun",
39
+ "bun.lockb": "bun"
40
+ };
41
+
42
+ async function pathExists(path2, type) {
43
+ try {
44
+ const stat = await fs.stat(path2);
45
+ return type === "file" ? stat.isFile() : stat.isDirectory();
46
+ } catch {
47
+ return false;
48
+ }
49
+ }
50
+ function* lookup(cwd = process.cwd()) {
51
+ let directory = path.resolve(cwd);
52
+ const { root } = path.parse(directory);
53
+ while (directory && directory !== root) {
54
+ yield directory;
55
+ directory = path.dirname(directory);
56
+ }
57
+ }
58
+ async function parsePackageJson(filepath, onUnknown) {
59
+ return !filepath || !pathExists(filepath, "file") ? null : await handlePackageManager(filepath, onUnknown);
60
+ }
61
+ async function detect(options = {}) {
62
+ const {
63
+ cwd,
64
+ strategies = ["lockfile", "packageManager-field", "devEngines-field"],
65
+ onUnknown
66
+ } = options;
67
+ let stopDir;
68
+ if (typeof options.stopDir === "string") {
69
+ const resolved = path.resolve(options.stopDir);
70
+ stopDir = (dir) => dir === resolved;
71
+ } else {
72
+ stopDir = options.stopDir;
73
+ }
74
+ for (const directory of lookup(cwd)) {
75
+ for (const strategy of strategies) {
76
+ switch (strategy) {
77
+ case "lockfile": {
78
+ for (const lock of Object.keys(LOCKS)) {
79
+ if (await pathExists(path.join(directory, lock), "file")) {
80
+ const name = LOCKS[lock];
81
+ const result = await parsePackageJson(path.join(directory, "package.json"), onUnknown);
82
+ if (result)
83
+ return result;
84
+ else
85
+ return { name, agent: name };
86
+ }
87
+ }
88
+ break;
89
+ }
90
+ case "packageManager-field":
91
+ case "devEngines-field": {
92
+ const result = await parsePackageJson(path.join(directory, "package.json"), onUnknown);
93
+ if (result)
94
+ return result;
95
+ break;
96
+ }
97
+ case "install-metadata": {
98
+ for (const metadata of Object.keys(INSTALL_METADATA)) {
99
+ const fileOrDir = metadata.endsWith("/") ? "dir" : "file";
100
+ if (await pathExists(path.join(directory, metadata), fileOrDir)) {
101
+ const name = INSTALL_METADATA[metadata];
102
+ const agent = name === "yarn" ? isMetadataYarnClassic(metadata) ? "yarn" : "yarn@berry" : name;
103
+ return { name, agent };
104
+ }
105
+ }
106
+ break;
107
+ }
108
+ }
109
+ }
110
+ if (stopDir?.(directory))
111
+ break;
112
+ }
113
+ return null;
114
+ }
115
+ function getNameAndVer(pkg) {
116
+ const handelVer = (version) => version?.match(/\d+(\.\d+){0,2}/)?.[0] ?? version;
117
+ if (typeof pkg.packageManager === "string") {
118
+ const [name, ver] = pkg.packageManager.replace(/^\^/, "").split("@");
119
+ return { name, ver: handelVer(ver) };
120
+ }
121
+ if (typeof pkg.devEngines?.packageManager?.name === "string") {
122
+ return {
123
+ name: pkg.devEngines.packageManager.name,
124
+ ver: handelVer(pkg.devEngines.packageManager.version)
125
+ };
126
+ }
127
+ return void 0;
128
+ }
129
+ async function handlePackageManager(filepath, onUnknown) {
130
+ try {
131
+ const pkg = JSON.parse(await fs.readFile(filepath, "utf8"));
132
+ let agent;
133
+ const nameAndVer = getNameAndVer(pkg);
134
+ if (nameAndVer) {
135
+ const name = nameAndVer.name;
136
+ const ver = nameAndVer.ver;
137
+ let version = ver;
138
+ if (name === "yarn" && ver && Number.parseInt(ver) > 1) {
139
+ agent = "yarn@berry";
140
+ version = "berry";
141
+ return { name, agent, version };
142
+ } else if (name === "pnpm" && ver && Number.parseInt(ver) < 7) {
143
+ agent = "pnpm@6";
144
+ return { name, agent, version };
145
+ } else if (AGENTS.includes(name)) {
146
+ agent = name;
147
+ return { name, agent, version };
148
+ } else {
149
+ return onUnknown?.(pkg.packageManager) ?? null;
150
+ }
151
+ }
152
+ } catch {
153
+ }
154
+ return null;
155
+ }
156
+ function isMetadataYarnClassic(metadataPath) {
157
+ return metadataPath.endsWith(".yarn_integrity");
158
+ }
159
+
160
+ // src/detect.ts
161
+ async function detectPackageManager(cwd = process.cwd()) {
162
+ const result = await detect({
163
+ cwd,
164
+ onUnknown(packageManager) {
165
+ console.warn("[@antfu/install-pkg] Unknown packageManager:", packageManager);
166
+ return void 0;
167
+ }
168
+ });
169
+ return result?.agent || null;
170
+ }
171
+ async function installPackage(names, options = {}) {
172
+ const detectedAgent = options.packageManager || await detectPackageManager(options.cwd) || "npm";
173
+ const [agent] = detectedAgent.split("@");
174
+ if (!Array.isArray(names))
175
+ names = [names];
176
+ const args = (typeof options.additionalArgs === "function" ? options.additionalArgs(agent, detectedAgent) : options.additionalArgs) || [];
177
+ if (options.preferOffline) {
178
+ if (detectedAgent === "yarn@berry")
179
+ args.unshift("--cached");
180
+ else
181
+ args.unshift("--prefer-offline");
182
+ }
183
+ if (agent === "pnpm") {
184
+ args.unshift(
185
+ /**
186
+ * Prevent pnpm from removing installed devDeps while `NODE_ENV` is `production`
187
+ * @see https://pnpm.io/cli/install#--prod--p
188
+ */
189
+ "--prod=false"
190
+ );
191
+ if (existsSync(resolve(options.cwd ?? process.cwd(), "pnpm-workspace.yaml"))) {
192
+ args.unshift("-w");
193
+ }
194
+ }
195
+ return x(
196
+ agent,
197
+ [
198
+ agent === "yarn" ? "add" : "install",
199
+ options.dev ? "-D" : "",
200
+ ...args,
201
+ ...names
202
+ ].filter(Boolean),
203
+ {
204
+ nodeOptions: {
205
+ stdio: options.silent ? "ignore" : "inherit",
206
+ cwd: options.cwd
207
+ },
208
+ throwOnError: true
209
+ }
210
+ );
211
+ }
212
+
213
+ export { detectPackageManager, installPackage };
@@ -1,20 +1,14 @@
1
- import { c as createExpect, a as globalExpect, i as inject, v as vi, b as vitest } from './vi.BFR5YIgu.js';
2
- import { i as isFirstRun, a as runOnce } from './run-once.Dimr7O9f.js';
3
- import { b as bench } from './benchmark.BoF7jW0Q.js';
1
+ import { c as createExpect, a as globalExpect, i as inject, v as vi, b as vitest } from './vi.pkoYCV6A.js';
2
+ import { b as bench } from './benchmark.Cf_PACH1.js';
4
3
  import { expectTypeOf } from 'expect-type';
5
4
  import { afterAll, afterEach, beforeAll, beforeEach, describe, it, onTestFailed, onTestFinished, suite, test } from '@vitest/runner';
6
5
  import * as chai from 'chai';
7
6
  import { assert, should } from 'chai';
8
7
 
9
- function getRunningMode() {
10
- return process.env.VITEST_MODE === "WATCH" ? "watch" : "run";
11
- }
12
- function isWatchMode() {
13
- return getRunningMode() === "watch";
14
- }
15
-
16
8
  const assertType = function assertType() {};
17
9
 
10
+ // TODO: deprecate <reference types="vitest" /> in favor of `<reference types="vitest/config" />`
11
+
18
12
  var VitestIndex = /*#__PURE__*/Object.freeze({
19
13
  __proto__: null,
20
14
  afterAll: afterAll,
@@ -29,14 +23,10 @@ var VitestIndex = /*#__PURE__*/Object.freeze({
29
23
  describe: describe,
30
24
  expect: globalExpect,
31
25
  expectTypeOf: expectTypeOf,
32
- getRunningMode: getRunningMode,
33
26
  inject: inject,
34
- isFirstRun: isFirstRun,
35
- isWatchMode: isWatchMode,
36
27
  it: it,
37
28
  onTestFailed: onTestFailed,
38
29
  onTestFinished: onTestFinished,
39
- runOnce: runOnce,
40
30
  should: should,
41
31
  suite: suite,
42
32
  test: test,
@@ -44,4 +34,4 @@ var VitestIndex = /*#__PURE__*/Object.freeze({
44
34
  vitest: vitest
45
35
  });
46
36
 
47
- export { VitestIndex as V, assertType as a, getRunningMode as g, isWatchMode as i };
37
+ export { VitestIndex as V, assertType as a };
@@ -0,0 +1,276 @@
1
+ import fs from 'node:fs';
2
+ import { getTasks, getFullName, getTests } from '@vitest/runner/utils';
3
+ import * as pathe from 'pathe';
4
+ import c from 'tinyrainbow';
5
+ import { g as getStateSymbol, t as truncateString, F as F_RIGHT, D as DefaultReporter, f as formatProjectName } from './index.Bter3jj9.js';
6
+ import { stripVTControlCharacters } from 'node:util';
7
+ import { notNullish } from '@vitest/utils';
8
+
9
+ function createBenchmarkJsonReport(files) {
10
+ const report = { files: [] };
11
+ for (const file of files) {
12
+ const groups = [];
13
+ for (const task of getTasks(file)) {
14
+ if (task?.type === "suite") {
15
+ const benchmarks = [];
16
+ for (const t of task.tasks) {
17
+ const benchmark = t.meta.benchmark && t.result?.benchmark;
18
+ if (benchmark) {
19
+ benchmarks.push({
20
+ id: t.id,
21
+ ...benchmark,
22
+ samples: []
23
+ });
24
+ }
25
+ }
26
+ if (benchmarks.length) {
27
+ groups.push({
28
+ fullName: getFullName(task, " > "),
29
+ benchmarks
30
+ });
31
+ }
32
+ }
33
+ }
34
+ report.files.push({
35
+ filepath: file.filepath,
36
+ groups
37
+ });
38
+ }
39
+ return report;
40
+ }
41
+ function flattenFormattedBenchmarkReport(report) {
42
+ const flat = {};
43
+ for (const file of report.files) {
44
+ for (const group of file.groups) {
45
+ for (const t of group.benchmarks) {
46
+ flat[t.id] = t;
47
+ }
48
+ }
49
+ }
50
+ return flat;
51
+ }
52
+
53
+ const outputMap = new WeakMap();
54
+ function formatNumber(number) {
55
+ const res = String(number.toFixed(number < 100 ? 4 : 2)).split(".");
56
+ return res[0].replace(/(?=(?:\d{3})+$)\B/g, ",") + (res[1] ? `.${res[1]}` : "");
57
+ }
58
+ const tableHead = [
59
+ "name",
60
+ "hz",
61
+ "min",
62
+ "max",
63
+ "mean",
64
+ "p75",
65
+ "p99",
66
+ "p995",
67
+ "p999",
68
+ "rme",
69
+ "samples"
70
+ ];
71
+ function renderBenchmarkItems(result) {
72
+ return [
73
+ result.name,
74
+ formatNumber(result.hz || 0),
75
+ formatNumber(result.min || 0),
76
+ formatNumber(result.max || 0),
77
+ formatNumber(result.mean || 0),
78
+ formatNumber(result.p75 || 0),
79
+ formatNumber(result.p99 || 0),
80
+ formatNumber(result.p995 || 0),
81
+ formatNumber(result.p999 || 0),
82
+ `±${(result.rme || 0).toFixed(2)}%`,
83
+ (result.sampleCount || 0).toString()
84
+ ];
85
+ }
86
+ function computeColumnWidths(results) {
87
+ const rows = [tableHead, ...results.map((v) => renderBenchmarkItems(v))];
88
+ return Array.from(tableHead, (_, i) => Math.max(...rows.map((row) => stripVTControlCharacters(row[i]).length)));
89
+ }
90
+ function padRow(row, widths) {
91
+ return row.map((v, i) => i ? v.padStart(widths[i], " ") : v.padEnd(widths[i], " "));
92
+ }
93
+ function renderTableHead(widths) {
94
+ return " ".repeat(3) + padRow(tableHead, widths).map(c.bold).join(" ");
95
+ }
96
+ function renderBenchmark(result, widths) {
97
+ const padded = padRow(renderBenchmarkItems(result), widths);
98
+ return [
99
+ padded[0],
100
+ c.blue(padded[1]),
101
+ c.cyan(padded[2]),
102
+ c.cyan(padded[3]),
103
+ c.cyan(padded[4]),
104
+ c.cyan(padded[5]),
105
+ c.cyan(padded[6]),
106
+ c.cyan(padded[7]),
107
+ c.cyan(padded[8]),
108
+ c.dim(padded[9]),
109
+ c.dim(padded[10])
110
+ ].join(" ");
111
+ }
112
+ function renderTable(options) {
113
+ const output = [];
114
+ const benchMap = {};
115
+ for (const task of options.tasks) {
116
+ if (task.meta.benchmark && task.result?.benchmark) {
117
+ benchMap[task.id] = {
118
+ current: task.result.benchmark,
119
+ baseline: options.compare?.[task.id]
120
+ };
121
+ }
122
+ }
123
+ const benchCount = Object.entries(benchMap).length;
124
+ const columnWidths = computeColumnWidths(Object.values(benchMap).flatMap((v) => [v.current, v.baseline]).filter(notNullish));
125
+ let idx = 0;
126
+ const padding = " ".repeat(1 );
127
+ for (const task of options.tasks) {
128
+ const duration = task.result?.duration;
129
+ const bench = benchMap[task.id];
130
+ let prefix = "";
131
+ if (idx === 0 && task.meta?.benchmark) {
132
+ prefix += `${renderTableHead(columnWidths)}\n${padding}`;
133
+ }
134
+ prefix += ` ${getStateSymbol(task)} `;
135
+ let suffix = "";
136
+ if (task.type === "suite") {
137
+ suffix += c.dim(` (${getTests(task).length})`);
138
+ }
139
+ if (task.mode === "skip" || task.mode === "todo") {
140
+ suffix += c.dim(c.gray(" [skipped]"));
141
+ }
142
+ if (duration != null) {
143
+ const color = duration > options.slowTestThreshold ? c.yellow : c.green;
144
+ suffix += color(` ${Math.round(duration)}${c.dim("ms")}`);
145
+ }
146
+ if (options.showHeap && task.result?.heap != null) {
147
+ suffix += c.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`);
148
+ }
149
+ if (bench) {
150
+ let body = renderBenchmark(bench.current, columnWidths);
151
+ if (options.compare && bench.baseline) {
152
+ if (bench.current.hz) {
153
+ const diff = bench.current.hz / bench.baseline.hz;
154
+ const diffFixed = diff.toFixed(2);
155
+ if (diffFixed === "1.0.0") {
156
+ body += c.gray(` [${diffFixed}x]`);
157
+ }
158
+ if (diff > 1) {
159
+ body += c.blue(` [${diffFixed}x] ⇑`);
160
+ } else {
161
+ body += c.red(` [${diffFixed}x] ⇓`);
162
+ }
163
+ }
164
+ output.push(padding + prefix + body + suffix);
165
+ const bodyBaseline = renderBenchmark(bench.baseline, columnWidths);
166
+ output.push(`${padding} ${bodyBaseline} ${c.dim("(baseline)")}`);
167
+ } else {
168
+ if (bench.current.rank === 1 && benchCount > 1) {
169
+ body += c.bold(c.green(" fastest"));
170
+ }
171
+ if (bench.current.rank === benchCount && benchCount > 2) {
172
+ body += c.bold(c.gray(" slowest"));
173
+ }
174
+ output.push(padding + prefix + body + suffix);
175
+ }
176
+ } else {
177
+ output.push(padding + prefix + task.name + suffix);
178
+ }
179
+ if (task.result?.state !== "pass" && outputMap.get(task) != null) {
180
+ let data = outputMap.get(task);
181
+ if (typeof data === "string") {
182
+ data = stripVTControlCharacters(data.trim().split("\n").filter(Boolean).pop());
183
+ if (data === "") {
184
+ data = undefined;
185
+ }
186
+ }
187
+ if (data != null) {
188
+ const out = ` ${" ".repeat(options.level)}${F_RIGHT} ${data}`;
189
+ output.push(c.gray(truncateString(out, options.columns)));
190
+ }
191
+ }
192
+ idx++;
193
+ }
194
+ return output.filter(Boolean).join("\n");
195
+ }
196
+
197
+ class BenchmarkReporter extends DefaultReporter {
198
+ compare;
199
+ async onInit(ctx) {
200
+ super.onInit(ctx);
201
+ if (this.ctx.config.benchmark?.compare) {
202
+ const compareFile = pathe.resolve(this.ctx.config.root, this.ctx.config.benchmark?.compare);
203
+ try {
204
+ this.compare = flattenFormattedBenchmarkReport(JSON.parse(await fs.promises.readFile(compareFile, "utf-8")));
205
+ } catch (e) {
206
+ this.error(`Failed to read '${compareFile}'`, e);
207
+ }
208
+ }
209
+ }
210
+ onTaskUpdate(packs) {
211
+ for (const pack of packs) {
212
+ const task = this.ctx.state.idMap.get(pack[0]);
213
+ if (task?.type === "suite" && task.result?.state !== "run") {
214
+ task.tasks.filter((task) => task.result?.benchmark).sort((benchA, benchB) => benchA.result.benchmark.mean - benchB.result.benchmark.mean).forEach((bench, idx) => {
215
+ bench.result.benchmark.rank = Number(idx) + 1;
216
+ });
217
+ }
218
+ }
219
+ }
220
+ onTestSuiteResult(testSuite) {
221
+ super.onTestSuiteResult(testSuite);
222
+ this.printSuiteTable(testSuite);
223
+ }
224
+ printTestModule(testModule) {
225
+ this.printSuiteTable(testModule);
226
+ }
227
+ printSuiteTable(testTask) {
228
+ const state = testTask.state();
229
+ if (state === "pending" || state === "queued") {
230
+ return;
231
+ }
232
+ const benches = testTask.task.tasks.filter((t) => t.meta.benchmark);
233
+ const duration = testTask.task.result?.duration || 0;
234
+ if (benches.length > 0 && benches.every((t) => t.result?.state !== "run" && t.result?.state !== "queued")) {
235
+ let title = `\n ${getStateSymbol(testTask.task)} ${formatProjectName(testTask.project)}${getFullName(testTask.task, c.dim(" > "))}`;
236
+ if (duration != null && duration > this.ctx.config.slowTestThreshold) {
237
+ title += c.yellow(` ${Math.round(duration)}${c.dim("ms")}`);
238
+ }
239
+ this.log(title);
240
+ this.log(renderTable({
241
+ tasks: benches,
242
+ level: 1,
243
+ columns: this.ctx.logger.getColumns(),
244
+ compare: this.compare,
245
+ showHeap: this.ctx.config.logHeapUsage,
246
+ slowTestThreshold: this.ctx.config.slowTestThreshold
247
+ }));
248
+ }
249
+ }
250
+ async onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
251
+ super.onFinished(files, errors);
252
+ // write output for future comparison
253
+ let outputFile = this.ctx.config.benchmark?.outputJson;
254
+ if (outputFile) {
255
+ outputFile = pathe.resolve(this.ctx.config.root, outputFile);
256
+ const outputDirectory = pathe.dirname(outputFile);
257
+ if (!fs.existsSync(outputDirectory)) {
258
+ await fs.promises.mkdir(outputDirectory, { recursive: true });
259
+ }
260
+ const output = createBenchmarkJsonReport(files);
261
+ await fs.promises.writeFile(outputFile, JSON.stringify(output, null, 2));
262
+ this.log(`Benchmark report written to ${outputFile}`);
263
+ }
264
+ }
265
+ }
266
+
267
+ class VerboseBenchmarkReporter extends BenchmarkReporter {
268
+ verbose = true;
269
+ }
270
+
271
+ const BenchmarkReportsMap = {
272
+ default: BenchmarkReporter,
273
+ verbose: VerboseBenchmarkReporter
274
+ };
275
+
276
+ export { BenchmarkReporter as B, VerboseBenchmarkReporter as V, BenchmarkReportsMap as a };
@@ -1,4 +1,4 @@
1
- import p from 'node:path';
1
+ import path from 'node:path';
2
2
  import { fileURLToPath } from 'node:url';
3
3
  import process$1 from 'node:process';
4
4
  import { promises } from 'node:fs';
@@ -237,7 +237,7 @@ async function locatePath(
237
237
 
238
238
  return pLocate(paths, async path_ => {
239
239
  try {
240
- const stat = await statFunction(p.resolve(cwd, path_));
240
+ const stat = await statFunction(path.resolve(cwd, path_));
241
241
  return matchType(type, stat);
242
242
  } catch {
243
243
  return false;
@@ -250,9 +250,9 @@ const toPath = urlOrPath => urlOrPath instanceof URL ? fileURLToPath(urlOrPath)
250
250
  const findUpStop = Symbol('findUpStop');
251
251
 
252
252
  async function findUpMultiple(name, options = {}) {
253
- let directory = p.resolve(toPath(options.cwd) || '');
254
- const {root} = p.parse(directory);
255
- const stopAt = p.resolve(directory, options.stopAt || root);
253
+ let directory = path.resolve(toPath(options.cwd) || '');
254
+ const {root} = path.parse(directory);
255
+ const stopAt = path.resolve(directory, options.stopAt || root);
256
256
  const limit = options.limit || Number.POSITIVE_INFINITY;
257
257
  const paths = [name].flat();
258
258
 
@@ -280,14 +280,14 @@ async function findUpMultiple(name, options = {}) {
280
280
  }
281
281
 
282
282
  if (foundPath) {
283
- matches.push(p.resolve(directory, foundPath));
283
+ matches.push(path.resolve(directory, foundPath));
284
284
  }
285
285
 
286
286
  if (directory === stopAt || matches.length >= limit) {
287
287
  break;
288
288
  }
289
289
 
290
- directory = p.dirname(directory);
290
+ directory = path.dirname(directory);
291
291
  }
292
292
 
293
293
  return matches;
@@ -13,11 +13,13 @@ function setupInspect(ctx) {
13
13
  const isEnabled = config.inspector.enabled;
14
14
  if (isEnabled) {
15
15
  inspector = __require("node:inspector");
16
+ // Inspector may be open already if "isolate: false" is used
16
17
  const isOpen = inspector.url() !== undefined;
17
18
  if (!isOpen) {
18
19
  inspector.open(config.inspector.port, config.inspector.host, config.inspector.waitForDebugger);
19
20
  if (config.inspectBrk) {
20
21
  const firstTestFile = typeof ctx.files[0] === "string" ? ctx.files[0] : ctx.files[0].filepath;
22
+ // Stop at first test file
21
23
  if (firstTestFile) {
22
24
  session = new inspector.Session();
23
25
  session.connect();
@@ -46,6 +48,7 @@ function closeInspector(config) {
46
48
  }
47
49
  }
48
50
  function shouldKeepOpen(config) {
51
+ // In watch mode the inspector can persist re-runs if isolation is disabled and a single worker is used
49
52
  const isIsolatedSingleThread = config.pool === "threads" && config.poolOptions?.threads?.isolate === false && config.poolOptions?.threads?.singleThread;
50
53
  const isIsolatedSingleFork = config.pool === "forks" && config.poolOptions?.forks?.isolate === false && config.poolOptions?.forks?.singleFork;
51
54
  return config.watch && (isIsolatedSingleFork || isIsolatedSingleThread);
@@ -1,5 +1,5 @@
1
1
  import { NodeSnapshotEnvironment } from '@vitest/snapshot/environment';
2
- import { g as getWorkerState } from './utils.CgTj3MsC.js';
2
+ import { g as getWorkerState } from './utils.BlI4TC7Y.js';
3
3
  import '@vitest/utils';
4
4
 
5
5
  class VitestNodeSnapshotEnvironment extends NodeSnapshotEnvironment {