vitest 5.0.0-beta.5 → 5.0.0-beta.7

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 (76) hide show
  1. package/LICENSE.md +165 -1
  2. package/dist/browser.d.ts +27 -14
  3. package/dist/browser.js +11 -14
  4. package/dist/chunks/{artifact.C0OHWdod.js → artifact.DC5WoEgy.js} +1310 -13
  5. package/dist/chunks/{base.BPbmtl-C.js → base.B0fUxpj9.js} +17 -13
  6. package/dist/chunks/{browser.d.B-p-y0sB.d.ts → browser.d.BFOby8YL.d.ts} +3 -3
  7. package/dist/chunks/{cac.DYQRhgb-.js → cac.B41kXwyU.js} +22 -24
  8. package/dist/chunks/check.Cz_-YojU.js +15 -0
  9. package/dist/chunks/cli-api.bqNN5viV.js +519 -0
  10. package/dist/chunks/{config.d.Bkl6J5iR.d.ts → config.d.DsC1jkby.d.ts} +877 -27
  11. package/dist/chunks/{console.DjVIMaXT.js → console.omGxyKMT.js} +5 -5
  12. package/dist/chunks/{coverage.CTzCuANN.js → coverage.BVb1JqW7.js} +7 -2
  13. package/dist/chunks/coverage.BfSEMtie.js +26 -0
  14. package/dist/chunks/coverage.d.ByaAMV4A.d.ts +88 -0
  15. package/dist/chunks/{creator.CJiHagNv.js → creator.BzMFaPC-.js} +54 -30
  16. package/dist/chunks/{defaults.CUUnbOrq.js → defaults.BJUmAuaO.js} +3 -2
  17. package/dist/chunks/display.CYwyMF4S.js +192 -0
  18. package/dist/chunks/{env.BKKtU2WC.js → env.DzFJjrmK.js} +1 -1
  19. package/dist/chunks/{environment.d.CrsxCzP1.d.ts → environment.d.4-rzQgpt.d.ts} +1 -1
  20. package/dist/chunks/globals.sd6Qutmc.js +28 -0
  21. package/dist/chunks/{cli-api.SMst4llK.js → index.5krd73UD.js} +14591 -13056
  22. package/dist/chunks/{index.CXzZ7KB8.js → index.CLtI1k_4.js} +627 -214
  23. package/dist/chunks/{index.DzNNaFWy.js → index.DxR-nMjO.js} +63 -10
  24. package/dist/chunks/index.DzTmMrSM.js +940 -0
  25. package/dist/chunks/{index.DugGyGng.js → index.JaztIWgW.js} +6 -5
  26. package/dist/chunks/{init-forks.CDWjf0q6.js → init-forks.CXzT841o.js} +1 -1
  27. package/dist/chunks/{init-threads.B-vZ8N2q.js → init-threads.Ch-Bw5j3.js} +1 -1
  28. package/dist/chunks/{init.gslB1aqB.js → init.CfiYZpFg.js} +41 -25
  29. package/dist/chunks/{native.DPzPHdi5.js → native.BUCvPRKp.js} +3 -4
  30. package/dist/chunks/{nativeModuleMocker.CrcWvO03.js → nativeModuleMocker.Uot80PXb.js} +2 -3
  31. package/dist/chunks/{index.CesbTg1C.js → nativeModuleRunner.BDnwGb8g.js} +39 -3
  32. package/dist/chunks/{node.C9I1sbE9.js → node.BPMnm_Q2.js} +1 -1
  33. package/dist/chunks/offset.Dy-5Fdfn.js +24 -0
  34. package/dist/chunks/pathe.M-eThtNZ.CbK_Vbae.js +489 -0
  35. package/dist/chunks/{plugin.d.BuiCQSo8.d.ts → plugin.d.BOjbmxWW.d.ts} +1757 -1566
  36. package/dist/chunks/{plugins.DrsmdUE2.js → plugins.CsoX-42X.js} +1 -1
  37. package/dist/chunks/resolver.CERfsKE-.js +48 -0
  38. package/dist/chunks/{rpc.d.BLxNuPAq.d.ts → rpc.d.BeasqWpO.d.ts} +14 -1
  39. package/dist/chunks/{rpc.DZEh5xnQ.js → rpc.iNjF664v.js} +2 -2
  40. package/dist/chunks/setup-common.vxjAyUtK.js +36 -0
  41. package/dist/chunks/setup.DasACXvo.js +5409 -0
  42. package/dist/chunks/source-map.DZdIqpIJ.js +1776 -0
  43. package/dist/chunks/spy.B8mHA9qu.js +422 -0
  44. package/dist/chunks/{task-utils.d.CLWcZaUf.d.ts → task-utils.d.BKHiHxSN.d.ts} +20 -2
  45. package/dist/chunks/tinyrainbow.Ht9iggcq.js +95 -0
  46. package/dist/chunks/{utils.DKODp04v.js → utils.CO-iLyCr.js} +41 -42
  47. package/dist/chunks/{vm._FqKqltU.js → vm.DoQh8CN9.js} +110 -11
  48. package/dist/chunks/{worker.d.Cb0Z-SnE.d.ts → worker.d.s_RdeZtI.d.ts} +14 -11
  49. package/dist/cli.js +4 -5
  50. package/dist/config.cjs +2 -1
  51. package/dist/config.d.ts +19 -17
  52. package/dist/config.js +2 -2
  53. package/dist/index.d.ts +241 -31
  54. package/dist/index.js +11 -16
  55. package/dist/module-evaluator.d.ts +40 -8
  56. package/dist/module-evaluator.js +73 -22
  57. package/dist/node.d.ts +225 -86
  58. package/dist/node.js +30 -66
  59. package/dist/runtime.d.ts +6 -11
  60. package/dist/runtime.js +4 -5
  61. package/dist/spy.js +1 -1
  62. package/dist/task-utils.js +1 -2
  63. package/dist/worker.d.ts +5 -10
  64. package/dist/worker.js +24 -36
  65. package/dist/workers/forks.js +21 -33
  66. package/dist/workers/runVmTests.js +15 -20
  67. package/dist/workers/threads.js +21 -33
  68. package/dist/workers/vmForks.js +13 -15
  69. package/dist/workers/vmThreads.js +13 -15
  70. package/package.json +20 -20
  71. package/dist/chunks/_commonjsHelpers.D26ty3Ew.js +0 -6
  72. package/dist/chunks/coverage.d.Dn6XbyQq.d.ts +0 -43
  73. package/dist/chunks/globals.D2wDMk06.js +0 -33
  74. package/dist/chunks/index.6dZyLbho.js +0 -6918
  75. package/dist/chunks/nativeModuleRunner.WlMdOB52.js +0 -36
  76. package/dist/chunks/setup-common.DRlwpHsL.js +0 -64
@@ -0,0 +1,519 @@
1
+ import { mkdirSync, writeFileSync } from 'node:fs';
2
+ import { C as CoverageProviderMap } from './coverage.BVb1JqW7.js';
3
+ import { P as PluginHarness, L as Logger, j as VitestPackageInstaller, u as resolveConfig, V as Vitest, y as stdout, w as prompt, f as FilesNotFoundError, G as GitNotFoundError, I as IncludeTaskLocationDisabledError, z as RangeLocationFilterProvidedError, A as LocationFilterFileNotFoundError } from './index.5krd73UD.js';
4
+ import readline from 'node:readline';
5
+ import { y } from './tinyrainbow.Ht9iggcq.js';
6
+ import { i as isWindows } from './env.DzFJjrmK.js';
7
+ import { stripVTControlCharacters } from 'node:util';
8
+ import { e as createDefer, a as relative, r as resolve, d as dirname, i as isAbsolute } from './pathe.M-eThtNZ.CbK_Vbae.js';
9
+
10
+ async function createVitest(modeOrOptions, optionsOrViteOverrides = {}, viteOverridesOrVitestOptions = {}, maybeVitestOptions = {}) {
11
+ let options;
12
+ let viteOverrides;
13
+ let vitestOptions;
14
+ if (typeof modeOrOptions === "string") {
15
+ options = optionsOrViteOverrides;
16
+ viteOverrides = viteOverridesOrVitestOptions;
17
+ vitestOptions = maybeVitestOptions;
18
+ } else {
19
+ options = modeOrOptions;
20
+ viteOverrides = optionsOrViteOverrides;
21
+ vitestOptions = viteOverridesOrVitestOptions;
22
+ }
23
+ const pluginHarness = new PluginHarness(new Logger(vitestOptions.stdout, vitestOptions.stderr), vitestOptions.packageInstaller ?? new VitestPackageInstaller());
24
+ const config = await resolveConfig(options, viteOverrides, pluginHarness);
25
+ const vitest = new Vitest(pluginHarness, config);
26
+ try {
27
+ await vitest._start(config);
28
+ if (vitest.config.api.port && vitest.config.ui && vitest.config.open) vitest.vite.openBrowser();
29
+ return vitest;
30
+ }
31
+ // Vitest can fail at any point during setup or inside a custom plugin.
32
+ // Make sure everything is properly closed (like the logger).
33
+ catch (error) {
34
+ await vitest.close();
35
+ throw error;
36
+ }
37
+ }
38
+
39
+ const MAX_RESULT_COUNT = 10;
40
+ const SELECTION_MAX_INDEX = 7;
41
+ const ESC = "\x1B[";
42
+ class WatchFilter {
43
+ filterRL;
44
+ currentKeyword = void 0;
45
+ message;
46
+ results = [];
47
+ selectionIndex = -1;
48
+ onKeyPress;
49
+ stdin;
50
+ stdout;
51
+ constructor(message, stdin = process.stdin, stdout$1 = stdout()) {
52
+ this.message = message;
53
+ this.stdin = stdin;
54
+ this.stdout = stdout$1;
55
+ this.filterRL = readline.createInterface({
56
+ input: this.stdin,
57
+ escapeCodeTimeout: 50
58
+ });
59
+ readline.emitKeypressEvents(this.stdin, this.filterRL);
60
+ if (this.stdin.isTTY) this.stdin.setRawMode(true);
61
+ }
62
+ async filter(filterFunc) {
63
+ this.write(this.promptLine());
64
+ const resultPromise = createDefer();
65
+ this.onKeyPress = this.filterHandler(filterFunc, (result) => {
66
+ resultPromise.resolve(result);
67
+ });
68
+ this.stdin.on("keypress", this.onKeyPress);
69
+ try {
70
+ return await resultPromise;
71
+ } finally {
72
+ this.close();
73
+ }
74
+ }
75
+ filterHandler(filterFunc, onSubmit) {
76
+ return async (str, key) => {
77
+ switch (true) {
78
+ case key.sequence === "":
79
+ if (this.currentKeyword && this.currentKeyword?.length > 1) this.currentKeyword = this.currentKeyword?.slice(0, -1);
80
+ else this.currentKeyword = void 0;
81
+ break;
82
+ case key?.ctrl && key?.name === "c":
83
+ case key?.name === "escape":
84
+ this.write(`${ESC}1G${ESC}0J`);
85
+ onSubmit(void 0);
86
+ return;
87
+ case key?.name === "enter":
88
+ case key?.name === "return": {
89
+ const selection = this.results[this.selectionIndex];
90
+ onSubmit((typeof selection === "string" ? selection : selection?.key) || this.currentKeyword || "");
91
+ this.currentKeyword = void 0;
92
+ break;
93
+ }
94
+ case key?.name === "up":
95
+ if (this.selectionIndex && this.selectionIndex > 0) this.selectionIndex--;
96
+ else this.selectionIndex = -1;
97
+ break;
98
+ case key?.name === "down":
99
+ if (this.selectionIndex < this.results.length - 1) this.selectionIndex++;
100
+ else if (this.selectionIndex >= this.results.length - 1) this.selectionIndex = this.results.length - 1;
101
+ break;
102
+ case !key?.ctrl && !key?.meta:
103
+ if (this.currentKeyword === void 0) this.currentKeyword = str;
104
+ else this.currentKeyword += str || "";
105
+ break;
106
+ }
107
+ if (this.currentKeyword) this.results = await filterFunc(this.currentKeyword);
108
+ this.render();
109
+ };
110
+ }
111
+ render() {
112
+ let printStr = this.promptLine();
113
+ if (!this.currentKeyword) printStr += "\nPlease input filter pattern";
114
+ else if (this.currentKeyword && this.results.length === 0) printStr += "\nPattern matches no results";
115
+ else {
116
+ const resultCountLine = this.results.length === 1 ? `Pattern matches ${this.results.length} result` : `Pattern matches ${this.results.length} results`;
117
+ let resultBody = "";
118
+ if (this.results.length > MAX_RESULT_COUNT) {
119
+ const offset = this.selectionIndex > SELECTION_MAX_INDEX ? this.selectionIndex - SELECTION_MAX_INDEX : 0;
120
+ const displayResults = this.results.slice(offset, MAX_RESULT_COUNT + offset);
121
+ const remainingResultCount = this.results.length - offset - displayResults.length;
122
+ resultBody = `${displayResults.map((result, index) => index + offset === this.selectionIndex ? y.green(` › ${result}`) : y.dim(` › ${result}`)).join("\n")}`;
123
+ if (remainingResultCount > 0) resultBody += `
124
+ ${y.dim(` ...and ${remainingResultCount} more ${remainingResultCount === 1 ? "result" : "results"}`)}`;
125
+ } else resultBody = this.results.map((result, index) => index === this.selectionIndex ? y.green(` › ${result}`) : y.dim(` › ${result}`)).join("\n");
126
+ printStr += `\n${resultCountLine}\n${resultBody}`;
127
+ }
128
+ this.eraseAndPrint(printStr);
129
+ this.restoreCursor();
130
+ }
131
+ keywordOffset() {
132
+ return `? ${this.message} › `.length + 1;
133
+ }
134
+ promptLine() {
135
+ return `${y.cyan("?")} ${y.bold(this.message)} › ${this.currentKeyword || ""}`;
136
+ }
137
+ eraseAndPrint(str) {
138
+ let rows = 0;
139
+ const lines = str.split(/\r?\n/);
140
+ for (const line of lines) {
141
+ const columns = "columns" in this.stdout ? this.stdout.columns : 80;
142
+ // We have to take care of screen width in case of long lines
143
+ rows += 1 + Math.floor(Math.max(stripVTControlCharacters(line).length - 1, 0) / columns);
144
+ }
145
+ this.write(`${ESC}1G`);
146
+ this.write(`${ESC}J`);
147
+ this.write(str);
148
+ this.write(`${ESC}${rows - 1}A`);
149
+ }
150
+ close() {
151
+ this.filterRL.close();
152
+ if (this.onKeyPress) this.stdin.removeListener("keypress", this.onKeyPress);
153
+ if (this.stdin.isTTY) this.stdin.setRawMode(false);
154
+ }
155
+ restoreCursor() {
156
+ const cursorPos = this.keywordOffset() + (this.currentKeyword?.length || 0);
157
+ this.write(`${ESC}${cursorPos}G`);
158
+ }
159
+ write(data) {
160
+ this.stdout.write(data);
161
+ }
162
+ getLastResults() {
163
+ return this.results.map((r) => typeof r === "string" ? r : r.toString());
164
+ }
165
+ }
166
+
167
+ const keys = [
168
+ [["a", "return"], "rerun all tests"],
169
+ ["r", "rerun current pattern tests"],
170
+ ["f", "rerun only failed tests"],
171
+ ["u", "update snapshot"],
172
+ ["p", "filter by a filename"],
173
+ ["t", "filter by a test name regex pattern"],
174
+ ["w", "filter by a project name"],
175
+ ["q", "quit"]
176
+ ];
177
+ const cancelKeys = [
178
+ "space",
179
+ "c",
180
+ "h",
181
+ ...keys.map((key) => key[0]).flat()
182
+ ];
183
+ function printShortcutsHelp() {
184
+ stdout().write(`
185
+ ${y.bold(" Watch Usage")}
186
+ ${keys.map((i) => y.dim(" press ") + y.reset([i[0]].flat().map(y.bold).join(", ")) + y.dim(` to ${i[1]}`)).join("\n")}
187
+ `);
188
+ }
189
+ function* traverseFilteredTestNames(parentName, filter, t) {
190
+ if (t.type === "test") {
191
+ if (t.name.match(filter)) {
192
+ const displayName = `${parentName} > ${t.name}`;
193
+ yield {
194
+ key: t.name,
195
+ toString: () => displayName
196
+ };
197
+ }
198
+ } else {
199
+ parentName = parentName.length ? `${parentName} > ${t.name}` : t.name;
200
+ for (const task of t.tasks) yield* traverseFilteredTestNames(parentName, filter, task);
201
+ }
202
+ }
203
+ function* getFilteredTestNames(pattern, suite) {
204
+ try {
205
+ const reg = new RegExp(pattern);
206
+ // TODO: we cannot run tests per workspace yet: filtering files
207
+ const files = /* @__PURE__ */ new Set();
208
+ for (const file of suite) if (!files.has(file.name)) {
209
+ files.add(file.name);
210
+ yield* traverseFilteredTestNames("", reg, file);
211
+ }
212
+ } catch {}
213
+ }
214
+ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
215
+ let latestFilename = "";
216
+ async function _keypressHandler(str, key) {
217
+ // Cancel run and exit when ctrl-c or esc is pressed.
218
+ // If cancelling takes long and key is pressed multiple times, exit forcefully.
219
+ if (str === "" || str === "\x1B" || key && key.ctrl && key.name === "c") {
220
+ if (!ctx.isCancelling) {
221
+ ctx.logger.log(y.red("Cancelling test run. Press CTRL+c again to exit forcefully.\n"));
222
+ process.exitCode = 130;
223
+ await ctx.cancelCurrentRun("keyboard-input");
224
+ }
225
+ return ctx.exit(true);
226
+ }
227
+ // window not support suspend
228
+ if (!isWindows && key && key.ctrl && key.name === "z") {
229
+ process.kill(process.ppid, "SIGTSTP");
230
+ process.kill(process.pid, "SIGTSTP");
231
+ return;
232
+ }
233
+ const name = key?.name;
234
+ if (ctx.runningPromise) {
235
+ if (cancelKeys.includes(name)) await ctx.cancelCurrentRun("keyboard-input");
236
+ return;
237
+ }
238
+ // quit
239
+ if (name === "q") return ctx.exit(true);
240
+ // help
241
+ if (name === "h") return printShortcutsHelp();
242
+ // update snapshot
243
+ if (name === "u") return ctx.updateSnapshot();
244
+ // rerun all tests
245
+ if (name === "a" || name === "return") {
246
+ const files = await ctx._globTestFilepaths();
247
+ return ctx.changeNamePattern("", files, "rerun all tests");
248
+ }
249
+ // rerun current pattern tests
250
+ if (name === "r") return ctx.rerunFiles();
251
+ // rerun only failed tests
252
+ if (name === "f") return ctx.rerunFailed();
253
+ // change project filter
254
+ if (name === "w") return inputProjectName();
255
+ // change testNamePattern
256
+ if (name === "t") return inputNamePattern();
257
+ // change fileNamePattern
258
+ if (name === "p") return inputFilePattern();
259
+ }
260
+ async function keypressHandler(str, key) {
261
+ await _keypressHandler(str, key);
262
+ }
263
+ async function inputNamePattern() {
264
+ off();
265
+ const filter = await new WatchFilter("Input test name pattern (RegExp)", stdin, stdout).filter((str) => {
266
+ return [...getFilteredTestNames(str, ctx.state.getFiles())];
267
+ });
268
+ on();
269
+ if (typeof filter === "undefined") return;
270
+ const files = ctx.state.getFilepaths();
271
+ // if running in standalone mode, Vitest instance doesn't know about any test file
272
+ const cliFiles = ctx.config.standalone && !files.length ? await ctx._globTestFilepaths() : void 0;
273
+ await ctx.changeNamePattern(filter?.trim() || "", cliFiles, "change pattern");
274
+ }
275
+ async function inputProjectName() {
276
+ off();
277
+ const { filter = "" } = await prompt([{
278
+ name: "filter",
279
+ type: "text",
280
+ message: "Input a single project name",
281
+ initial: ctx.config.project[0] || ""
282
+ }]);
283
+ on();
284
+ await ctx.changeProjectName(filter.trim());
285
+ }
286
+ async function inputFilePattern() {
287
+ off();
288
+ const watchFilter = new WatchFilter("Input filename pattern", stdin, stdout);
289
+ const filter = await watchFilter.filter(async (str) => {
290
+ return (await ctx.globTestSpecifications([str])).map((specification) => relative(ctx.config.root, specification.moduleId)).filter((file, index, all) => all.indexOf(file) === index);
291
+ });
292
+ on();
293
+ if (typeof filter === "undefined") return;
294
+ latestFilename = filter?.trim() || "";
295
+ const lastResults = watchFilter.getLastResults();
296
+ await ctx.changeFilenamePattern(latestFilename, filter && lastResults.length ? lastResults.map((i) => resolve(ctx.config.root, i)) : void 0);
297
+ }
298
+ let rl;
299
+ function on() {
300
+ off();
301
+ rl = readline.createInterface({
302
+ input: stdin,
303
+ escapeCodeTimeout: 50
304
+ });
305
+ readline.emitKeypressEvents(stdin, rl);
306
+ if (stdin.isTTY) stdin.setRawMode(true);
307
+ stdin.on("keypress", keypressHandler);
308
+ }
309
+ function off() {
310
+ rl?.close();
311
+ rl = void 0;
312
+ stdin.removeListener("keypress", keypressHandler);
313
+ if (stdin.isTTY) stdin.setRawMode(false);
314
+ }
315
+ on();
316
+ return function cleanup() {
317
+ off();
318
+ };
319
+ }
320
+
321
+ async function startVitest(modeOrCliFilters, cliFiltersOrOptions, optionsOrViteOverrides, viteOverridesOrVitestOptions, maybeVitestOptions) {
322
+ let cliFilters;
323
+ let options;
324
+ let viteOverrides;
325
+ let vitestOptions;
326
+ if (typeof modeOrCliFilters === "string") {
327
+ cliFilters = cliFiltersOrOptions ?? [];
328
+ options = optionsOrViteOverrides ?? {};
329
+ viteOverrides = viteOverridesOrVitestOptions;
330
+ vitestOptions = maybeVitestOptions;
331
+ } else {
332
+ cliFilters = modeOrCliFilters ?? [];
333
+ options = cliFiltersOrOptions ?? {};
334
+ viteOverrides = optionsOrViteOverrides;
335
+ vitestOptions = viteOverridesOrVitestOptions;
336
+ }
337
+ const root = resolve(options.root || process.cwd());
338
+ const ctx = await prepareVitest(options, viteOverrides, vitestOptions, cliFilters);
339
+ if (ctx._coverageOptions.enabled) {
340
+ const requiredPackages = CoverageProviderMap[ctx._coverageOptions.provider || "v8"];
341
+ if (requiredPackages) {
342
+ if (!await ctx.packageInstaller.ensureInstalled(requiredPackages, root, ctx.version)) {
343
+ process.exitCode = 1;
344
+ return ctx;
345
+ }
346
+ }
347
+ }
348
+ const stdin = vitestOptions?.stdin || process.stdin;
349
+ const stdout = vitestOptions?.stdout || process.stdout;
350
+ let stdinCleanup;
351
+ if (stdin.isTTY && ctx.config.watch) stdinCleanup = registerConsoleShortcuts(ctx, stdin, stdout);
352
+ ctx.onAfterSetServer(() => {
353
+ if (ctx.config.standalone) ctx.standalone();
354
+ else ctx.start(cliFilters);
355
+ });
356
+ try {
357
+ if (ctx.config.listTags) await ctx.listTags();
358
+ else if (ctx.config.clearCache) await ctx.experimental_clearCache();
359
+ else if (ctx.config.mergeReports) await ctx.mergeReports();
360
+ else if (ctx.config.standalone) await ctx.standalone();
361
+ else await ctx.start(cliFilters);
362
+ return ctx;
363
+ } catch (e) {
364
+ if (e instanceof FilesNotFoundError) return ctx;
365
+ if (e instanceof GitNotFoundError) {
366
+ ctx.logger.error(e.message);
367
+ return ctx;
368
+ }
369
+ if (e instanceof IncludeTaskLocationDisabledError || e instanceof RangeLocationFilterProvidedError || e instanceof LocationFilterFileNotFoundError) {
370
+ ctx.logger.printError(e, { verbose: false });
371
+ return ctx;
372
+ }
373
+ process.exitCode = 1;
374
+ ctx.logger.printError(e, {
375
+ fullStack: true,
376
+ type: "Unhandled Error"
377
+ });
378
+ ctx.logger.error("\n\n");
379
+ return ctx;
380
+ } finally {
381
+ if (!ctx?.shouldKeepServer()) {
382
+ stdinCleanup?.();
383
+ await ctx.close();
384
+ }
385
+ }
386
+ }
387
+ async function prepareVitest(modeOrOptions, optionsOrViteOverrides, viteOverridesOrVitestOptions, vitestOptionsOrCliFilters, maybeCliFilters) {
388
+ let options;
389
+ let viteOverrides;
390
+ let vitestOptions;
391
+ let cliFilters;
392
+ if (typeof modeOrOptions === "string") {
393
+ options = optionsOrViteOverrides ?? {};
394
+ viteOverrides = viteOverridesOrVitestOptions;
395
+ vitestOptions = vitestOptionsOrCliFilters;
396
+ cliFilters = maybeCliFilters;
397
+ } else {
398
+ options = modeOrOptions ?? {};
399
+ viteOverrides = optionsOrViteOverrides;
400
+ vitestOptions = viteOverridesOrVitestOptions;
401
+ cliFilters = vitestOptionsOrCliFilters;
402
+ }
403
+ process.env.TEST = "true";
404
+ process.env.VITEST = "true";
405
+ process.env.NODE_ENV ??= "test";
406
+ if (options.run) options.watch = false;
407
+ if (options.standalone && (cliFilters?.length || 0) > 0) options.standalone = false;
408
+ // this shouldn't affect _application root_ that can be changed inside config
409
+ const root = resolve(options.root || process.cwd());
410
+ const ctx = await createVitest(options, viteOverrides, vitestOptions);
411
+ const environmentPackage = getEnvPackageName(ctx.config.environment);
412
+ if (environmentPackage && !await ctx.packageInstaller.ensureInstalled(environmentPackage, root)) {
413
+ process.exitCode = 1;
414
+ return ctx;
415
+ }
416
+ return ctx;
417
+ }
418
+ function processCollected(ctx, files, options) {
419
+ let errorsPrinted = false;
420
+ forEachSuite(files, (suite) => {
421
+ suite.errors().forEach((error) => {
422
+ errorsPrinted = true;
423
+ ctx.logger.printError(error, { project: suite.project });
424
+ });
425
+ });
426
+ if (errorsPrinted) return;
427
+ if (typeof options.json !== "undefined") return processJsonOutput(files, options);
428
+ return formatCollectedAsString(files).forEach((test) => console.log(test));
429
+ }
430
+ function outputFileList(files, options) {
431
+ if (typeof options.json !== "undefined") return outputJsonFileList(files, options);
432
+ formatFilesAsString(files, options).map((file) => console.log(file));
433
+ }
434
+ function outputJsonFileList(files, options) {
435
+ if (typeof options.json === "boolean") return console.log(JSON.stringify(formatFilesAsJSON(files), null, 2));
436
+ if (typeof options.json === "string") {
437
+ const jsonPath = resolve(options.root || process.cwd(), options.json);
438
+ mkdirSync(dirname(jsonPath), { recursive: true });
439
+ writeFileSync(jsonPath, JSON.stringify(formatFilesAsJSON(files), null, 2));
440
+ }
441
+ }
442
+ function formatFilesAsJSON(files) {
443
+ return files.map((file) => {
444
+ const result = { file: file.moduleId };
445
+ if (file.project.name) result.projectName = file.project.name;
446
+ return result;
447
+ });
448
+ }
449
+ function formatFilesAsString(files, options) {
450
+ return files.map((file) => {
451
+ let name = relative(options.root || process.cwd(), file.moduleId);
452
+ if (file.project.name) name = `[${file.project.name}] ${name}`;
453
+ return name;
454
+ });
455
+ }
456
+ function processJsonOutput(files, options) {
457
+ if (typeof options.json === "boolean") return console.log(JSON.stringify(formatCollectedAsJSON(files), null, 2));
458
+ if (typeof options.json === "string") {
459
+ const jsonPath = resolve(options.root || process.cwd(), options.json);
460
+ mkdirSync(dirname(jsonPath), { recursive: true });
461
+ writeFileSync(jsonPath, JSON.stringify(formatCollectedAsJSON(files), null, 2));
462
+ }
463
+ }
464
+ function forEachSuite(modules, callback) {
465
+ modules.forEach((testModule) => {
466
+ callback(testModule);
467
+ for (const suite of testModule.children.allSuites()) callback(suite);
468
+ });
469
+ }
470
+ function formatCollectedAsJSON(files) {
471
+ const results = [];
472
+ files.forEach((file) => {
473
+ for (const test of file.children.allTests()) {
474
+ if (test.result().state === "skipped") continue;
475
+ const result = {
476
+ name: test.fullName,
477
+ file: test.module.moduleId
478
+ };
479
+ if (test.project.name) result.projectName = test.project.name;
480
+ if (test.location) result.location = test.location;
481
+ results.push(result);
482
+ }
483
+ });
484
+ return results;
485
+ }
486
+ function formatCollectedAsString(testModules) {
487
+ const results = [];
488
+ testModules.forEach((testModule) => {
489
+ for (const test of testModule.children.allTests()) {
490
+ if (test.result().state === "skipped") continue;
491
+ const fullName = `${test.module.task.name} > ${test.fullName}`;
492
+ results.push((test.project.name ? `[${test.project.name}] ` : "") + fullName);
493
+ }
494
+ });
495
+ return results;
496
+ }
497
+ const envPackageNames = {
498
+ "jsdom": "jsdom",
499
+ "happy-dom": "happy-dom",
500
+ "edge-runtime": "@edge-runtime/vm"
501
+ };
502
+ function getEnvPackageName(env) {
503
+ if (env === "node") return null;
504
+ if (env in envPackageNames) return envPackageNames[env];
505
+ if (env[0] === "." || isAbsolute(env)) return null;
506
+ return `vitest-environment-${env}`;
507
+ }
508
+
509
+ var cliApi = /*#__PURE__*/Object.freeze({
510
+ __proto__: null,
511
+ formatCollectedAsJSON: formatCollectedAsJSON,
512
+ formatCollectedAsString: formatCollectedAsString,
513
+ outputFileList: outputFileList,
514
+ prepareVitest: prepareVitest,
515
+ processCollected: processCollected,
516
+ startVitest: startVitest
517
+ });
518
+
519
+ export { cliApi as a, createVitest as c, registerConsoleShortcuts as r, startVitest as s };