vitest 3.0.0-beta.3 → 3.0.0
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.
- package/LICENSE.md +1 -315
- package/config.d.ts +2 -0
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +1 -1
- package/dist/chunks/{base.CQ2VEtuH.js → base.CUDzyU2J.js} +2 -2
- package/dist/chunks/{cac.e7qW4xLT.js → cac.DZC9WjGM.js} +8 -8
- package/dist/chunks/{cli-api.CWDlED-m.js → cli-api.CmJw5Cd_.js} +920 -84
- package/dist/chunks/{config.BTPBhmK5.d.ts → config.BRtC-JeT.d.ts} +6 -0
- package/dist/chunks/{console.BYGVloWk.js → console.CN7AiMGV.js} +16 -7
- package/dist/chunks/{creator.Ot9GlSGw.js → creator.DztqrnyH.js} +1 -1
- package/dist/chunks/{execute.2pr0rHgK.js → execute.BMOaRArH.js} +27 -16
- package/dist/chunks/global.CnI8_G5V.d.ts +133 -0
- package/dist/chunks/{globals.BFncSRNA.js → globals.C5RQxaV3.js} +2 -2
- package/dist/chunks/{index.CkWmZCXU.js → index.BQbxGbG9.js} +1 -1
- package/dist/chunks/{index.BBoOXW-l.js → index.CUcwvygK.js} +5 -5
- package/dist/chunks/{index.DQboAxJm.js → index.D9C26wCk.js} +1 -0
- package/dist/chunks/index.TKSL1HjN.js +2460 -0
- package/dist/chunks/{reporters.DCiyjXOg.d.ts → reporters.Y8BYiXBN.d.ts} +412 -386
- package/dist/chunks/{resolveConfig.C1d7TK-U.js → resolveConfig.CSLLD33d.js} +140 -55
- package/dist/chunks/{rpc.C3q9uwRX.js → rpc.TVf73xOu.js} +0 -1
- package/dist/chunks/{runBaseTests.qNWRkgHj.js → runBaseTests.C0T_TQwH.js} +9 -7
- package/dist/chunks/{setup-common.Cp_bu5q3.js → setup-common.D0zLenuv.js} +1 -1
- package/dist/chunks/{RandomSequencer.C6x84bNN.js → typechecker.BJMkWMXo.js} +84 -108
- package/dist/chunks/{utils.Coei4Wlj.js → utils.DJWL04yX.js} +9 -20
- package/dist/chunks/{vi.S4Fq8wSo.js → vi.Da_PT3Vw.js} +554 -272
- package/dist/chunks/{vite.CRSMFy31.d.ts → vite.CQ0dHgkN.d.ts} +1 -1
- package/dist/chunks/{vm.DGhTouO3.js → vm.DrFVeTXo.js} +4 -4
- package/dist/chunks/{worker.R-PA7DpW.d.ts → worker.B1y96qmv.d.ts} +1 -1
- package/dist/chunks/{worker.XbtCXEXv.d.ts → worker.CIpff8Eg.d.ts} +3 -5
- package/dist/cli.js +1 -1
- package/dist/config.d.ts +4 -4
- package/dist/coverage.d.ts +2 -2
- package/dist/coverage.js +5 -4
- package/dist/execute.d.ts +3 -3
- package/dist/execute.js +1 -1
- package/dist/index.d.ts +18 -119
- package/dist/index.js +2 -2
- package/dist/node.d.ts +12 -9
- package/dist/node.js +25 -24
- package/dist/reporters.d.ts +2 -2
- package/dist/reporters.js +4 -10
- package/dist/runners.d.ts +2 -1
- package/dist/runners.js +9 -16
- package/dist/worker.js +1 -1
- package/dist/workers/forks.js +2 -2
- package/dist/workers/runVmTests.js +8 -6
- package/dist/workers/threads.js +2 -2
- package/dist/workers/vmForks.js +3 -3
- package/dist/workers/vmThreads.js +3 -3
- package/dist/workers.d.ts +3 -3
- package/dist/workers.js +5 -5
- package/package.json +17 -19
- package/dist/chunks/index.CzkCSFCy.js +0 -5455
- package/dist/chunks/types.BOjykUpq.d.ts +0 -27
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { existsSync, promises, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { normalize, relative, dirname, resolve, join, basename, isAbsolute } from 'pathe';
|
|
2
|
+
import { extname, normalize, relative, dirname, resolve, join, basename, isAbsolute } from 'pathe';
|
|
3
3
|
import { g as getCoverageProvider, C as CoverageProviderMap } from './coverage.BWeNbfBa.js';
|
|
4
4
|
import a, { resolve as resolve$1 } from 'node:path';
|
|
5
|
-
import { noop, isPrimitive, createDefer, toArray, deepMerge, nanoid, slash, deepClone, notNullish } from '@vitest/utils';
|
|
5
|
+
import { noop, isPrimitive, createDefer, highlight, toArray, deepMerge, nanoid, slash, deepClone, notNullish } from '@vitest/utils';
|
|
6
6
|
import { f as findUp, p as prompt } from './index.BJDntFik.js';
|
|
7
|
+
import * as vite from 'vite';
|
|
7
8
|
import { searchForWorkspaceRoot, version, createServer, mergeConfig } from 'vite';
|
|
8
9
|
import { A as API_PATH, c as configFiles, a as defaultBrowserPort, w as workspacesFiles, d as defaultPort } from './constants.fzPh7AOq.js';
|
|
9
|
-
import { createFileTask, limitConcurrency,
|
|
10
|
+
import { generateFileHash, createFileTask, limitConcurrency, hasFailed, getTasks, getTests } from '@vitest/runner/utils';
|
|
10
11
|
import { SnapshotManager } from '@vitest/snapshot/manager';
|
|
11
12
|
import { ViteNodeRunner } from 'vite-node/client';
|
|
12
13
|
import { ViteNodeServer } from 'vite-node/server';
|
|
13
|
-
import { v as version$1 } from './cac.
|
|
14
|
+
import { v as version$1 } from './cac.DZC9WjGM.js';
|
|
14
15
|
import { c as createBirpc } from './index.68735LiX.js';
|
|
15
|
-
import { s as stringify, p as parse,
|
|
16
|
+
import { s as stringify, p as parse, g as printError, h as generateCodeFrame, R as ReportersMap, b as BenchmarkReportsMap, i as BlobReporter, r as readBlobs, H as HangingProcessReporter } from './index.TKSL1HjN.js';
|
|
16
17
|
import require$$0$2 from 'stream';
|
|
17
18
|
import require$$0 from 'zlib';
|
|
18
19
|
import require$$0$1 from 'buffer';
|
|
@@ -26,11 +27,13 @@ import require$$7 from 'url';
|
|
|
26
27
|
import { g as getDefaultExportFromCjs, c as commonjsGlobal } from './_commonjsHelpers.BFTU3MAI.js';
|
|
27
28
|
import { parseErrorStacktrace } from '@vitest/utils/source-map';
|
|
28
29
|
import { distDir, rootDir } from '../path.js';
|
|
29
|
-
import { i as isPackageExists, e as requireMicromatch, V as VitestCache, f as configDefaults, g as getFilePoolName,
|
|
30
|
+
import { R as RandomSequencer, i as isPackageExists, e as requireMicromatch, h as hash, V as VitestCache, f as configDefaults, g as getFilePoolName, j as isBrowserEnabled, m as mm, a as resolveConfig, k as groupBy, w as wildcardPatternToRegExp, l as createPool, b as resolveApiServerConfig, s as stdout } from './resolveConfig.CSLLD33d.js';
|
|
31
|
+
import { i as isTTY, b as isWindows, c as convertTasksToEvents } from './typechecker.BJMkWMXo.js';
|
|
32
|
+
import { Console } from 'node:console';
|
|
33
|
+
import c from 'tinyrainbow';
|
|
34
|
+
import { a as formatProjectName, w as withLabel, d as divider } from './utils.DJWL04yX.js';
|
|
30
35
|
import { createRequire } from 'node:module';
|
|
31
36
|
import url from 'node:url';
|
|
32
|
-
import c from 'tinyrainbow';
|
|
33
|
-
import { b as isTTY, h as hash, i as isWindows } from './RandomSequencer.C6x84bNN.js';
|
|
34
37
|
import { rm } from 'node:fs/promises';
|
|
35
38
|
import nodeos__default, { tmpdir } from 'node:os';
|
|
36
39
|
import require$$0$4 from 'os';
|
|
@@ -39,7 +42,8 @@ import require$$0$6 from 'fs';
|
|
|
39
42
|
import { normalizeRequestId, cleanUrl } from 'vite-node/utils';
|
|
40
43
|
import { hoistMocksPlugin, automockPlugin } from '@vitest/mocker/node';
|
|
41
44
|
import MagicString from 'magic-string';
|
|
42
|
-
import
|
|
45
|
+
import assert$1 from 'node:assert';
|
|
46
|
+
import { serializeError } from '@vitest/utils/error';
|
|
43
47
|
import readline from 'node:readline';
|
|
44
48
|
import { stripVTControlCharacters } from 'node:util';
|
|
45
49
|
|
|
@@ -4900,9 +4904,8 @@ function setup(ctx, _server) {
|
|
|
4900
4904
|
function setupClient(ws) {
|
|
4901
4905
|
const rpc = createBirpc(
|
|
4902
4906
|
{
|
|
4903
|
-
async onTaskUpdate(packs) {
|
|
4904
|
-
ctx.
|
|
4905
|
-
await ctx.report("onTaskUpdate", packs);
|
|
4907
|
+
async onTaskUpdate(packs, events) {
|
|
4908
|
+
await ctx._testRun.updated(packs, events);
|
|
4906
4909
|
},
|
|
4907
4910
|
getFiles() {
|
|
4908
4911
|
return ctx.state.getFiles();
|
|
@@ -4933,6 +4936,9 @@ function setup(ctx, _server) {
|
|
|
4933
4936
|
getConfig() {
|
|
4934
4937
|
return ctx.getRootProject().serializedConfig;
|
|
4935
4938
|
},
|
|
4939
|
+
getResolvedProjectNames() {
|
|
4940
|
+
return ctx.resolvedProjects.map((p) => p.name);
|
|
4941
|
+
},
|
|
4936
4942
|
async getTransformResult(projectName, id, browser = false) {
|
|
4937
4943
|
const project = ctx.getProjectByName(projectName);
|
|
4938
4944
|
const result = browser ? await project.browser.vite.transformRequest(id) : await project.vitenode.transformRequest(id);
|
|
@@ -5109,7 +5115,7 @@ class LocationFilterFileNotFoundError extends Error {
|
|
|
5109
5115
|
class IncludeTaskLocationDisabledError extends Error {
|
|
5110
5116
|
code = "VITEST_INCLUDE_TASK_LOCATION_DISABLED";
|
|
5111
5117
|
constructor() {
|
|
5112
|
-
super("
|
|
5118
|
+
super("Received line number filters while `includeTaskLocation` option is disabled");
|
|
5113
5119
|
}
|
|
5114
5120
|
}
|
|
5115
5121
|
class RangeLocationFilterProvidedError extends Error {
|
|
@@ -5119,6 +5125,292 @@ class RangeLocationFilterProvidedError extends Error {
|
|
|
5119
5125
|
}
|
|
5120
5126
|
}
|
|
5121
5127
|
|
|
5128
|
+
const HIGHLIGHT_SUPPORTED_EXTS = new Set(
|
|
5129
|
+
["js", "ts"].flatMap((lang) => [
|
|
5130
|
+
`.${lang}`,
|
|
5131
|
+
`.m${lang}`,
|
|
5132
|
+
`.c${lang}`,
|
|
5133
|
+
`.${lang}x`,
|
|
5134
|
+
`.m${lang}x`,
|
|
5135
|
+
`.c${lang}x`
|
|
5136
|
+
])
|
|
5137
|
+
);
|
|
5138
|
+
function highlightCode(id, source, colors) {
|
|
5139
|
+
const ext = extname(id);
|
|
5140
|
+
if (!HIGHLIGHT_SUPPORTED_EXTS.has(ext)) {
|
|
5141
|
+
return source;
|
|
5142
|
+
}
|
|
5143
|
+
const isJsx = ext.endsWith("x");
|
|
5144
|
+
return highlight(source, { jsx: isJsx, colors: c });
|
|
5145
|
+
}
|
|
5146
|
+
|
|
5147
|
+
const PAD = " ";
|
|
5148
|
+
const ESC$1 = "\x1B[";
|
|
5149
|
+
const ERASE_DOWN = `${ESC$1}J`;
|
|
5150
|
+
const ERASE_SCROLLBACK = `${ESC$1}3J`;
|
|
5151
|
+
const CURSOR_TO_START = `${ESC$1}1;1H`;
|
|
5152
|
+
const HIDE_CURSOR = `${ESC$1}?25l`;
|
|
5153
|
+
const SHOW_CURSOR = `${ESC$1}?25h`;
|
|
5154
|
+
const CLEAR_SCREEN = "\x1Bc";
|
|
5155
|
+
class Logger {
|
|
5156
|
+
constructor(ctx, outputStream = process.stdout, errorStream = process.stderr) {
|
|
5157
|
+
this.ctx = ctx;
|
|
5158
|
+
this.outputStream = outputStream;
|
|
5159
|
+
this.errorStream = errorStream;
|
|
5160
|
+
this.console = new Console({ stdout: outputStream, stderr: errorStream });
|
|
5161
|
+
this._highlights.clear();
|
|
5162
|
+
this.addCleanupListeners();
|
|
5163
|
+
this.registerUnhandledRejection();
|
|
5164
|
+
this.outputStream.write(HIDE_CURSOR);
|
|
5165
|
+
}
|
|
5166
|
+
_clearScreenPending;
|
|
5167
|
+
_highlights = /* @__PURE__ */ new Map();
|
|
5168
|
+
cleanupListeners = [];
|
|
5169
|
+
console;
|
|
5170
|
+
log(...args) {
|
|
5171
|
+
this._clearScreen();
|
|
5172
|
+
this.console.log(...args);
|
|
5173
|
+
}
|
|
5174
|
+
error(...args) {
|
|
5175
|
+
this._clearScreen();
|
|
5176
|
+
this.console.error(...args);
|
|
5177
|
+
}
|
|
5178
|
+
warn(...args) {
|
|
5179
|
+
this._clearScreen();
|
|
5180
|
+
this.console.warn(...args);
|
|
5181
|
+
}
|
|
5182
|
+
clearFullScreen(message = "") {
|
|
5183
|
+
if (!this.ctx.config.clearScreen) {
|
|
5184
|
+
this.console.log(message);
|
|
5185
|
+
return;
|
|
5186
|
+
}
|
|
5187
|
+
if (message) {
|
|
5188
|
+
this.console.log(`${CLEAR_SCREEN}${ERASE_SCROLLBACK}${message}`);
|
|
5189
|
+
} else {
|
|
5190
|
+
this.outputStream.write(`${CLEAR_SCREEN}${ERASE_SCROLLBACK}`);
|
|
5191
|
+
}
|
|
5192
|
+
}
|
|
5193
|
+
clearScreen(message, force = false) {
|
|
5194
|
+
if (!this.ctx.config.clearScreen) {
|
|
5195
|
+
this.console.log(message);
|
|
5196
|
+
return;
|
|
5197
|
+
}
|
|
5198
|
+
this._clearScreenPending = message;
|
|
5199
|
+
if (force) {
|
|
5200
|
+
this._clearScreen();
|
|
5201
|
+
}
|
|
5202
|
+
}
|
|
5203
|
+
_clearScreen() {
|
|
5204
|
+
if (this._clearScreenPending == null) {
|
|
5205
|
+
return;
|
|
5206
|
+
}
|
|
5207
|
+
const log = this._clearScreenPending;
|
|
5208
|
+
this._clearScreenPending = void 0;
|
|
5209
|
+
this.console.log(`${CURSOR_TO_START}${ERASE_DOWN}${log}`);
|
|
5210
|
+
}
|
|
5211
|
+
printError(err, options = {}) {
|
|
5212
|
+
printError(err, this.ctx, this, options);
|
|
5213
|
+
}
|
|
5214
|
+
clearHighlightCache(filename) {
|
|
5215
|
+
if (filename) {
|
|
5216
|
+
this._highlights.delete(filename);
|
|
5217
|
+
} else {
|
|
5218
|
+
this._highlights.clear();
|
|
5219
|
+
}
|
|
5220
|
+
}
|
|
5221
|
+
highlight(filename, source) {
|
|
5222
|
+
if (this._highlights.has(filename)) {
|
|
5223
|
+
return this._highlights.get(filename);
|
|
5224
|
+
}
|
|
5225
|
+
const code = highlightCode(filename, source);
|
|
5226
|
+
this._highlights.set(filename, code);
|
|
5227
|
+
return code;
|
|
5228
|
+
}
|
|
5229
|
+
printNoTestFound(filters) {
|
|
5230
|
+
const config = this.ctx.config;
|
|
5231
|
+
if (config.watch && (config.changed || config.related?.length)) {
|
|
5232
|
+
this.log(`No affected ${config.mode} files found
|
|
5233
|
+
`);
|
|
5234
|
+
} else if (config.watch) {
|
|
5235
|
+
this.log(
|
|
5236
|
+
c.red(`No ${config.mode} files found. You can change the file name pattern by pressing "p"
|
|
5237
|
+
`)
|
|
5238
|
+
);
|
|
5239
|
+
} else {
|
|
5240
|
+
if (config.passWithNoTests) {
|
|
5241
|
+
this.log(`No ${config.mode} files found, exiting with code 0
|
|
5242
|
+
`);
|
|
5243
|
+
} else {
|
|
5244
|
+
this.error(
|
|
5245
|
+
c.red(`No ${config.mode} files found, exiting with code 1
|
|
5246
|
+
`)
|
|
5247
|
+
);
|
|
5248
|
+
}
|
|
5249
|
+
}
|
|
5250
|
+
const comma = c.dim(", ");
|
|
5251
|
+
if (filters?.length) {
|
|
5252
|
+
this.console.error(c.dim("filter: ") + c.yellow(filters.join(comma)));
|
|
5253
|
+
}
|
|
5254
|
+
const projectsFilter = toArray(config.project);
|
|
5255
|
+
if (projectsFilter.length) {
|
|
5256
|
+
this.console.error(
|
|
5257
|
+
c.dim("projects: ") + c.yellow(projectsFilter.join(comma))
|
|
5258
|
+
);
|
|
5259
|
+
}
|
|
5260
|
+
this.ctx.projects.forEach((project) => {
|
|
5261
|
+
const config2 = project.config;
|
|
5262
|
+
const printConfig = !project.isRootProject() && project.name;
|
|
5263
|
+
if (printConfig) {
|
|
5264
|
+
this.console.error(`
|
|
5265
|
+
${formatProjectName(project.name)}
|
|
5266
|
+
`);
|
|
5267
|
+
}
|
|
5268
|
+
if (config2.include) {
|
|
5269
|
+
this.console.error(
|
|
5270
|
+
c.dim("include: ") + c.yellow(config2.include.join(comma))
|
|
5271
|
+
);
|
|
5272
|
+
}
|
|
5273
|
+
if (config2.exclude) {
|
|
5274
|
+
this.console.error(
|
|
5275
|
+
c.dim("exclude: ") + c.yellow(config2.exclude.join(comma))
|
|
5276
|
+
);
|
|
5277
|
+
}
|
|
5278
|
+
if (config2.typecheck.enabled) {
|
|
5279
|
+
this.console.error(
|
|
5280
|
+
c.dim("typecheck include: ") + c.yellow(config2.typecheck.include.join(comma))
|
|
5281
|
+
);
|
|
5282
|
+
this.console.error(
|
|
5283
|
+
c.dim("typecheck exclude: ") + c.yellow(config2.typecheck.exclude.join(comma))
|
|
5284
|
+
);
|
|
5285
|
+
}
|
|
5286
|
+
});
|
|
5287
|
+
this.console.error();
|
|
5288
|
+
}
|
|
5289
|
+
printBanner() {
|
|
5290
|
+
this.log();
|
|
5291
|
+
const color = this.ctx.config.watch ? "blue" : "cyan";
|
|
5292
|
+
const mode = this.ctx.config.watch ? "DEV" : "RUN";
|
|
5293
|
+
this.log(withLabel(color, mode, `v${this.ctx.version} `) + c.gray(this.ctx.config.root));
|
|
5294
|
+
if (this.ctx.config.sequence.sequencer === RandomSequencer) {
|
|
5295
|
+
this.log(PAD + c.gray(`Running tests with seed "${this.ctx.config.sequence.seed}"`));
|
|
5296
|
+
}
|
|
5297
|
+
if (this.ctx.config.ui) {
|
|
5298
|
+
const host = this.ctx.config.api?.host || "localhost";
|
|
5299
|
+
const port = this.ctx.server.config.server.port;
|
|
5300
|
+
const base = this.ctx.config.uiBase;
|
|
5301
|
+
this.log(PAD + c.dim(c.green(`UI started at http://${host}:${c.bold(port)}${base}`)));
|
|
5302
|
+
} else if (this.ctx.config.api?.port) {
|
|
5303
|
+
const resolvedUrls = this.ctx.server.resolvedUrls;
|
|
5304
|
+
const fallbackUrl = `http://${this.ctx.config.api.host || "localhost"}:${this.ctx.config.api.port}`;
|
|
5305
|
+
const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0] ?? fallbackUrl;
|
|
5306
|
+
this.log(PAD + c.dim(c.green(`API started at ${new URL("/", origin)}`)));
|
|
5307
|
+
}
|
|
5308
|
+
if (this.ctx.coverageProvider) {
|
|
5309
|
+
this.log(PAD + c.dim("Coverage enabled with ") + c.yellow(this.ctx.coverageProvider.name));
|
|
5310
|
+
}
|
|
5311
|
+
if (this.ctx.config.standalone) {
|
|
5312
|
+
this.log(c.yellow(`
|
|
5313
|
+
Vitest is running in standalone mode. Edit a test file to rerun tests.`));
|
|
5314
|
+
} else {
|
|
5315
|
+
this.log();
|
|
5316
|
+
}
|
|
5317
|
+
}
|
|
5318
|
+
printBrowserBanner(project) {
|
|
5319
|
+
if (!project.browser) {
|
|
5320
|
+
return;
|
|
5321
|
+
}
|
|
5322
|
+
const resolvedUrls = project.browser.vite.resolvedUrls;
|
|
5323
|
+
const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
|
|
5324
|
+
if (!origin) {
|
|
5325
|
+
return;
|
|
5326
|
+
}
|
|
5327
|
+
const output = project.isRootProject() ? "" : formatProjectName(project.name);
|
|
5328
|
+
const provider = project.browser.provider.name;
|
|
5329
|
+
const providerString = provider === "preview" ? "" : ` by ${c.reset(c.bold(provider))}`;
|
|
5330
|
+
this.log(
|
|
5331
|
+
c.dim(
|
|
5332
|
+
`${output}Browser runner started${providerString} ${c.dim("at")} ${c.blue(new URL("/", origin))}
|
|
5333
|
+
`
|
|
5334
|
+
)
|
|
5335
|
+
);
|
|
5336
|
+
}
|
|
5337
|
+
printUnhandledErrors(errors) {
|
|
5338
|
+
const errorMessage = c.red(
|
|
5339
|
+
c.bold(
|
|
5340
|
+
`
|
|
5341
|
+
Vitest caught ${errors.length} unhandled error${errors.length > 1 ? "s" : ""} during the test run.
|
|
5342
|
+
This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.`
|
|
5343
|
+
)
|
|
5344
|
+
);
|
|
5345
|
+
this.error(c.red(divider(c.bold(c.inverse(" Unhandled Errors ")))));
|
|
5346
|
+
this.error(errorMessage);
|
|
5347
|
+
errors.forEach((err) => {
|
|
5348
|
+
this.printError(err, {
|
|
5349
|
+
fullStack: true,
|
|
5350
|
+
type: err.type || "Unhandled Error"
|
|
5351
|
+
});
|
|
5352
|
+
});
|
|
5353
|
+
this.error(c.red(divider()));
|
|
5354
|
+
}
|
|
5355
|
+
printSourceTypeErrors(errors) {
|
|
5356
|
+
const errorMessage = c.red(
|
|
5357
|
+
c.bold(
|
|
5358
|
+
`
|
|
5359
|
+
Vitest found ${errors.length} error${errors.length > 1 ? "s" : ""} not related to your test files.`
|
|
5360
|
+
)
|
|
5361
|
+
);
|
|
5362
|
+
this.log(c.red(divider(c.bold(c.inverse(" Source Errors ")))));
|
|
5363
|
+
this.log(errorMessage);
|
|
5364
|
+
errors.forEach((err) => {
|
|
5365
|
+
this.printError(err, { fullStack: true });
|
|
5366
|
+
});
|
|
5367
|
+
this.log(c.red(divider()));
|
|
5368
|
+
}
|
|
5369
|
+
getColumns() {
|
|
5370
|
+
return "columns" in this.outputStream ? this.outputStream.columns : 80;
|
|
5371
|
+
}
|
|
5372
|
+
onTerminalCleanup(listener) {
|
|
5373
|
+
this.cleanupListeners.push(listener);
|
|
5374
|
+
}
|
|
5375
|
+
addCleanupListeners() {
|
|
5376
|
+
const cleanup = () => {
|
|
5377
|
+
this.cleanupListeners.forEach((fn) => fn());
|
|
5378
|
+
this.outputStream.write(SHOW_CURSOR);
|
|
5379
|
+
};
|
|
5380
|
+
const onExit = (signal, exitCode) => {
|
|
5381
|
+
cleanup();
|
|
5382
|
+
if (process.exitCode === void 0) {
|
|
5383
|
+
process.exitCode = exitCode !== void 0 ? 128 + exitCode : Number(signal);
|
|
5384
|
+
}
|
|
5385
|
+
process.exit();
|
|
5386
|
+
};
|
|
5387
|
+
process.once("SIGINT", onExit);
|
|
5388
|
+
process.once("SIGTERM", onExit);
|
|
5389
|
+
process.once("exit", onExit);
|
|
5390
|
+
this.ctx.onClose(() => {
|
|
5391
|
+
process.off("SIGINT", onExit);
|
|
5392
|
+
process.off("SIGTERM", onExit);
|
|
5393
|
+
process.off("exit", onExit);
|
|
5394
|
+
cleanup();
|
|
5395
|
+
});
|
|
5396
|
+
}
|
|
5397
|
+
registerUnhandledRejection() {
|
|
5398
|
+
const onUnhandledRejection = (err) => {
|
|
5399
|
+
process.exitCode = 1;
|
|
5400
|
+
this.printError(err, {
|
|
5401
|
+
fullStack: true,
|
|
5402
|
+
type: "Unhandled Rejection"
|
|
5403
|
+
});
|
|
5404
|
+
this.error("\n\n");
|
|
5405
|
+
process.exit();
|
|
5406
|
+
};
|
|
5407
|
+
process.on("unhandledRejection", onUnhandledRejection);
|
|
5408
|
+
this.ctx.onClose(() => {
|
|
5409
|
+
process.off("unhandledRejection", onUnhandledRejection);
|
|
5410
|
+
});
|
|
5411
|
+
}
|
|
5412
|
+
}
|
|
5413
|
+
|
|
5122
5414
|
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
5123
5415
|
class VitestPackageInstaller {
|
|
5124
5416
|
isPackageExists(name, options) {
|
|
@@ -5159,7 +5451,7 @@ class VitestPackageInstaller {
|
|
|
5159
5451
|
});
|
|
5160
5452
|
if (install) {
|
|
5161
5453
|
const packageName = version ? `${dependency}@${version}` : dependency;
|
|
5162
|
-
await (await import('./index.
|
|
5454
|
+
await (await import('./index.D9C26wCk.js')).installPackage(packageName, { dev: true });
|
|
5163
5455
|
process.stderr.write(
|
|
5164
5456
|
c.yellow(
|
|
5165
5457
|
`
|
|
@@ -8316,7 +8608,7 @@ function requireOut () {
|
|
|
8316
8608
|
}
|
|
8317
8609
|
win32.convertPathToPattern = convertPathToPattern;
|
|
8318
8610
|
})(FastGlob.win32 || (FastGlob.win32 = {}));
|
|
8319
|
-
})(FastGlob
|
|
8611
|
+
})(FastGlob);
|
|
8320
8612
|
function getWorks(source, _Provider, options) {
|
|
8321
8613
|
const patterns = [].concat(source);
|
|
8322
8614
|
const settings = new settings_1.default(options);
|
|
@@ -8669,6 +8961,10 @@ function silenceImportViteIgnoreWarning(logger) {
|
|
|
8669
8961
|
};
|
|
8670
8962
|
}
|
|
8671
8963
|
|
|
8964
|
+
function getDefaultServerConditions() {
|
|
8965
|
+
return vite.defaultServerConditions ?? ["node"];
|
|
8966
|
+
}
|
|
8967
|
+
|
|
8672
8968
|
const cssLangs = "\\.(?:css|less|sass|scss|styl|stylus|pcss|postcss)(?:$|\\?)";
|
|
8673
8969
|
const cssLangRE = new RegExp(cssLangs);
|
|
8674
8970
|
const cssModuleRE = new RegExp(`\\.module${cssLangs}`);
|
|
@@ -9482,6 +9778,7 @@ function WorkspaceVitestPlugin(project, options) {
|
|
|
9482
9778
|
name = options.workspacePath.toString();
|
|
9483
9779
|
}
|
|
9484
9780
|
}
|
|
9781
|
+
const conditions = getDefaultServerConditions();
|
|
9485
9782
|
const config = {
|
|
9486
9783
|
root,
|
|
9487
9784
|
resolve: {
|
|
@@ -9489,7 +9786,7 @@ function WorkspaceVitestPlugin(project, options) {
|
|
|
9489
9786
|
// setting this option can bypass that and fallback to cjs version
|
|
9490
9787
|
mainFields: [],
|
|
9491
9788
|
alias: testConfig.alias,
|
|
9492
|
-
conditions
|
|
9789
|
+
conditions
|
|
9493
9790
|
},
|
|
9494
9791
|
esbuild: viteConfig.esbuild === false ? false : {
|
|
9495
9792
|
// Lowest target Vitest supports is Node18
|
|
@@ -9522,7 +9819,7 @@ function WorkspaceVitestPlugin(project, options) {
|
|
|
9522
9819
|
// by default Vite resolves `module` field, which not always a native ESM module
|
|
9523
9820
|
// setting this option can bypass that and fallback to cjs version
|
|
9524
9821
|
mainFields: [],
|
|
9525
|
-
conditions
|
|
9822
|
+
conditions
|
|
9526
9823
|
}
|
|
9527
9824
|
}
|
|
9528
9825
|
},
|
|
@@ -9588,6 +9885,10 @@ class TestSpecification {
|
|
|
9588
9885
|
* @deprecated use `pool` instead
|
|
9589
9886
|
*/
|
|
9590
9887
|
2;
|
|
9888
|
+
/**
|
|
9889
|
+
* The task ID associated with the test module.
|
|
9890
|
+
*/
|
|
9891
|
+
taskId;
|
|
9591
9892
|
/**
|
|
9592
9893
|
* The test project that the module belongs to.
|
|
9593
9894
|
*/
|
|
@@ -9609,11 +9910,27 @@ class TestSpecification {
|
|
|
9609
9910
|
this[0] = project;
|
|
9610
9911
|
this[1] = moduleId;
|
|
9611
9912
|
this[2] = { pool };
|
|
9913
|
+
const name = project.config.name;
|
|
9914
|
+
const hashName = pool !== "typescript" ? name : name ? `${name}:__typecheck__` : "__typecheck__";
|
|
9915
|
+
this.taskId = generateFileHash(
|
|
9916
|
+
relative(project.config.root, moduleId),
|
|
9917
|
+
hashName
|
|
9918
|
+
);
|
|
9612
9919
|
this.project = project;
|
|
9613
9920
|
this.moduleId = moduleId;
|
|
9614
9921
|
this.pool = pool;
|
|
9615
9922
|
this.testLines = testLines;
|
|
9616
9923
|
}
|
|
9924
|
+
/**
|
|
9925
|
+
* Test module associated with the specification.
|
|
9926
|
+
*/
|
|
9927
|
+
get testModule() {
|
|
9928
|
+
const task = this.project.vitest.state.idMap.get(this.taskId);
|
|
9929
|
+
if (!task) {
|
|
9930
|
+
return void 0;
|
|
9931
|
+
}
|
|
9932
|
+
return this.project.vitest.state.getReportedEntity(task);
|
|
9933
|
+
}
|
|
9617
9934
|
toJSON() {
|
|
9618
9935
|
return [
|
|
9619
9936
|
{
|
|
@@ -9681,13 +9998,14 @@ class TestProject {
|
|
|
9681
9998
|
typechecker;
|
|
9682
9999
|
/** @internal */
|
|
9683
10000
|
_config;
|
|
10001
|
+
/** @internal */
|
|
10002
|
+
_vite;
|
|
9684
10003
|
runner;
|
|
9685
10004
|
closingPromise;
|
|
9686
10005
|
testFilesList = null;
|
|
9687
10006
|
typecheckFilesList = null;
|
|
9688
10007
|
_globalSetups;
|
|
9689
10008
|
_provided = {};
|
|
9690
|
-
_vite;
|
|
9691
10009
|
// "provide" is a property, not a method to keep the context when destructed in the global setup,
|
|
9692
10010
|
// making it a method would be a breaking change, and can be done in Vitest 3 at minimum
|
|
9693
10011
|
/**
|
|
@@ -9770,7 +10088,7 @@ class TestProject {
|
|
|
9770
10088
|
* Serialized project configuration. This is the config that tests receive.
|
|
9771
10089
|
*/
|
|
9772
10090
|
get serializedConfig() {
|
|
9773
|
-
return this.
|
|
10091
|
+
return this._serializeOverriddenConfig();
|
|
9774
10092
|
}
|
|
9775
10093
|
/** @deprecated use `vite` instead */
|
|
9776
10094
|
get server() {
|
|
@@ -9914,19 +10232,19 @@ class TestProject {
|
|
|
9914
10232
|
* Returns if the file is a test file. Requires `.globTestFiles()` to be called first.
|
|
9915
10233
|
* @internal
|
|
9916
10234
|
*/
|
|
9917
|
-
|
|
10235
|
+
_isCachedTestFile(testPath) {
|
|
9918
10236
|
return !!this.testFilesList && this.testFilesList.includes(testPath);
|
|
9919
10237
|
}
|
|
9920
10238
|
/**
|
|
9921
10239
|
* Returns if the file is a typecheck test file. Requires `.globTestFiles()` to be called first.
|
|
9922
10240
|
* @internal
|
|
9923
10241
|
*/
|
|
9924
|
-
|
|
10242
|
+
_isCachedTypecheckFile(testPath) {
|
|
9925
10243
|
return !!this.typecheckFilesList && this.typecheckFilesList.includes(testPath);
|
|
9926
10244
|
}
|
|
9927
10245
|
/** @deprecated use `serializedConfig` instead */
|
|
9928
10246
|
getSerializableConfig() {
|
|
9929
|
-
return this.
|
|
10247
|
+
return this._serializeOverriddenConfig();
|
|
9930
10248
|
}
|
|
9931
10249
|
/** @internal */
|
|
9932
10250
|
async globFiles(include, exclude, cwd) {
|
|
@@ -9942,7 +10260,7 @@ class TestProject {
|
|
|
9942
10260
|
* Test if a file matches the test globs. This does the actual glob matching if the test is not cached, unlike `isCachedTestFile`.
|
|
9943
10261
|
*/
|
|
9944
10262
|
matchesTestGlob(moduleId, source) {
|
|
9945
|
-
if (this.
|
|
10263
|
+
if (this._isCachedTestFile(moduleId)) {
|
|
9946
10264
|
return true;
|
|
9947
10265
|
}
|
|
9948
10266
|
const relativeId = relative(this.config.dir || this.config.root, moduleId);
|
|
@@ -9987,9 +10305,7 @@ class TestProject {
|
|
|
9987
10305
|
}
|
|
9988
10306
|
return testFiles;
|
|
9989
10307
|
}
|
|
9990
|
-
/** @internal */
|
|
9991
10308
|
_parentBrowser;
|
|
9992
|
-
/** @internal */
|
|
9993
10309
|
_parent;
|
|
9994
10310
|
/** @internal */
|
|
9995
10311
|
_initParentBrowser = deduped(async () => {
|
|
@@ -10027,6 +10343,7 @@ class TestProject {
|
|
|
10027
10343
|
await this._parent?._initParentBrowser();
|
|
10028
10344
|
if (!this.browser && this._parent?._parentBrowser) {
|
|
10029
10345
|
this.browser = this._parent._parentBrowser.spawn(this);
|
|
10346
|
+
await this.vitest.report("onBrowserInit", this);
|
|
10030
10347
|
}
|
|
10031
10348
|
});
|
|
10032
10349
|
/**
|
|
@@ -10097,7 +10414,7 @@ class TestProject {
|
|
|
10097
10414
|
}
|
|
10098
10415
|
});
|
|
10099
10416
|
}
|
|
10100
|
-
|
|
10417
|
+
_serializeOverriddenConfig() {
|
|
10101
10418
|
const config = serializeConfig(
|
|
10102
10419
|
this.config,
|
|
10103
10420
|
this.vitest.config,
|
|
@@ -10182,7 +10499,7 @@ function deduped(cb) {
|
|
|
10182
10499
|
}
|
|
10183
10500
|
async function initializeProject(workspacePath, ctx, options) {
|
|
10184
10501
|
const project = new TestProject(workspacePath, ctx, options);
|
|
10185
|
-
const {
|
|
10502
|
+
const { configFile, ...restOptions } = options;
|
|
10186
10503
|
const config = {
|
|
10187
10504
|
...restOptions,
|
|
10188
10505
|
configFile,
|
|
@@ -10310,10 +10627,10 @@ class VitestSpecifications {
|
|
|
10310
10627
|
}
|
|
10311
10628
|
const specs = [];
|
|
10312
10629
|
for (const project of this.vitest.projects) {
|
|
10313
|
-
if (project.
|
|
10630
|
+
if (project._isCachedTestFile(moduleId)) {
|
|
10314
10631
|
specs.push(project.createSpecification(moduleId));
|
|
10315
10632
|
}
|
|
10316
|
-
if (project.
|
|
10633
|
+
if (project._isCachedTypecheckFile(moduleId)) {
|
|
10317
10634
|
specs.push(project.createSpecification(moduleId, [], "typescript"));
|
|
10318
10635
|
}
|
|
10319
10636
|
}
|
|
@@ -10449,6 +10766,411 @@ class VitestSpecifications {
|
|
|
10449
10766
|
}
|
|
10450
10767
|
}
|
|
10451
10768
|
|
|
10769
|
+
class ReportedTaskImplementation {
|
|
10770
|
+
/**
|
|
10771
|
+
* Task instance.
|
|
10772
|
+
* @internal
|
|
10773
|
+
*/
|
|
10774
|
+
task;
|
|
10775
|
+
/**
|
|
10776
|
+
* The project associated with the test or suite.
|
|
10777
|
+
*/
|
|
10778
|
+
project;
|
|
10779
|
+
/**
|
|
10780
|
+
* Unique identifier.
|
|
10781
|
+
* This ID is deterministic and will be the same for the same test across multiple runs.
|
|
10782
|
+
* The ID is based on the project name, module url and test order.
|
|
10783
|
+
*/
|
|
10784
|
+
id;
|
|
10785
|
+
/**
|
|
10786
|
+
* Location in the module where the test or suite is defined.
|
|
10787
|
+
*/
|
|
10788
|
+
location;
|
|
10789
|
+
/** @internal */
|
|
10790
|
+
constructor(task, project) {
|
|
10791
|
+
this.task = task;
|
|
10792
|
+
this.project = project;
|
|
10793
|
+
this.id = task.id;
|
|
10794
|
+
this.location = task.location;
|
|
10795
|
+
}
|
|
10796
|
+
/**
|
|
10797
|
+
* Checks if the test did not fail the suite.
|
|
10798
|
+
* If the test is not finished yet or was skipped, it will return `true`.
|
|
10799
|
+
*/
|
|
10800
|
+
ok() {
|
|
10801
|
+
const result = this.task.result;
|
|
10802
|
+
return !result || result.state !== "fail";
|
|
10803
|
+
}
|
|
10804
|
+
/**
|
|
10805
|
+
* Creates a new reported task instance and stores it in the project's state for future use.
|
|
10806
|
+
* @internal
|
|
10807
|
+
*/
|
|
10808
|
+
static register(task, project) {
|
|
10809
|
+
const state = new this(task, project);
|
|
10810
|
+
storeTask(project, task, state);
|
|
10811
|
+
return state;
|
|
10812
|
+
}
|
|
10813
|
+
}
|
|
10814
|
+
class TestCase extends ReportedTaskImplementation {
|
|
10815
|
+
#fullName;
|
|
10816
|
+
type = "test";
|
|
10817
|
+
/**
|
|
10818
|
+
* Direct reference to the test module where the test or suite is defined.
|
|
10819
|
+
*/
|
|
10820
|
+
module;
|
|
10821
|
+
/**
|
|
10822
|
+
* Name of the test.
|
|
10823
|
+
*/
|
|
10824
|
+
name;
|
|
10825
|
+
/**
|
|
10826
|
+
* Options that the test was initiated with.
|
|
10827
|
+
*/
|
|
10828
|
+
options;
|
|
10829
|
+
/**
|
|
10830
|
+
* Parent suite. If the test was called directly inside the module, the parent will be the module itself.
|
|
10831
|
+
*/
|
|
10832
|
+
parent;
|
|
10833
|
+
/** @internal */
|
|
10834
|
+
constructor(task, project) {
|
|
10835
|
+
super(task, project);
|
|
10836
|
+
this.name = task.name;
|
|
10837
|
+
this.module = getReportedTask(project, task.file);
|
|
10838
|
+
const suite = this.task.suite;
|
|
10839
|
+
if (suite) {
|
|
10840
|
+
this.parent = getReportedTask(project, suite);
|
|
10841
|
+
} else {
|
|
10842
|
+
this.parent = this.module;
|
|
10843
|
+
}
|
|
10844
|
+
this.options = buildOptions(task);
|
|
10845
|
+
}
|
|
10846
|
+
/**
|
|
10847
|
+
* Full name of the test including all parent suites separated with `>`.
|
|
10848
|
+
*/
|
|
10849
|
+
get fullName() {
|
|
10850
|
+
if (this.#fullName === void 0) {
|
|
10851
|
+
if (this.parent.type !== "module") {
|
|
10852
|
+
this.#fullName = `${this.parent.fullName} > ${this.name}`;
|
|
10853
|
+
} else {
|
|
10854
|
+
this.#fullName = this.name;
|
|
10855
|
+
}
|
|
10856
|
+
}
|
|
10857
|
+
return this.#fullName;
|
|
10858
|
+
}
|
|
10859
|
+
/**
|
|
10860
|
+
* Test results.
|
|
10861
|
+
* - **pending**: Test was collected, but didn't finish running yet.
|
|
10862
|
+
* - **passed**: Test passed successfully
|
|
10863
|
+
* - **failed**: Test failed to execute
|
|
10864
|
+
* - **skipped**: Test was skipped during collection or dynamically with `ctx.skip()`.
|
|
10865
|
+
*/
|
|
10866
|
+
result() {
|
|
10867
|
+
const result = this.task.result;
|
|
10868
|
+
const mode = result?.state || this.task.mode;
|
|
10869
|
+
if (!result && (mode === "skip" || mode === "todo")) {
|
|
10870
|
+
return {
|
|
10871
|
+
state: "skipped",
|
|
10872
|
+
note: void 0,
|
|
10873
|
+
errors: void 0
|
|
10874
|
+
};
|
|
10875
|
+
}
|
|
10876
|
+
if (!result || result.state === "run" || result.state === "queued") {
|
|
10877
|
+
return {
|
|
10878
|
+
state: "pending",
|
|
10879
|
+
errors: void 0
|
|
10880
|
+
};
|
|
10881
|
+
}
|
|
10882
|
+
const state = result.state === "fail" ? "failed" : result.state === "pass" ? "passed" : "skipped";
|
|
10883
|
+
if (state === "skipped") {
|
|
10884
|
+
return {
|
|
10885
|
+
state,
|
|
10886
|
+
note: result.note,
|
|
10887
|
+
errors: void 0
|
|
10888
|
+
};
|
|
10889
|
+
}
|
|
10890
|
+
if (state === "passed") {
|
|
10891
|
+
return {
|
|
10892
|
+
state,
|
|
10893
|
+
errors: result.errors
|
|
10894
|
+
};
|
|
10895
|
+
}
|
|
10896
|
+
return {
|
|
10897
|
+
state,
|
|
10898
|
+
errors: result.errors || []
|
|
10899
|
+
};
|
|
10900
|
+
}
|
|
10901
|
+
/**
|
|
10902
|
+
* Custom metadata that was attached to the test during its execution.
|
|
10903
|
+
*/
|
|
10904
|
+
meta() {
|
|
10905
|
+
return this.task.meta;
|
|
10906
|
+
}
|
|
10907
|
+
/**
|
|
10908
|
+
* Useful information about the test like duration, memory usage, etc.
|
|
10909
|
+
* Diagnostic is only available after the test has finished.
|
|
10910
|
+
*/
|
|
10911
|
+
diagnostic() {
|
|
10912
|
+
const result = this.task.result;
|
|
10913
|
+
if (!result || !result.startTime) {
|
|
10914
|
+
return void 0;
|
|
10915
|
+
}
|
|
10916
|
+
const duration = result.duration || 0;
|
|
10917
|
+
const slow = duration > this.project.globalConfig.slowTestThreshold;
|
|
10918
|
+
return {
|
|
10919
|
+
slow,
|
|
10920
|
+
heap: result.heap,
|
|
10921
|
+
duration,
|
|
10922
|
+
startTime: result.startTime,
|
|
10923
|
+
retryCount: result.retryCount ?? 0,
|
|
10924
|
+
repeatCount: result.repeatCount ?? 0,
|
|
10925
|
+
flaky: !!result.retryCount && result.state === "pass" && result.retryCount > 0
|
|
10926
|
+
};
|
|
10927
|
+
}
|
|
10928
|
+
}
|
|
10929
|
+
class TestCollection {
|
|
10930
|
+
#task;
|
|
10931
|
+
#project;
|
|
10932
|
+
constructor(task, project) {
|
|
10933
|
+
this.#task = task;
|
|
10934
|
+
this.#project = project;
|
|
10935
|
+
}
|
|
10936
|
+
/**
|
|
10937
|
+
* Returns the test or suite at a specific index.
|
|
10938
|
+
*/
|
|
10939
|
+
at(index) {
|
|
10940
|
+
if (index < 0) {
|
|
10941
|
+
index = this.size + index;
|
|
10942
|
+
}
|
|
10943
|
+
return getReportedTask(this.#project, this.#task.tasks[index]);
|
|
10944
|
+
}
|
|
10945
|
+
/**
|
|
10946
|
+
* The number of tests and suites in the collection.
|
|
10947
|
+
*/
|
|
10948
|
+
get size() {
|
|
10949
|
+
return this.#task.tasks.length;
|
|
10950
|
+
}
|
|
10951
|
+
/**
|
|
10952
|
+
* Returns the collection in array form for easier manipulation.
|
|
10953
|
+
*/
|
|
10954
|
+
array() {
|
|
10955
|
+
return Array.from(this);
|
|
10956
|
+
}
|
|
10957
|
+
/**
|
|
10958
|
+
* Filters all tests that are part of this collection and its children.
|
|
10959
|
+
*/
|
|
10960
|
+
*allTests(state) {
|
|
10961
|
+
for (const child of this) {
|
|
10962
|
+
if (child.type === "suite") {
|
|
10963
|
+
yield* child.children.allTests(state);
|
|
10964
|
+
} else if (state) {
|
|
10965
|
+
const testState = child.result().state;
|
|
10966
|
+
if (state === testState) {
|
|
10967
|
+
yield child;
|
|
10968
|
+
}
|
|
10969
|
+
} else {
|
|
10970
|
+
yield child;
|
|
10971
|
+
}
|
|
10972
|
+
}
|
|
10973
|
+
}
|
|
10974
|
+
/**
|
|
10975
|
+
* Filters only the tests that are part of this collection.
|
|
10976
|
+
*/
|
|
10977
|
+
*tests(state) {
|
|
10978
|
+
for (const child of this) {
|
|
10979
|
+
if (child.type !== "test") {
|
|
10980
|
+
continue;
|
|
10981
|
+
}
|
|
10982
|
+
if (state) {
|
|
10983
|
+
const testState = child.result().state;
|
|
10984
|
+
if (state === testState) {
|
|
10985
|
+
yield child;
|
|
10986
|
+
}
|
|
10987
|
+
} else {
|
|
10988
|
+
yield child;
|
|
10989
|
+
}
|
|
10990
|
+
}
|
|
10991
|
+
}
|
|
10992
|
+
/**
|
|
10993
|
+
* Filters only the suites that are part of this collection.
|
|
10994
|
+
*/
|
|
10995
|
+
*suites() {
|
|
10996
|
+
for (const child of this) {
|
|
10997
|
+
if (child.type === "suite") {
|
|
10998
|
+
yield child;
|
|
10999
|
+
}
|
|
11000
|
+
}
|
|
11001
|
+
}
|
|
11002
|
+
/**
|
|
11003
|
+
* Filters all suites that are part of this collection and its children.
|
|
11004
|
+
*/
|
|
11005
|
+
*allSuites() {
|
|
11006
|
+
for (const child of this) {
|
|
11007
|
+
if (child.type === "suite") {
|
|
11008
|
+
yield child;
|
|
11009
|
+
yield* child.children.allSuites();
|
|
11010
|
+
}
|
|
11011
|
+
}
|
|
11012
|
+
}
|
|
11013
|
+
*[Symbol.iterator]() {
|
|
11014
|
+
for (const task of this.#task.tasks) {
|
|
11015
|
+
yield getReportedTask(this.#project, task);
|
|
11016
|
+
}
|
|
11017
|
+
}
|
|
11018
|
+
}
|
|
11019
|
+
class SuiteImplementation extends ReportedTaskImplementation {
|
|
11020
|
+
/**
|
|
11021
|
+
* Collection of suites and tests that are part of this suite.
|
|
11022
|
+
*/
|
|
11023
|
+
children;
|
|
11024
|
+
/** @internal */
|
|
11025
|
+
constructor(task, project) {
|
|
11026
|
+
super(task, project);
|
|
11027
|
+
this.children = new TestCollection(task, project);
|
|
11028
|
+
}
|
|
11029
|
+
/**
|
|
11030
|
+
* Errors that happened outside of the test run during collection, like syntax errors.
|
|
11031
|
+
*/
|
|
11032
|
+
errors() {
|
|
11033
|
+
return this.task.result?.errors || [];
|
|
11034
|
+
}
|
|
11035
|
+
}
|
|
11036
|
+
class TestSuite extends SuiteImplementation {
|
|
11037
|
+
#fullName;
|
|
11038
|
+
type = "suite";
|
|
11039
|
+
/**
|
|
11040
|
+
* Name of the test or the suite.
|
|
11041
|
+
*/
|
|
11042
|
+
name;
|
|
11043
|
+
/**
|
|
11044
|
+
* Direct reference to the test module where the test or suite is defined.
|
|
11045
|
+
*/
|
|
11046
|
+
module;
|
|
11047
|
+
/**
|
|
11048
|
+
* Parent suite. If suite was called directly inside the module, the parent will be the module itself.
|
|
11049
|
+
*/
|
|
11050
|
+
parent;
|
|
11051
|
+
/**
|
|
11052
|
+
* Options that suite was initiated with.
|
|
11053
|
+
*/
|
|
11054
|
+
options;
|
|
11055
|
+
/** @internal */
|
|
11056
|
+
constructor(task, project) {
|
|
11057
|
+
super(task, project);
|
|
11058
|
+
this.name = task.name;
|
|
11059
|
+
this.module = getReportedTask(project, task.file);
|
|
11060
|
+
const suite = this.task.suite;
|
|
11061
|
+
if (suite) {
|
|
11062
|
+
this.parent = getReportedTask(project, suite);
|
|
11063
|
+
} else {
|
|
11064
|
+
this.parent = this.module;
|
|
11065
|
+
}
|
|
11066
|
+
this.options = buildOptions(task);
|
|
11067
|
+
}
|
|
11068
|
+
/**
|
|
11069
|
+
* Checks the running state of the suite.
|
|
11070
|
+
*/
|
|
11071
|
+
state() {
|
|
11072
|
+
return getSuiteState(this.task);
|
|
11073
|
+
}
|
|
11074
|
+
/**
|
|
11075
|
+
* Full name of the suite including all parent suites separated with `>`.
|
|
11076
|
+
*/
|
|
11077
|
+
get fullName() {
|
|
11078
|
+
if (this.#fullName === void 0) {
|
|
11079
|
+
if (this.parent.type !== "module") {
|
|
11080
|
+
this.#fullName = `${this.parent.fullName} > ${this.name}`;
|
|
11081
|
+
} else {
|
|
11082
|
+
this.#fullName = this.name;
|
|
11083
|
+
}
|
|
11084
|
+
}
|
|
11085
|
+
return this.#fullName;
|
|
11086
|
+
}
|
|
11087
|
+
}
|
|
11088
|
+
class TestModule extends SuiteImplementation {
|
|
11089
|
+
type = "module";
|
|
11090
|
+
/**
|
|
11091
|
+
* This is usually an absolute UNIX file path.
|
|
11092
|
+
* It can be a virtual ID if the file is not on the disk.
|
|
11093
|
+
* This value corresponds to the ID in the Vite's module graph.
|
|
11094
|
+
*/
|
|
11095
|
+
moduleId;
|
|
11096
|
+
/** @internal */
|
|
11097
|
+
constructor(task, project) {
|
|
11098
|
+
super(task, project);
|
|
11099
|
+
this.moduleId = task.filepath;
|
|
11100
|
+
}
|
|
11101
|
+
/**
|
|
11102
|
+
* Checks the running state of the test file.
|
|
11103
|
+
*/
|
|
11104
|
+
state() {
|
|
11105
|
+
const state = this.task.result?.state;
|
|
11106
|
+
if (state === "queued") {
|
|
11107
|
+
return "queued";
|
|
11108
|
+
}
|
|
11109
|
+
return getSuiteState(this.task);
|
|
11110
|
+
}
|
|
11111
|
+
/**
|
|
11112
|
+
* Useful information about the module like duration, memory usage, etc.
|
|
11113
|
+
* If the module was not executed yet, all diagnostic values will return `0`.
|
|
11114
|
+
*/
|
|
11115
|
+
diagnostic() {
|
|
11116
|
+
const setupDuration = this.task.setupDuration || 0;
|
|
11117
|
+
const collectDuration = this.task.collectDuration || 0;
|
|
11118
|
+
const prepareDuration = this.task.prepareDuration || 0;
|
|
11119
|
+
const environmentSetupDuration = this.task.environmentLoad || 0;
|
|
11120
|
+
const duration = this.task.result?.duration || 0;
|
|
11121
|
+
return {
|
|
11122
|
+
environmentSetupDuration,
|
|
11123
|
+
prepareDuration,
|
|
11124
|
+
collectDuration,
|
|
11125
|
+
setupDuration,
|
|
11126
|
+
duration
|
|
11127
|
+
};
|
|
11128
|
+
}
|
|
11129
|
+
}
|
|
11130
|
+
function buildOptions(task) {
|
|
11131
|
+
return {
|
|
11132
|
+
each: task.each,
|
|
11133
|
+
fails: task.type === "test" && task.fails,
|
|
11134
|
+
concurrent: task.concurrent,
|
|
11135
|
+
shuffle: task.shuffle,
|
|
11136
|
+
retry: task.retry,
|
|
11137
|
+
repeats: task.repeats,
|
|
11138
|
+
// runner types are too broad, but the public API should be more strict
|
|
11139
|
+
// the queued state exists only on Files and this method is called
|
|
11140
|
+
// only for tests and suites
|
|
11141
|
+
mode: task.mode
|
|
11142
|
+
};
|
|
11143
|
+
}
|
|
11144
|
+
function storeTask(project, runnerTask, reportedTask) {
|
|
11145
|
+
project.vitest.state.reportedTasksMap.set(runnerTask, reportedTask);
|
|
11146
|
+
}
|
|
11147
|
+
function getReportedTask(project, runnerTask) {
|
|
11148
|
+
const reportedTask = project.vitest.state.getReportedEntity(runnerTask);
|
|
11149
|
+
if (!reportedTask) {
|
|
11150
|
+
throw new Error(
|
|
11151
|
+
`Task instance was not found for ${runnerTask.type} "${runnerTask.name}"`
|
|
11152
|
+
);
|
|
11153
|
+
}
|
|
11154
|
+
return reportedTask;
|
|
11155
|
+
}
|
|
11156
|
+
function getSuiteState(task) {
|
|
11157
|
+
const mode = task.mode;
|
|
11158
|
+
const state = task.result?.state;
|
|
11159
|
+
if (mode === "skip" || mode === "todo" || state === "skip" || state === "todo") {
|
|
11160
|
+
return "skipped";
|
|
11161
|
+
}
|
|
11162
|
+
if (state == null || state === "run" || state === "only") {
|
|
11163
|
+
return "pending";
|
|
11164
|
+
}
|
|
11165
|
+
if (state === "fail") {
|
|
11166
|
+
return "failed";
|
|
11167
|
+
}
|
|
11168
|
+
if (state === "pass") {
|
|
11169
|
+
return "passed";
|
|
11170
|
+
}
|
|
11171
|
+
throw new Error(`Unknown suite state: ${state}`);
|
|
11172
|
+
}
|
|
11173
|
+
|
|
10452
11174
|
function isAggregateError(err) {
|
|
10453
11175
|
if (typeof AggregateError !== "undefined" && err instanceof AggregateError) {
|
|
10454
11176
|
return true;
|
|
@@ -10630,6 +11352,127 @@ class StateManager {
|
|
|
10630
11352
|
}
|
|
10631
11353
|
}
|
|
10632
11354
|
|
|
11355
|
+
class TestRun {
|
|
11356
|
+
constructor(vitest) {
|
|
11357
|
+
this.vitest = vitest;
|
|
11358
|
+
}
|
|
11359
|
+
async start(specifications) {
|
|
11360
|
+
const filepaths = specifications.map((spec) => spec.moduleId);
|
|
11361
|
+
this.vitest.state.collectPaths(filepaths);
|
|
11362
|
+
await this.vitest.report("onPathsCollected", Array.from(new Set(filepaths)));
|
|
11363
|
+
await this.vitest.report("onSpecsCollected", specifications.map((spec) => spec.toJSON()));
|
|
11364
|
+
await this.vitest.report("onTestRunStart", [...specifications]);
|
|
11365
|
+
}
|
|
11366
|
+
async enqueued(project, file) {
|
|
11367
|
+
this.vitest.state.collectFiles(project, [file]);
|
|
11368
|
+
const testModule = this.vitest.state.getReportedEntity(file);
|
|
11369
|
+
await this.vitest.report("onTestModuleQueued", testModule);
|
|
11370
|
+
}
|
|
11371
|
+
async collected(project, files) {
|
|
11372
|
+
this.vitest.state.collectFiles(project, files);
|
|
11373
|
+
await Promise.all([
|
|
11374
|
+
this.vitest.report("onCollected", files),
|
|
11375
|
+
...files.map((file) => {
|
|
11376
|
+
const testModule = this.vitest.state.getReportedEntity(file);
|
|
11377
|
+
return this.vitest.report("onTestModuleCollected", testModule);
|
|
11378
|
+
})
|
|
11379
|
+
]);
|
|
11380
|
+
}
|
|
11381
|
+
async log(log) {
|
|
11382
|
+
this.vitest.state.updateUserLog(log);
|
|
11383
|
+
await this.vitest.report("onUserConsoleLog", log);
|
|
11384
|
+
}
|
|
11385
|
+
async updated(update, events) {
|
|
11386
|
+
this.vitest.state.updateTasks(update);
|
|
11387
|
+
await this.vitest.report("onTaskUpdate", update);
|
|
11388
|
+
for (const [id, event] of events) {
|
|
11389
|
+
await this.reportEvent(id, event).catch((error) => {
|
|
11390
|
+
this.vitest.state.catchError(serializeError(error), "Unhandled Reporter Error");
|
|
11391
|
+
});
|
|
11392
|
+
}
|
|
11393
|
+
}
|
|
11394
|
+
async end(specifications, errors, coverage) {
|
|
11395
|
+
const modules = specifications.map((spec) => spec.testModule).filter((s) => s != null);
|
|
11396
|
+
const files = modules.map((m) => m.task);
|
|
11397
|
+
const state = this.vitest.isCancelling ? "interrupted" : process.exitCode ? "failed" : "passed";
|
|
11398
|
+
try {
|
|
11399
|
+
await Promise.all([
|
|
11400
|
+
this.vitest.report("onTestRunEnd", modules, [...errors], state),
|
|
11401
|
+
// TODO: in a perfect world, the coverage should be done in parallel to `onFinished`
|
|
11402
|
+
this.vitest.report("onFinished", files, errors, coverage)
|
|
11403
|
+
]);
|
|
11404
|
+
} finally {
|
|
11405
|
+
if (coverage) {
|
|
11406
|
+
await this.vitest.report("onCoverage", coverage);
|
|
11407
|
+
}
|
|
11408
|
+
}
|
|
11409
|
+
}
|
|
11410
|
+
async reportEvent(id, event) {
|
|
11411
|
+
const task = this.vitest.state.idMap.get(id);
|
|
11412
|
+
const entity = task && this.vitest.state.getReportedEntity(task);
|
|
11413
|
+
assert$1(task && entity, `Entity must be found for task ${task?.name || id}`);
|
|
11414
|
+
if (event === "suite-prepare" && entity.type === "suite") {
|
|
11415
|
+
return await this.vitest.report("onTestSuiteReady", entity);
|
|
11416
|
+
}
|
|
11417
|
+
if (event === "suite-prepare" && entity.type === "module") {
|
|
11418
|
+
return await this.vitest.report("onTestModuleStart", entity);
|
|
11419
|
+
}
|
|
11420
|
+
if (event === "suite-finished") {
|
|
11421
|
+
assert$1(entity.type === "suite" || entity.type === "module", "Entity type must be suite or module");
|
|
11422
|
+
if (entity.state() === "skipped") {
|
|
11423
|
+
await this.reportChildren(entity.children);
|
|
11424
|
+
} else {
|
|
11425
|
+
for (const test of entity.children.tests("skipped")) {
|
|
11426
|
+
if (test.task.result?.pending) {
|
|
11427
|
+
continue;
|
|
11428
|
+
}
|
|
11429
|
+
await this.vitest.report("onTestCaseReady", test);
|
|
11430
|
+
await this.vitest.report("onTestCaseResult", test);
|
|
11431
|
+
}
|
|
11432
|
+
}
|
|
11433
|
+
if (entity.type === "module") {
|
|
11434
|
+
await this.vitest.report("onTestModuleEnd", entity);
|
|
11435
|
+
} else {
|
|
11436
|
+
await this.vitest.report("onTestSuiteResult", entity);
|
|
11437
|
+
}
|
|
11438
|
+
return;
|
|
11439
|
+
}
|
|
11440
|
+
if (event === "test-prepare" && entity.type === "test") {
|
|
11441
|
+
return await this.vitest.report("onTestCaseReady", entity);
|
|
11442
|
+
}
|
|
11443
|
+
if (event === "test-finished" && entity.type === "test") {
|
|
11444
|
+
return await this.vitest.report("onTestCaseResult", entity);
|
|
11445
|
+
}
|
|
11446
|
+
if (event.startsWith("before-hook") || event.startsWith("after-hook")) {
|
|
11447
|
+
const isBefore = event.startsWith("before-hook");
|
|
11448
|
+
const hook = entity.type === "test" ? {
|
|
11449
|
+
name: isBefore ? "beforeEach" : "afterEach",
|
|
11450
|
+
entity
|
|
11451
|
+
} : {
|
|
11452
|
+
name: isBefore ? "beforeAll" : "afterAll",
|
|
11453
|
+
entity
|
|
11454
|
+
};
|
|
11455
|
+
if (event.endsWith("-start")) {
|
|
11456
|
+
await this.vitest.report("onHookStart", hook);
|
|
11457
|
+
} else {
|
|
11458
|
+
await this.vitest.report("onHookEnd", hook);
|
|
11459
|
+
}
|
|
11460
|
+
}
|
|
11461
|
+
}
|
|
11462
|
+
async reportChildren(children) {
|
|
11463
|
+
for (const child of children) {
|
|
11464
|
+
if (child.type === "test") {
|
|
11465
|
+
await this.vitest.report("onTestCaseReady", child);
|
|
11466
|
+
await this.vitest.report("onTestCaseResult", child);
|
|
11467
|
+
} else {
|
|
11468
|
+
await this.vitest.report("onTestSuiteReady", child);
|
|
11469
|
+
await this.reportChildren(child.children);
|
|
11470
|
+
await this.vitest.report("onTestSuiteResult", child);
|
|
11471
|
+
}
|
|
11472
|
+
}
|
|
11473
|
+
}
|
|
11474
|
+
}
|
|
11475
|
+
|
|
10633
11476
|
class VitestWatcher {
|
|
10634
11477
|
constructor(vitest) {
|
|
10635
11478
|
this.vitest = vitest;
|
|
@@ -10730,7 +11573,7 @@ class VitestWatcher {
|
|
|
10730
11573
|
return moduleGraph.getModulesByFile(filepath)?.size;
|
|
10731
11574
|
});
|
|
10732
11575
|
if (!projects.length) {
|
|
10733
|
-
if (this.vitest.state.filesMap.has(filepath) || this.vitest.projects.some((project) => project.
|
|
11576
|
+
if (this.vitest.state.filesMap.has(filepath) || this.vitest.projects.some((project) => project._isCachedTestFile(filepath))) {
|
|
10734
11577
|
this.changedTests.add(filepath);
|
|
10735
11578
|
return true;
|
|
10736
11579
|
}
|
|
@@ -10743,7 +11586,7 @@ class VitestWatcher {
|
|
|
10743
11586
|
continue;
|
|
10744
11587
|
}
|
|
10745
11588
|
this.invalidates.add(filepath);
|
|
10746
|
-
if (this.vitest.state.filesMap.has(filepath) || project.
|
|
11589
|
+
if (this.vitest.state.filesMap.has(filepath) || project._isCachedTestFile(filepath)) {
|
|
10747
11590
|
this.changedTests.add(filepath);
|
|
10748
11591
|
files.push(filepath);
|
|
10749
11592
|
continue;
|
|
@@ -10839,13 +11682,12 @@ async function resolveWorkspace(vitest, cliOptions, workspaceConfigPath, workspa
|
|
|
10839
11682
|
const concurrent = limitConcurrency(nodeos__default.availableParallelism?.() || nodeos__default.cpus().length || 5);
|
|
10840
11683
|
projectConfigs.forEach((options, index) => {
|
|
10841
11684
|
const configRoot = workspaceConfigPath ? dirname(workspaceConfigPath) : vitest.config.root;
|
|
10842
|
-
const configFile = typeof options.extends === "string" ? resolve(configRoot, options.extends) : false;
|
|
10843
|
-
const rootOptions = options.extends === true ? vitest._options : {};
|
|
11685
|
+
const configFile = typeof options.extends === "string" ? resolve(configRoot, options.extends) : options.extends === true ? vitest.vite.config.configFile || false : false;
|
|
10844
11686
|
const root = options.root ? resolve(configRoot, options.root) : vitest.config.root;
|
|
10845
11687
|
projectPromises.push(concurrent(() => initializeProject(
|
|
10846
11688
|
index,
|
|
10847
11689
|
vitest,
|
|
10848
|
-
|
|
11690
|
+
{ ...options, root, configFile }
|
|
10849
11691
|
)));
|
|
10850
11692
|
});
|
|
10851
11693
|
for (const path of fileProjects) {
|
|
@@ -11029,8 +11871,8 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, workspaceD
|
|
|
11029
11871
|
if (!isDynamicPattern(stringOption)) {
|
|
11030
11872
|
const file = resolve(vitest.config.root, stringOption);
|
|
11031
11873
|
if (!existsSync(file)) {
|
|
11032
|
-
const
|
|
11033
|
-
const note = workspaceConfigPath ? `Workspace config file "${
|
|
11874
|
+
const relativeWorkSpaceConfigPath = workspaceConfigPath ? relative(vitest.config.root, workspaceConfigPath) : void 0;
|
|
11875
|
+
const note = workspaceConfigPath ? `Workspace config file "${relativeWorkSpaceConfigPath}"` : "Inline workspace";
|
|
11034
11876
|
throw new Error(`${note} references a non-existing file or a directory: ${file}`);
|
|
11035
11877
|
}
|
|
11036
11878
|
const stats = await promises.stat(file);
|
|
@@ -11178,6 +12020,8 @@ class Vitest {
|
|
|
11178
12020
|
vitenode = void 0;
|
|
11179
12021
|
/** @internal */
|
|
11180
12022
|
runner = void 0;
|
|
12023
|
+
/** @internal */
|
|
12024
|
+
_testRun = void 0;
|
|
11181
12025
|
isFirstRun = true;
|
|
11182
12026
|
restartsCount = 0;
|
|
11183
12027
|
specifications;
|
|
@@ -11262,6 +12106,7 @@ class Vitest {
|
|
|
11262
12106
|
this._workspaceConfigPath = void 0;
|
|
11263
12107
|
this.coverageProvider = void 0;
|
|
11264
12108
|
this.runningPromise = void 0;
|
|
12109
|
+
this.coreWorkspaceProject = void 0;
|
|
11265
12110
|
this.specifications.clearCache();
|
|
11266
12111
|
this._onUserTestsRerun = [];
|
|
11267
12112
|
const resolved = resolveConfig(this.mode, options, server.config, this.logger);
|
|
@@ -11270,6 +12115,7 @@ class Vitest {
|
|
|
11270
12115
|
this._state = new StateManager();
|
|
11271
12116
|
this._cache = new VitestCache(this.version);
|
|
11272
12117
|
this._snapshot = new SnapshotManager({ ...resolved.snapshotOptions });
|
|
12118
|
+
this._testRun = new TestRun(this);
|
|
11273
12119
|
if (this.config.watch) {
|
|
11274
12120
|
this.watcher.registerWatcher();
|
|
11275
12121
|
}
|
|
@@ -11455,43 +12301,35 @@ class Vitest {
|
|
|
11455
12301
|
const { files, errors, coverages } = await readBlobs(this.version, directory || this.config.mergeReports, this.projects);
|
|
11456
12302
|
await this.report("onInit", this);
|
|
11457
12303
|
await this.report("onPathsCollected", files.flatMap((f) => f.filepath));
|
|
11458
|
-
const
|
|
12304
|
+
const specifications = [];
|
|
11459
12305
|
for (const file of files) {
|
|
11460
12306
|
const project = this.getProjectByName(file.projectName || "");
|
|
11461
|
-
const
|
|
11462
|
-
|
|
11463
|
-
workspaceSpecs.set(project, specs);
|
|
11464
|
-
}
|
|
11465
|
-
for (const [project, files2] of workspaceSpecs) {
|
|
11466
|
-
const filepaths = files2.map((f) => f.filepath);
|
|
11467
|
-
this.state.clearFiles(project, filepaths);
|
|
11468
|
-
files2.forEach((file) => {
|
|
11469
|
-
file.logs?.forEach((log) => this.state.updateUserLog(log));
|
|
11470
|
-
});
|
|
11471
|
-
this.state.collectFiles(project, files2);
|
|
12307
|
+
const specification = project.createSpecification(file.filepath, void 0, file.pool);
|
|
12308
|
+
specifications.push(specification);
|
|
11472
12309
|
}
|
|
11473
|
-
await this.report("
|
|
12310
|
+
await this.report("onSpecsCollected", specifications.map((spec) => spec.toJSON()));
|
|
12311
|
+
await this._testRun.start(specifications).catch(noop);
|
|
11474
12312
|
for (const file of files) {
|
|
12313
|
+
const project = this.getProjectByName(file.projectName || "");
|
|
12314
|
+
await this._testRun.enqueued(project, file).catch(noop);
|
|
12315
|
+
await this._testRun.collected(project, [file]).catch(noop);
|
|
11475
12316
|
const logs = [];
|
|
11476
|
-
const
|
|
11477
|
-
const tasks = getTasks(file);
|
|
11478
|
-
for (const task of tasks) {
|
|
12317
|
+
const { packs, events } = convertTasksToEvents(file, (task) => {
|
|
11479
12318
|
if (task.logs) {
|
|
11480
12319
|
logs.push(...task.logs);
|
|
11481
12320
|
}
|
|
11482
|
-
|
|
11483
|
-
}
|
|
12321
|
+
});
|
|
11484
12322
|
logs.sort((log1, log2) => log1.time - log2.time);
|
|
11485
12323
|
for (const log of logs) {
|
|
11486
|
-
await this.
|
|
12324
|
+
await this._testRun.log(log).catch(noop);
|
|
11487
12325
|
}
|
|
11488
|
-
await this.
|
|
12326
|
+
await this._testRun.updated(packs, events).catch(noop);
|
|
11489
12327
|
}
|
|
11490
12328
|
if (hasFailed(files)) {
|
|
11491
12329
|
process.exitCode = 1;
|
|
11492
12330
|
}
|
|
11493
12331
|
this._checkUnhandledErrors(errors);
|
|
11494
|
-
await this.
|
|
12332
|
+
await this._testRun.end(specifications, errors).catch(noop);
|
|
11495
12333
|
await this.initCoverageProvider();
|
|
11496
12334
|
await this.coverageProvider?.mergeReports?.(coverages);
|
|
11497
12335
|
return {
|
|
@@ -11537,12 +12375,16 @@ class Vitest {
|
|
|
11537
12375
|
this.filenamePattern = filters && filters?.length > 0 ? filters : void 0;
|
|
11538
12376
|
const files = await this.specifications.getRelevantTestSpecifications(filters);
|
|
11539
12377
|
if (!files.length) {
|
|
12378
|
+
const throwAnError = !this.config.watch || !(this.config.changed || this.config.related?.length);
|
|
12379
|
+
await this._testRun.start([]);
|
|
11540
12380
|
const coverage = await this.coverageProvider?.generateCoverage?.({ allTestsRun: true });
|
|
11541
|
-
|
|
11542
|
-
this.logger.printNoTestFound(filters);
|
|
11543
|
-
if (!this.config.watch || !(this.config.changed || this.config.related?.length)) {
|
|
12381
|
+
if (throwAnError) {
|
|
11544
12382
|
const exitCode = this.config.passWithNoTests ? 0 : 1;
|
|
11545
12383
|
process.exitCode = exitCode;
|
|
12384
|
+
}
|
|
12385
|
+
await this._testRun.end([], [], coverage);
|
|
12386
|
+
await this.reportCoverage(coverage, true);
|
|
12387
|
+
if (throwAnError) {
|
|
11546
12388
|
throw new FilesNotFoundError(this.mode);
|
|
11547
12389
|
}
|
|
11548
12390
|
}
|
|
@@ -11587,7 +12429,7 @@ class Vitest {
|
|
|
11587
12429
|
return this.getModuleSpecifications(file);
|
|
11588
12430
|
}
|
|
11589
12431
|
/**
|
|
11590
|
-
* Get test specifications
|
|
12432
|
+
* Get test specifications associated with the given module. If module is not a test file, an empty array is returned.
|
|
11591
12433
|
*
|
|
11592
12434
|
* **Note:** this method relies on a cache generated by `globTestSpecifications`. If the file was not processed yet, use `project.matchesGlobPattern` instead.
|
|
11593
12435
|
* @param moduleId The module ID to get test specifications for.
|
|
@@ -11596,7 +12438,7 @@ class Vitest {
|
|
|
11596
12438
|
return this.specifications.getModuleSpecifications(moduleId);
|
|
11597
12439
|
}
|
|
11598
12440
|
/**
|
|
11599
|
-
* Vitest automatically caches test specifications for each file. This method clears the cache for the given file or the whole cache
|
|
12441
|
+
* Vitest automatically caches test specifications for each file. This method clears the cache for the given file or the whole cache altogether.
|
|
11600
12442
|
*/
|
|
11601
12443
|
clearSpecificationsCache(moduleId) {
|
|
11602
12444
|
this.specifications.clearCache(moduleId);
|
|
@@ -11627,10 +12469,7 @@ class Vitest {
|
|
|
11627
12469
|
return result;
|
|
11628
12470
|
}
|
|
11629
12471
|
async runFiles(specs, allTestsRun) {
|
|
11630
|
-
|
|
11631
|
-
this.state.collectPaths(filepaths);
|
|
11632
|
-
await this.report("onPathsCollected", filepaths);
|
|
11633
|
-
await this.report("onSpecsCollected", specs.map((spec) => spec.toJSON()));
|
|
12472
|
+
await this._testRun.start(specs);
|
|
11634
12473
|
await this.runningPromise;
|
|
11635
12474
|
this._onCancelListeners = [];
|
|
11636
12475
|
this.isCancelling = false;
|
|
@@ -11663,11 +12502,10 @@ class Vitest {
|
|
|
11663
12502
|
unhandledErrors: this.state.getUnhandledErrors()
|
|
11664
12503
|
};
|
|
11665
12504
|
} finally {
|
|
11666
|
-
const files = Array.from(new Set(specs.map((spec) => spec.moduleId)));
|
|
11667
|
-
const errors = this.state.getUnhandledErrors();
|
|
11668
12505
|
const coverage = await this.coverageProvider?.generateCoverage({ allTestsRun });
|
|
12506
|
+
const errors = this.state.getUnhandledErrors();
|
|
11669
12507
|
this._checkUnhandledErrors(errors);
|
|
11670
|
-
await this.
|
|
12508
|
+
await this._testRun.end(specs, errors, coverage);
|
|
11671
12509
|
await this.reportCoverage(coverage, allTestsRun);
|
|
11672
12510
|
}
|
|
11673
12511
|
})().finally(() => {
|
|
@@ -11723,6 +12561,7 @@ class Vitest {
|
|
|
11723
12561
|
async cancelCurrentRun(reason) {
|
|
11724
12562
|
this.isCancelling = true;
|
|
11725
12563
|
await Promise.all(this._onCancelListeners.splice(0).map((listener) => listener(reason)));
|
|
12564
|
+
await this.runningPromise;
|
|
11726
12565
|
}
|
|
11727
12566
|
/** @internal */
|
|
11728
12567
|
async _initBrowserServers() {
|
|
@@ -11836,12 +12675,14 @@ class Vitest {
|
|
|
11836
12675
|
// environment is resolved inside a worker thread
|
|
11837
12676
|
snapshotEnvironment: null
|
|
11838
12677
|
};
|
|
12678
|
+
this.snapshot.options.updateSnapshot = "all";
|
|
11839
12679
|
}
|
|
11840
12680
|
/**
|
|
11841
12681
|
* Disable the mode that allows updating snapshots when running tests.
|
|
11842
12682
|
*/
|
|
11843
12683
|
resetSnapshotUpdate() {
|
|
11844
12684
|
delete this.configOverride.snapshotOptions;
|
|
12685
|
+
this.snapshot.options.updateSnapshot = this.config.snapshotOptions.updateSnapshot;
|
|
11845
12686
|
}
|
|
11846
12687
|
/**
|
|
11847
12688
|
* Set the global test name pattern to a regexp.
|
|
@@ -11975,7 +12816,6 @@ class Vitest {
|
|
|
11975
12816
|
this.logger.error("error during close", r.reason);
|
|
11976
12817
|
}
|
|
11977
12818
|
});
|
|
11978
|
-
this.logger.logUpdate.done();
|
|
11979
12819
|
});
|
|
11980
12820
|
})();
|
|
11981
12821
|
}
|
|
@@ -11991,7 +12831,7 @@ class Vitest {
|
|
|
11991
12831
|
console.warn(`close timed out after ${this.config.teardownTimeout}ms`);
|
|
11992
12832
|
this.state.getProcessTimeoutCauses().forEach((cause) => console.warn(cause));
|
|
11993
12833
|
if (!this.pool) {
|
|
11994
|
-
const runningServers = [this.
|
|
12834
|
+
const runningServers = [this._vite, ...this.resolvedProjects.map((p) => p._vite)].filter(Boolean).length;
|
|
11995
12835
|
if (runningServers === 1) {
|
|
11996
12836
|
console.warn("Tests closed successfully but something prevents Vite server from exiting");
|
|
11997
12837
|
} else if (runningServers > 1) {
|
|
@@ -11999,7 +12839,9 @@ class Vitest {
|
|
|
11999
12839
|
} else {
|
|
12000
12840
|
console.warn("Tests closed successfully but something prevents the main process from exiting");
|
|
12001
12841
|
}
|
|
12002
|
-
|
|
12842
|
+
if (!this.reporters.some((r) => r instanceof HangingProcessReporter)) {
|
|
12843
|
+
console.warn('You can try to identify the cause by enabling "hanging-process" reporter. See https://vitest.dev/config/#reporters');
|
|
12844
|
+
}
|
|
12003
12845
|
}
|
|
12004
12846
|
process.exit();
|
|
12005
12847
|
});
|
|
@@ -12119,6 +12961,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
|
|
|
12119
12961
|
if (testConfig.ui && testConfig.open) {
|
|
12120
12962
|
open = testConfig.uiBase ?? "/__vitest__/";
|
|
12121
12963
|
}
|
|
12964
|
+
const conditions = getDefaultServerConditions();
|
|
12122
12965
|
const config = {
|
|
12123
12966
|
root: viteConfig.test?.root || options.root,
|
|
12124
12967
|
esbuild: viteConfig.esbuild === false ? false : {
|
|
@@ -12133,7 +12976,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
|
|
|
12133
12976
|
// setting this option can bypass that and fallback to cjs version
|
|
12134
12977
|
mainFields: [],
|
|
12135
12978
|
alias: testConfig.alias,
|
|
12136
|
-
conditions
|
|
12979
|
+
conditions
|
|
12137
12980
|
},
|
|
12138
12981
|
server: {
|
|
12139
12982
|
...testConfig.api,
|
|
@@ -12162,7 +13005,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
|
|
|
12162
13005
|
// by default Vite resolves `module` field, which not always a native ESM module
|
|
12163
13006
|
// setting this option can bypass that and fallback to cjs version
|
|
12164
13007
|
mainFields: [],
|
|
12165
|
-
conditions
|
|
13008
|
+
conditions
|
|
12166
13009
|
}
|
|
12167
13010
|
}
|
|
12168
13011
|
},
|
|
@@ -12187,11 +13030,6 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
|
|
|
12187
13030
|
}
|
|
12188
13031
|
);
|
|
12189
13032
|
config.customLogger = silenceImportViteIgnoreWarning(config.customLogger);
|
|
12190
|
-
if (userConfig.coverage?.enabled && !userConfig.coverage.exclude && userConfig.include && config.test) {
|
|
12191
|
-
config.test.coverage = {
|
|
12192
|
-
exclude: [...coverageConfigDefaults.exclude, ...userConfig.include]
|
|
12193
|
-
};
|
|
12194
|
-
}
|
|
12195
13033
|
if (viteConfig.ssr?.noExternal !== true) {
|
|
12196
13034
|
const inline = testConfig.server?.deps?.inline;
|
|
12197
13035
|
if (inline === true) {
|
|
@@ -12504,13 +13342,11 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout2) {
|
|
|
12504
13342
|
async function _keypressHandler(str, key) {
|
|
12505
13343
|
if (str === "" || str === "\x1B" || key && key.ctrl && key.name === "c") {
|
|
12506
13344
|
if (!ctx.isCancelling) {
|
|
12507
|
-
ctx.logger.logUpdate.clear();
|
|
12508
13345
|
ctx.logger.log(
|
|
12509
13346
|
c.red("Cancelling test run. Press CTRL+c again to exit forcefully.\n")
|
|
12510
13347
|
);
|
|
12511
13348
|
process.exitCode = 130;
|
|
12512
13349
|
await ctx.cancelCurrentRun("keyboard-input");
|
|
12513
|
-
await ctx.runningPromise;
|
|
12514
13350
|
}
|
|
12515
13351
|
return ctx.exit(true);
|
|
12516
13352
|
}
|
|
@@ -12809,7 +13645,7 @@ function formatCollectedAsJSON(files) {
|
|
|
12809
13645
|
const results = [];
|
|
12810
13646
|
files.forEach((file) => {
|
|
12811
13647
|
for (const test of file.children.allTests()) {
|
|
12812
|
-
if (test.
|
|
13648
|
+
if (test.result().state === "skipped") {
|
|
12813
13649
|
continue;
|
|
12814
13650
|
}
|
|
12815
13651
|
const result = {
|
|
@@ -12831,7 +13667,7 @@ function formatCollectedAsString(testModules) {
|
|
|
12831
13667
|
const results = [];
|
|
12832
13668
|
testModules.forEach((testModule) => {
|
|
12833
13669
|
for (const test of testModule.children.allTests()) {
|
|
12834
|
-
if (test.
|
|
13670
|
+
if (test.result().state === "skipped") {
|
|
12835
13671
|
continue;
|
|
12836
13672
|
}
|
|
12837
13673
|
const fullName = `${test.module.task.name} > ${test.fullName}`;
|
|
@@ -12870,4 +13706,4 @@ var cliApi = /*#__PURE__*/Object.freeze({
|
|
|
12870
13706
|
startVitest: startVitest
|
|
12871
13707
|
});
|
|
12872
13708
|
|
|
12873
|
-
export { FilesNotFoundError as F, GitNotFoundError as G, Vitest as V, VitestPlugin as a, VitestPackageInstaller as b, createVitest as c, registerConsoleShortcuts as d, createViteLogger as e, cliApi as f, resolveFsAllow as r, startVitest as s };
|
|
13709
|
+
export { FilesNotFoundError as F, GitNotFoundError as G, TestModule as T, Vitest as V, VitestPlugin as a, VitestPackageInstaller as b, createVitest as c, registerConsoleShortcuts as d, createViteLogger as e, cliApi as f, resolveFsAllow as r, startVitest as s };
|