vitest 5.0.0-beta.2 → 5.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +1 -1
- package/dist/chunks/{base.Opc_YHkk.js → base.Bay6B1Dz.js} +4 -4
- package/dist/chunks/{browser.d.BUhkKcDl.d.ts → browser.d.DM1g8UNp.d.ts} +2 -2
- package/dist/chunks/{cac.8N4bOkkB.js → cac.DoK9yX-i.js} +8 -6
- package/dist/chunks/{cli-api.B0RFke2g.js → cli-api.BCY9ylNq.js} +140 -68
- package/dist/chunks/{config.d.D91DHYaD.d.ts → config.d.C0UMwus7.d.ts} +86 -63
- package/dist/chunks/{defaults.szbHWQun.js → defaults.DVfzlTkU.js} +1 -1
- package/dist/chunks/{env.D4Lgay0q.js → env.BKKtU2WC.js} +2 -1
- package/dist/chunks/{global.d.DhbKSQoV.d.ts → global.d.DZbA5YnY.d.ts} +4 -2
- package/dist/chunks/{globals.EHmmu0nC.js → globals.8_qjZdeE.js} +1 -1
- package/dist/chunks/{index.CViWo__T.js → index.PuMGMNHF.js} +2 -2
- package/dist/chunks/{index.D_7-4CaB.js → index.ukHtlBbI.js} +1305 -555
- package/dist/chunks/{init-forks.DMge3WTt.js → init-forks.OoZmDo1g.js} +1 -1
- package/dist/chunks/{init-threads.eIoyCTon.js → init-threads.eSHAowcx.js} +1 -1
- package/dist/chunks/{init.BVd7SaCA.js → init.YjNsCb-_.js} +1 -1
- package/dist/chunks/{plugin.d.cIKZEZ16.d.ts → plugin.d.C00LxKL6.d.ts} +35 -9
- package/dist/chunks/{setup-common.Hpq30zVk.js → setup-common.eQsbxe88.js} +1 -1
- package/dist/chunks/{vm.2okbRRME.js → vm.BE_VOfSs.js} +1 -1
- package/dist/chunks/{worker.d.Bu1kXGw4.d.ts → worker.d.Dv3hDCFf.d.ts} +1 -1
- package/dist/cli.js +2 -2
- package/dist/config.d.ts +6 -7
- package/dist/config.js +2 -2
- package/dist/index.d.ts +8 -8
- package/dist/index.js +1 -1
- package/dist/module-evaluator.js +1 -1
- package/dist/node.d.ts +7 -8
- package/dist/node.js +5 -5
- package/dist/worker.d.ts +2 -2
- package/dist/worker.js +5 -5
- package/dist/workers/forks.js +6 -6
- package/dist/workers/runVmTests.js +3 -3
- package/dist/workers/threads.js +6 -6
- package/dist/workers/vmForks.js +3 -3
- package/dist/workers/vmThreads.js +3 -3
- package/package.json +19 -20
package/dist/browser.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as SerializedCoverageConfig, a as SerializedConfig } from './chunks/config.d.
|
|
1
|
+
import { c as SerializedCoverageConfig, a as SerializedConfig } from './chunks/config.d.C0UMwus7.js';
|
|
2
2
|
import { R as RuntimeCoverageModuleLoader } from './chunks/coverage.d.g2xbl2sP.js';
|
|
3
3
|
import { SerializedDiffOptions } from '@vitest/utils/diff';
|
|
4
4
|
export { collectTests, startTests } from '@vitest/runner';
|
package/dist/browser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { l as loadDiffConfig, a as loadSnapshotSerializers, s as setupCommonEnv, b as startCoverageInsideWorker, c as stopCoverageInsideWorker, t as takeCoverageInsideWorker } from './chunks/setup-common.
|
|
1
|
+
export { l as loadDiffConfig, a as loadSnapshotSerializers, s as setupCommonEnv, b as startCoverageInsideWorker, c as stopCoverageInsideWorker, t as takeCoverageInsideWorker } from './chunks/setup-common.eQsbxe88.js';
|
|
2
2
|
export { collectTests, startTests } from '@vitest/runner';
|
|
3
3
|
import * as spyModule from '@vitest/spy';
|
|
4
4
|
export { spyModule as SpyModule };
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { runInThisContext } from 'node:vm';
|
|
2
2
|
import * as spyModule from '@vitest/spy';
|
|
3
|
-
import { r as resolveTestRunner, a as resolveSnapshotEnvironment, d as detectAsyncLeaks, s as setupChaiConfig } from './index.
|
|
4
|
-
import { l as loadEnvironment, e as emitModuleRunner, a as listenForErrors } from './init.
|
|
3
|
+
import { r as resolveTestRunner, a as resolveSnapshotEnvironment, d as detectAsyncLeaks, s as setupChaiConfig } from './index.PuMGMNHF.js';
|
|
4
|
+
import { l as loadEnvironment, e as emitModuleRunner, a as listenForErrors } from './init.YjNsCb-_.js';
|
|
5
5
|
import { N as NativeModuleRunner } from './nativeModuleRunner.BOeMnHl4.js';
|
|
6
6
|
import { Traces } from '../traces.js';
|
|
7
7
|
import { V as VitestEvaluatedModules } from './rpc.DFRWVnRh.js';
|
|
8
8
|
import { s as startVitestModuleRunner, c as createNodeImportMeta } from './index.CbgUM9E5.js';
|
|
9
9
|
import { performance as performance$1 } from 'node:perf_hooks';
|
|
10
10
|
import { startTests, collectTests } from '@vitest/runner';
|
|
11
|
-
import { s as setupCommonEnv, b as startCoverageInsideWorker, c as stopCoverageInsideWorker } from './setup-common.
|
|
12
|
-
import { i as index, g as globalExpect, v as vi } from './index.
|
|
11
|
+
import { s as setupCommonEnv, b as startCoverageInsideWorker, c as stopCoverageInsideWorker } from './setup-common.eQsbxe88.js';
|
|
12
|
+
import { i as index, g as globalExpect, v as vi } from './index.ukHtlBbI.js';
|
|
13
13
|
import { c as closeInspector } from './inspector.CvyFGlXm.js';
|
|
14
14
|
import { createRequire } from 'node:module';
|
|
15
15
|
import timers from 'node:timers';
|
|
@@ -6,7 +6,7 @@ import { Test, FileSpecification } from '@vitest/runner';
|
|
|
6
6
|
import { ChainableFunction } from '@vitest/runner/utils';
|
|
7
7
|
import { TaskResult, Bench, Options } from 'tinybench';
|
|
8
8
|
import { O as OTELCarrier } from './rpc.d.7JZuxZ8u.js';
|
|
9
|
-
import { T as TestExecutionMethod } from './worker.d.
|
|
9
|
+
import { T as TestExecutionMethod } from './worker.d.Dv3hDCFf.js';
|
|
10
10
|
|
|
11
11
|
type SerializedTestSpecification = [project: {
|
|
12
12
|
name: string | undefined;
|
|
@@ -200,7 +200,7 @@ interface CustomMatcher {
|
|
|
200
200
|
* expect('foo').toBeOneOf([expect.any(String)])
|
|
201
201
|
* expect({ a: 1 }).toEqual({ a: expect.toBeOneOf(['1', '2', '3']) })
|
|
202
202
|
*/
|
|
203
|
-
toBeOneOf: <T>(sample:
|
|
203
|
+
toBeOneOf: <T>(sample: ReadonlyArray<T> | ReadonlySet<T>) => any;
|
|
204
204
|
}
|
|
205
205
|
interface AsymmetricMatchersContaining extends CustomMatcher {
|
|
206
206
|
/**
|
|
@@ -2,7 +2,7 @@ import { toArray } from '@vitest/utils/helpers';
|
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
3
|
import { normalize } from 'pathe';
|
|
4
4
|
import c$2, { disableDefaultColors } from 'tinyrainbow';
|
|
5
|
-
import './env.
|
|
5
|
+
import { i as isForceColor } from './env.BKKtU2WC.js';
|
|
6
6
|
import { a as defaultPort, d as defaultBrowserPort } from './constants.-juJ8b_4.js';
|
|
7
7
|
import assert from 'node:assert';
|
|
8
8
|
import { isAgent } from 'std-env';
|
|
@@ -621,7 +621,7 @@ class CAC extends EventEmitter {
|
|
|
621
621
|
|
|
622
622
|
const cac = (name = "") => new CAC(name);
|
|
623
623
|
|
|
624
|
-
var version = "5.0.0-beta.
|
|
624
|
+
var version = "5.0.0-beta.3";
|
|
625
625
|
|
|
626
626
|
const apiConfig = (port) => ({
|
|
627
627
|
port: {
|
|
@@ -907,7 +907,8 @@ const cliOptionsConfig = {
|
|
|
907
907
|
argument: "<options>",
|
|
908
908
|
subcommands: {
|
|
909
909
|
testIdAttribute: null,
|
|
910
|
-
exact: { description: "Should locators match the text exactly by default (default: `false`)" }
|
|
910
|
+
exact: { description: "Should locators match the text exactly by default (default: `false`)" },
|
|
911
|
+
errorFormat: null
|
|
911
912
|
},
|
|
912
913
|
transform(val) {
|
|
913
914
|
if (typeof val !== "object" || val == null) return {};
|
|
@@ -1109,6 +1110,7 @@ const cliOptionsConfig = {
|
|
|
1109
1110
|
},
|
|
1110
1111
|
allowJs: { description: "Allow JavaScript files to be typechecked. By default takes the value from tsconfig.json" },
|
|
1111
1112
|
ignoreSourceErrors: { description: "Ignore type errors from source files" },
|
|
1113
|
+
build: { description: "Use TypeScript build mode" },
|
|
1112
1114
|
tsconfig: {
|
|
1113
1115
|
description: "Path to a custom tsconfig file",
|
|
1114
1116
|
argument: "<path>",
|
|
@@ -2225,7 +2227,7 @@ function addCliOptions(cli, options) {
|
|
|
2225
2227
|
for (const [optionName, option] of Object.entries(options)) if (option) addCommand(cli, optionName, option);
|
|
2226
2228
|
}
|
|
2227
2229
|
function createCLI(options = {}) {
|
|
2228
|
-
if (isAgent) disableDefaultColors();
|
|
2230
|
+
if (isAgent && !isForceColor()) disableDefaultColors();
|
|
2229
2231
|
const cli = cac("vitest");
|
|
2230
2232
|
cli.version(version);
|
|
2231
2233
|
addCliOptions(cli, cliOptionsConfig);
|
|
@@ -2348,7 +2350,7 @@ function normalizeCliOptions(cliFilters, argv) {
|
|
|
2348
2350
|
}
|
|
2349
2351
|
async function start(mode, cliFilters, options) {
|
|
2350
2352
|
try {
|
|
2351
|
-
const { startVitest } = await import('./cli-api.
|
|
2353
|
+
const { startVitest } = await import('./cli-api.BCY9ylNq.js').then(function (n) { return n.K; });
|
|
2352
2354
|
const ctx = await startVitest(mode, cliFilters.map(normalize), normalizeCliOptions(cliFilters, options));
|
|
2353
2355
|
if (!ctx.shouldKeepServer()) await ctx.exit();
|
|
2354
2356
|
} catch (e) {
|
|
@@ -2370,7 +2372,7 @@ async function init(project) {
|
|
|
2370
2372
|
}
|
|
2371
2373
|
async function collect(mode, cliFilters, options) {
|
|
2372
2374
|
try {
|
|
2373
|
-
const { prepareVitest, processCollected, outputFileList } = await import('./cli-api.
|
|
2375
|
+
const { prepareVitest, processCollected, outputFileList } = await import('./cli-api.BCY9ylNq.js').then(function (n) { return n.K; });
|
|
2374
2376
|
const ctx = await prepareVitest(mode, {
|
|
2375
2377
|
...normalizeCliOptions(cliFilters, options),
|
|
2376
2378
|
watch: false,
|
|
@@ -14,7 +14,7 @@ import * as nodeos from 'node:os';
|
|
|
14
14
|
import nodeos__default, { tmpdir, hostname } from 'node:os';
|
|
15
15
|
import { getTests, createFileTask as createFileTask$1, createTaskName, validateTags, calculateSuiteHash, someTasksAreOnly, interpretTaskModes, hasFailed, generateFileHash, limitConcurrency, getTestName, getSuites, getTasks, getFullName, createTagsFilter, isTestCase } from '@vitest/runner/utils';
|
|
16
16
|
import { serializeValue } from '@vitest/utils/serialize';
|
|
17
|
-
import { v as version$1 } from './cac.
|
|
17
|
+
import { v as version$1 } from './cac.DoK9yX-i.js';
|
|
18
18
|
import { distDir, rootDir } from '../path.js';
|
|
19
19
|
import { Traces } from '../traces.js';
|
|
20
20
|
import { createDebug } from 'obug';
|
|
@@ -23,8 +23,8 @@ import { rm, readFile, writeFile, rename, stat, unlink, mkdir, readdir, copyFile
|
|
|
23
23
|
import c from 'tinyrainbow';
|
|
24
24
|
import url, { pathToFileURL, fileURLToPath } from 'node:url';
|
|
25
25
|
import { isDynamicPattern, glob } from 'tinyglobby';
|
|
26
|
-
import { c as configDefaults, e as benchmarkConfigDefaults, a as coverageConfigDefaults } from './defaults.
|
|
27
|
-
import {
|
|
26
|
+
import { c as configDefaults, e as benchmarkConfigDefaults, a as coverageConfigDefaults } from './defaults.DVfzlTkU.js';
|
|
27
|
+
import { a as isTTY, b as isWindows, i as isForceColor } from './env.BKKtU2WC.js';
|
|
28
28
|
import { w as withLabel, t as truncateString, e as errorBanner, F as F_POINTER, d as divider, f as formatProjectName, a as formatTimeString, b as taskFail, s as separator, c as F_CHECK, g as F_DOWN_RIGHT, h as getStateSymbol, r as renderSnapshotSummary, p as padSummaryTitle, i as getStateString$1, j as formatTime, k as countTestErrors, l as F_TREE_NODE_END, m as F_TREE_NODE_MIDDLE, n as noun, o as F_RIGHT } from './utils.DKODp04v.js';
|
|
29
29
|
import { isAgent, isCI, provider } from 'std-env';
|
|
30
30
|
import module$1, { createRequire, builtinModules, isBuiltin as isBuiltin$1 } from 'node:module';
|
|
@@ -1544,7 +1544,7 @@ class BrowserSessions {
|
|
|
1544
1544
|
destroySession(sessionId) {
|
|
1545
1545
|
this.sessions.delete(sessionId);
|
|
1546
1546
|
}
|
|
1547
|
-
createSession(sessionId, project, pool) {
|
|
1547
|
+
createSession(sessionId, project, pool, options) {
|
|
1548
1548
|
// this promise only waits for the WS connection with the orchestrator to be established
|
|
1549
1549
|
const defer = createDefer();
|
|
1550
1550
|
const timeout = setTimeout(() => {
|
|
@@ -1552,6 +1552,7 @@ class BrowserSessions {
|
|
|
1552
1552
|
}, project.vitest.config.browser.connectTimeout ?? 6e4).unref();
|
|
1553
1553
|
this.sessions.set(sessionId, {
|
|
1554
1554
|
project,
|
|
1555
|
+
otelCarrier: options?.otelCarrier,
|
|
1555
1556
|
connected: () => {
|
|
1556
1557
|
defer.resolve();
|
|
1557
1558
|
clearTimeout(timeout);
|
|
@@ -2457,7 +2458,7 @@ function resolveConfig$1(vitest, options, viteConfig) {
|
|
|
2457
2458
|
resolved.coverage.exclude = [
|
|
2458
2459
|
...resolved.coverage.exclude,
|
|
2459
2460
|
...resolved.setupFiles.map((file) => `${resolved.coverage.allowExternal ? "**/" : ""}${relative(resolved.root, file)}`),
|
|
2460
|
-
...resolved.include,
|
|
2461
|
+
...resolved.include.filter((pattern) => !pattern.startsWith("!")),
|
|
2461
2462
|
resolved.config && slash(resolved.config),
|
|
2462
2463
|
...configFiles,
|
|
2463
2464
|
"**/virtual:*",
|
|
@@ -2617,6 +2618,7 @@ function resolveConfig$1(vitest, options, viteConfig) {
|
|
|
2617
2618
|
resolved.browser.locators ??= {};
|
|
2618
2619
|
resolved.browser.locators.testIdAttribute ??= "data-testid";
|
|
2619
2620
|
resolved.browser.locators.exact ??= false;
|
|
2621
|
+
resolved.browser.locators.errorFormat ??= "all";
|
|
2620
2622
|
if (typeof resolved.browser.provider === "string") {
|
|
2621
2623
|
const source = `@vitest/browser-${resolved.browser.provider}`;
|
|
2622
2624
|
throw new TypeError(`The \`browser.provider\` configuration was changed to accept a factory instead of a string. Add an import of "${resolved.browser.provider}" from "${source}" instead. See: https://vitest.dev/config/browser/provider`);
|
|
@@ -4504,18 +4506,16 @@ Possible solutions:
|
|
|
4504
4506
|
}
|
|
4505
4507
|
async spawn() {
|
|
4506
4508
|
const { root, watch, typecheck } = this.project.config;
|
|
4507
|
-
const args = [
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
"false",
|
|
4511
|
-
"--incremental",
|
|
4512
|
-
"--tsBuildInfoFile",
|
|
4513
|
-
join(process.versions.pnp ? join(nodeos__default.tmpdir(), this.project.hash) : distDir, "tsconfig.tmp.tsbuildinfo")
|
|
4514
|
-
];
|
|
4509
|
+
const args = ["--pretty", "false"];
|
|
4510
|
+
if (typecheck.build) args.unshift("--build");
|
|
4511
|
+
else args.push("--noEmit", "--incremental", "--tsBuildInfoFile", join(process.versions.pnp ? join(nodeos__default.tmpdir(), this.project.hash) : distDir, "tsconfig.tmp.tsbuildinfo"));
|
|
4515
4512
|
// use builtin watcher because it's faster
|
|
4516
4513
|
if (watch) args.push("--watch");
|
|
4517
4514
|
if (typecheck.allowJs) args.push("--allowJs", "--checkJs");
|
|
4518
|
-
if (typecheck.tsconfig)
|
|
4515
|
+
if (typecheck.tsconfig) {
|
|
4516
|
+
if (!typecheck.build) args.push("-p");
|
|
4517
|
+
args.push(resolve$1(root, typecheck.tsconfig));
|
|
4518
|
+
}
|
|
4519
4519
|
this._output = "";
|
|
4520
4520
|
this._startTime = performance$1.now();
|
|
4521
4521
|
const child = x(typecheck.checker, args, {
|
|
@@ -12343,7 +12343,8 @@ function serializeConfig(project) {
|
|
|
12343
12343
|
screenshotFailures: browser.screenshotFailures,
|
|
12344
12344
|
locators: {
|
|
12345
12345
|
testIdAttribute: browser.locators.testIdAttribute,
|
|
12346
|
-
exact: browser.locators.exact
|
|
12346
|
+
exact: browser.locators.exact,
|
|
12347
|
+
errorFormat: browser.locators.errorFormat
|
|
12347
12348
|
},
|
|
12348
12349
|
providerOptions: provider?.name === "playwright" ? { actionTimeout: provider?.options?.actionTimeout } : {},
|
|
12349
12350
|
trackUnhandledErrors: browser.trackUnhandledErrors ?? true,
|
|
@@ -12367,7 +12368,7 @@ function serializeConfig(project) {
|
|
|
12367
12368
|
strictTags: config.strictTags ?? true,
|
|
12368
12369
|
mergeReportsLabel: config.mergeReportsLabel,
|
|
12369
12370
|
slowTestThreshold: config.slowTestThreshold ?? globalConfig.slowTestThreshold ?? configDefaults.slowTestThreshold,
|
|
12370
|
-
isAgent
|
|
12371
|
+
disableColors: isAgent && !isForceColor()
|
|
12371
12372
|
};
|
|
12372
12373
|
}
|
|
12373
12374
|
|
|
@@ -13660,9 +13661,9 @@ class TestSpecification {
|
|
|
13660
13661
|
* This class represents a test suite for a test module within a single project.
|
|
13661
13662
|
* @internal
|
|
13662
13663
|
*/
|
|
13663
|
-
constructor(project, moduleId, pool, testLinesOrOptions,
|
|
13664
|
+
constructor(project, moduleId, pool, testLinesOrOptions, taskIdOverride) {
|
|
13664
13665
|
const projectName = project.config.name;
|
|
13665
|
-
this.taskId = generateFileHash(relative(project.config.root, moduleId), projectName,
|
|
13666
|
+
this.taskId = taskIdOverride ?? generateFileHash(relative(project.config.root, moduleId), projectName, {
|
|
13666
13667
|
typecheck: pool === "typescript",
|
|
13667
13668
|
__vitest_label__: project.config.mergeReportsLabel
|
|
13668
13669
|
});
|
|
@@ -13779,8 +13780,8 @@ class TestProject {
|
|
|
13779
13780
|
* Creates a new test specification. Specifications describe how to run tests.
|
|
13780
13781
|
* @param moduleId The file path
|
|
13781
13782
|
*/
|
|
13782
|
-
createSpecification(moduleId, locationsOrOptions, pool,
|
|
13783
|
-
return new TestSpecification(this, moduleId, pool || getFilePoolName(this), locationsOrOptions,
|
|
13783
|
+
createSpecification(moduleId, locationsOrOptions, pool, taskIdOverride) {
|
|
13784
|
+
return new TestSpecification(this, moduleId, pool || getFilePoolName(this), locationsOrOptions, taskIdOverride);
|
|
13784
13785
|
}
|
|
13785
13786
|
toJSON() {
|
|
13786
13787
|
return {
|
|
@@ -14029,7 +14030,8 @@ class TestProject {
|
|
|
14029
14030
|
async _configureServer(options, server) {
|
|
14030
14031
|
this._config = resolveConfig$1(this.vitest, {
|
|
14031
14032
|
...options,
|
|
14032
|
-
coverage: this.vitest.config.coverage
|
|
14033
|
+
coverage: this.vitest.config.coverage,
|
|
14034
|
+
attachmentsDir: this.vitest.config.attachmentsDir
|
|
14033
14035
|
}, server.config);
|
|
14034
14036
|
this._config.api.token = this.vitest.config.api.token;
|
|
14035
14037
|
this._config.mergeReportsLabel = this.vitest.config.mergeReportsLabel;
|
|
@@ -14069,9 +14071,8 @@ class TestProject {
|
|
|
14069
14071
|
const url = new URL("/__vitest_test__/", origin);
|
|
14070
14072
|
url.searchParams.set("sessionId", sessionId);
|
|
14071
14073
|
const otelCarrier = this.vitest._traces.getContextCarrier();
|
|
14072
|
-
if (otelCarrier) url.searchParams.set("otelCarrier", JSON.stringify(otelCarrier));
|
|
14073
14074
|
this.vitest._browserSessions.sessionIds.add(sessionId);
|
|
14074
|
-
const sessionPromise = this.vitest._browserSessions.createSession(sessionId, this, pool);
|
|
14075
|
+
const sessionPromise = this.vitest._browserSessions.createSession(sessionId, this, pool, { otelCarrier });
|
|
14075
14076
|
const pagePromise = this.browser.provider.openPage(sessionId, url.toString(), { parallel: pool.parallel ?? false });
|
|
14076
14077
|
await Promise.all([sessionPromise, pagePromise]);
|
|
14077
14078
|
}
|
|
@@ -14345,7 +14346,8 @@ function cloneConfig(project, { browser, ...config }) {
|
|
|
14345
14346
|
...project.config.browser,
|
|
14346
14347
|
locators: locators ? {
|
|
14347
14348
|
testIdAttribute: locators.testIdAttribute ?? currentConfig.locators.testIdAttribute,
|
|
14348
|
-
exact: locators.exact ?? currentConfig.locators.exact
|
|
14349
|
+
exact: locators.exact ?? currentConfig.locators.exact,
|
|
14350
|
+
errorFormat: locators.errorFormat ?? currentConfig.locators.errorFormat
|
|
14349
14351
|
} : project.config.browser.locators,
|
|
14350
14352
|
viewport: viewport ?? currentConfig.viewport,
|
|
14351
14353
|
testerHtmlPath: testerHtmlPath ?? currentConfig.testerHtmlPath,
|
|
@@ -14512,8 +14514,8 @@ class BlobReporter {
|
|
|
14512
14514
|
outputFile = [
|
|
14513
14515
|
"blob",
|
|
14514
14516
|
this.ctx.config.mergeReportsLabel,
|
|
14515
|
-
shard ?
|
|
14516
|
-
].join("");
|
|
14517
|
+
shard ? `${shard.index}-${shard.count}` : ""
|
|
14518
|
+
].filter(Boolean).join("-");
|
|
14517
14519
|
outputFile = `${sanitizeFilePath(outputFile)}.json`;
|
|
14518
14520
|
await report.writeFile(outputFile, content, "utf-8");
|
|
14519
14521
|
outputFile = resolve$1(report.root, outputFile);
|
|
@@ -14587,9 +14589,11 @@ function serializeEnvironmentModuleGraph(environment) {
|
|
|
14587
14589
|
};
|
|
14588
14590
|
const modules = [];
|
|
14589
14591
|
for (const [id, mod] of environment.moduleGraph.idToModuleMap.entries()) {
|
|
14590
|
-
|
|
14592
|
+
// Vite can generate module with `file = ""` for module id "#..."
|
|
14593
|
+
// when the actual module doesn't exist (e.g. resolve failure or mocked module)
|
|
14594
|
+
if (mod.file == null) continue;
|
|
14591
14595
|
const importedIds = [];
|
|
14592
|
-
for (const importedNode of mod.importedModules) if (importedNode.id) importedIds.push(getIdIndex(importedNode.id));
|
|
14596
|
+
for (const importedNode of mod.importedModules) if (importedNode.id !== null) importedIds.push(getIdIndex(importedNode.id));
|
|
14593
14597
|
modules.push([
|
|
14594
14598
|
getIdIndex(id),
|
|
14595
14599
|
getIdIndex(mod.file),
|
|
@@ -14608,6 +14612,10 @@ function deserializeEnvironmentModuleGraph(environment, serialized) {
|
|
|
14608
14612
|
const moduleId = serialized.idTable[id];
|
|
14609
14613
|
const filePath = serialized.idTable[file];
|
|
14610
14614
|
const urlPath = serialized.idTable[url];
|
|
14615
|
+
// `createFileOnlyEntry('')` normalizes the file to ".". This keeps
|
|
14616
|
+
// the graph usable, but doesn't perfectly round-trip Vite's `file = ""`
|
|
14617
|
+
// nodes for ids like "#...".
|
|
14618
|
+
// We may just do moduleNode.file = filePath in the future.
|
|
14611
14619
|
const moduleNode = environment.moduleGraph.createFileOnlyEntry(filePath);
|
|
14612
14620
|
moduleNode.url = urlPath;
|
|
14613
14621
|
moduleNode.id = moduleId;
|
|
@@ -15208,6 +15216,9 @@ function getIndentation(suite, level = 1) {
|
|
|
15208
15216
|
return level;
|
|
15209
15217
|
}
|
|
15210
15218
|
|
|
15219
|
+
/** Minimum time between two renders, no matter how many scheduled renderes were called */
|
|
15220
|
+
const DEFAULT_RENDER_THRESHOLD_MS = 100;
|
|
15221
|
+
/** Interval between automatic renders. If no test state changes happened, this will increase just duration field */
|
|
15211
15222
|
const DEFAULT_RENDER_INTERVAL_MS = 1e3;
|
|
15212
15223
|
const ESC$1 = "\x1B[";
|
|
15213
15224
|
const CLEAR_LINE = `${ESC$1}K`;
|
|
@@ -15230,14 +15241,19 @@ class WindowRenderer {
|
|
|
15230
15241
|
cleanups = [];
|
|
15231
15242
|
constructor(options) {
|
|
15232
15243
|
this.options = {
|
|
15233
|
-
|
|
15234
|
-
|
|
15244
|
+
...options,
|
|
15245
|
+
threshold: options.threshold ?? DEFAULT_RENDER_THRESHOLD_MS,
|
|
15246
|
+
interval: options.interval ?? DEFAULT_RENDER_INTERVAL_MS
|
|
15235
15247
|
};
|
|
15248
|
+
// Capture the original write methods early, before intercepting these
|
|
15236
15249
|
this.streams = {
|
|
15237
15250
|
output: options.logger.outputStream.write.bind(options.logger.outputStream),
|
|
15238
15251
|
error: options.logger.errorStream.write.bind(options.logger.errorStream)
|
|
15239
15252
|
};
|
|
15240
15253
|
this.cleanups.push(this.interceptStream(process.stdout, "output"), this.interceptStream(process.stderr, "error"));
|
|
15254
|
+
// Intercept calls to custom VitestOptions.stdout and stderr streams
|
|
15255
|
+
if (options.logger.outputStream !== process.stdout) this.cleanups.push(this.interceptStream(options.logger.outputStream, "output"));
|
|
15256
|
+
if (options.logger.errorStream !== process.stderr) this.cleanups.push(this.interceptStream(options.logger.errorStream, "error"));
|
|
15241
15257
|
// Write buffered content on unexpected exits, e.g. direct `process.exit()` calls
|
|
15242
15258
|
this.options.logger.onTerminalCleanup(() => {
|
|
15243
15259
|
this.flushBuffer();
|
|
@@ -15269,9 +15285,10 @@ class WindowRenderer {
|
|
|
15269
15285
|
if (!this.renderScheduled) {
|
|
15270
15286
|
this.renderScheduled = true;
|
|
15271
15287
|
this.flushBuffer();
|
|
15272
|
-
setTimeout(() => {
|
|
15288
|
+
if (this.options.threshold) setTimeout(() => {
|
|
15273
15289
|
this.renderScheduled = false;
|
|
15274
|
-
},
|
|
15290
|
+
}, this.options.threshold).unref();
|
|
15291
|
+
else this.renderScheduled = false;
|
|
15275
15292
|
}
|
|
15276
15293
|
}
|
|
15277
15294
|
flushBuffer() {
|
|
@@ -15293,15 +15310,16 @@ class WindowRenderer {
|
|
|
15293
15310
|
if (current) this.render(current?.message, current?.type);
|
|
15294
15311
|
}
|
|
15295
15312
|
render(message, type = "output") {
|
|
15313
|
+
this.write(SYNC_START);
|
|
15296
15314
|
if (this.finished) {
|
|
15297
15315
|
this.clearWindow();
|
|
15298
|
-
|
|
15316
|
+
this.write(message || "", type);
|
|
15317
|
+
return this.write(SYNC_END);
|
|
15299
15318
|
}
|
|
15300
15319
|
const windowContent = this.options.getWindow();
|
|
15301
15320
|
const rowCount = getRenderedRowCount(windowContent, this.options.logger.getColumns());
|
|
15302
15321
|
let padding = this.windowHeight - rowCount;
|
|
15303
15322
|
if (padding > 0 && message) padding -= getRenderedRowCount([message], this.options.logger.getColumns());
|
|
15304
|
-
this.write(SYNC_START);
|
|
15305
15323
|
this.clearWindow();
|
|
15306
15324
|
if (message) this.write(message, type);
|
|
15307
15325
|
if (padding > 0) this.write("\n".repeat(padding));
|
|
@@ -15373,7 +15391,9 @@ class SummaryReporter {
|
|
|
15373
15391
|
};
|
|
15374
15392
|
this.renderer = new WindowRenderer({
|
|
15375
15393
|
logger: ctx.logger,
|
|
15376
|
-
getWindow: () => this.createSummary()
|
|
15394
|
+
getWindow: () => this.createSummary(),
|
|
15395
|
+
interval: this.options.interval,
|
|
15396
|
+
threshold: this.options.threshold
|
|
15377
15397
|
});
|
|
15378
15398
|
this.ctx.onClose(() => {
|
|
15379
15399
|
clearInterval(this.durationInterval);
|
|
@@ -15427,6 +15447,7 @@ class SummaryReporter {
|
|
|
15427
15447
|
};
|
|
15428
15448
|
stats.hook?.onFinish?.();
|
|
15429
15449
|
stats.hook = hook;
|
|
15450
|
+
if (!Number.isFinite(this.ctx.config.slowTestThreshold)) return;
|
|
15430
15451
|
const timeout = setTimeout(() => {
|
|
15431
15452
|
hook.visible = true;
|
|
15432
15453
|
}, this.ctx.config.slowTestThreshold).unref();
|
|
@@ -15449,9 +15470,9 @@ class SummaryReporter {
|
|
|
15449
15470
|
startTime: performance.now(),
|
|
15450
15471
|
onFinish: () => {}
|
|
15451
15472
|
};
|
|
15452
|
-
const timeout = setTimeout(() => {
|
|
15473
|
+
const timeout = Number.isFinite(this.ctx.config.slowTestThreshold) ? setTimeout(() => {
|
|
15453
15474
|
slowTest.visible = true;
|
|
15454
|
-
}, this.ctx.config.slowTestThreshold).unref();
|
|
15475
|
+
}, this.ctx.config.slowTestThreshold).unref() : void 0;
|
|
15455
15476
|
slowTest.onFinish = () => {
|
|
15456
15477
|
slowTest.hook?.onFinish();
|
|
15457
15478
|
clearTimeout(timeout);
|
|
@@ -15630,7 +15651,10 @@ class DefaultReporter extends BaseReporter {
|
|
|
15630
15651
|
}
|
|
15631
15652
|
onInit(ctx) {
|
|
15632
15653
|
super.onInit(ctx);
|
|
15633
|
-
this.summary?.onInit(ctx, {
|
|
15654
|
+
this.summary?.onInit(ctx, {
|
|
15655
|
+
verbose: this.verbose,
|
|
15656
|
+
...this.options.summaryOptions
|
|
15657
|
+
});
|
|
15634
15658
|
}
|
|
15635
15659
|
}
|
|
15636
15660
|
|
|
@@ -16277,14 +16301,7 @@ class JUnitReporter {
|
|
|
16277
16301
|
}
|
|
16278
16302
|
if (task.result?.state === "fail") {
|
|
16279
16303
|
const errors = task.result.errors || [];
|
|
16280
|
-
for (const error of errors) await this.
|
|
16281
|
-
message: error?.message,
|
|
16282
|
-
type: error?.name
|
|
16283
|
-
}, async () => {
|
|
16284
|
-
if (!error || !this.options.stackTrace) return;
|
|
16285
|
-
const result = this.ctx.logger.formatError(error, { project: this.ctx.getProjectByName(task.file?.projectName ?? "") });
|
|
16286
|
-
await this.baseLog(escapeXML(stripVTControlCharacters(result.output.trim())));
|
|
16287
|
-
});
|
|
16304
|
+
for (const error of errors) await this.writeErrorElement("failure", error, { project: this.ctx.getProjectByName(task.file?.projectName ?? "") });
|
|
16288
16305
|
}
|
|
16289
16306
|
});
|
|
16290
16307
|
}
|
|
@@ -16303,7 +16320,52 @@ class JUnitReporter {
|
|
|
16303
16320
|
if (typeof this.options.suiteNameTemplate === "function") return this.options.suiteNameTemplate(vars);
|
|
16304
16321
|
return this.options.suiteNameTemplate.replace(/\{filepath\}/g, () => vars.filepath).replace(/\{filename\}/g, () => vars.filename).replace(/\{basename\}/g, () => vars.basename).replace(/\{displayName\}/g, () => vars.displayName).replace(/\{title\}/g, () => vars.title);
|
|
16305
16322
|
}
|
|
16306
|
-
async
|
|
16323
|
+
async writeErrorElement(elementName, error, errorOptions) {
|
|
16324
|
+
await this.writeElement(elementName, {
|
|
16325
|
+
message: error?.message,
|
|
16326
|
+
type: error?.name
|
|
16327
|
+
}, async () => {
|
|
16328
|
+
if (!error || !this.options.stackTrace) return;
|
|
16329
|
+
const result = this.ctx.logger.formatError(error, errorOptions);
|
|
16330
|
+
await this.baseLog(escapeXML(stripVTControlCharacters(result.output.trim())));
|
|
16331
|
+
});
|
|
16332
|
+
}
|
|
16333
|
+
async writeUnhandledErrorsTestsuite(unhandledErrors, testModules) {
|
|
16334
|
+
await this.writeElement("testsuite", {
|
|
16335
|
+
name: "vitest unhandled errors",
|
|
16336
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16337
|
+
hostname: this.options.hostname || hostname(),
|
|
16338
|
+
tests: unhandledErrors.length,
|
|
16339
|
+
failures: 0,
|
|
16340
|
+
errors: unhandledErrors.length,
|
|
16341
|
+
skipped: 0,
|
|
16342
|
+
time: "0"
|
|
16343
|
+
}, async () => {
|
|
16344
|
+
// Stable order across runs — workers/projects report errors concurrently.
|
|
16345
|
+
const sortedErrors = [...unhandledErrors].sort((a, b) => {
|
|
16346
|
+
const ka = `${a.VITEST_TEST_PATH ?? ""}\0${a.type ?? ""}\0${a.name ?? ""}\0${a.message ?? ""}`;
|
|
16347
|
+
const kb = `${b.VITEST_TEST_PATH ?? ""}\0${b.type ?? ""}\0${b.name ?? ""}\0${b.message ?? ""}`;
|
|
16348
|
+
return ka < kb ? -1 : ka > kb ? 1 : 0;
|
|
16349
|
+
});
|
|
16350
|
+
for (const error of sortedErrors) {
|
|
16351
|
+
const errorTitle = error.type || error.name || "Unhandled Error";
|
|
16352
|
+
// Only attribute when the path resolves to exactly one module — when
|
|
16353
|
+
// multiple projects share a file, errors lack a project identifier and
|
|
16354
|
+
// we can't disambiguate without one (tracked for follow-up).
|
|
16355
|
+
const matches = error.VITEST_TEST_PATH ? testModules.filter((m) => m.task.filepath === error.VITEST_TEST_PATH) : [];
|
|
16356
|
+
const owningModule = matches.length === 1 ? matches[0] : void 0;
|
|
16357
|
+
await this.writeElement("testcase", {
|
|
16358
|
+
classname: "vitest unhandled errors",
|
|
16359
|
+
file: this.options.addFileAttribute && error.VITEST_TEST_PATH ? relative(this.ctx.config.root, error.VITEST_TEST_PATH) : void 0,
|
|
16360
|
+
name: error.message ? `${errorTitle}: ${error.message}` : errorTitle,
|
|
16361
|
+
time: "0"
|
|
16362
|
+
}, async () => {
|
|
16363
|
+
await this.writeErrorElement("error", error, { project: owningModule?.project });
|
|
16364
|
+
});
|
|
16365
|
+
}
|
|
16366
|
+
});
|
|
16367
|
+
}
|
|
16368
|
+
async onTestRunEnd(testModules, unhandledErrors = []) {
|
|
16307
16369
|
const files = testModules.map((testModule) => testModule.task);
|
|
16308
16370
|
const separator = this.options.ancestorSeparator ?? " > ";
|
|
16309
16371
|
await this.logger.log("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
|
|
@@ -16361,32 +16423,36 @@ class JUnitReporter {
|
|
|
16361
16423
|
name: this.options.suiteName || "vitest tests",
|
|
16362
16424
|
tests: 0,
|
|
16363
16425
|
failures: 0,
|
|
16364
|
-
errors:
|
|
16426
|
+
errors: unhandledErrors.length,
|
|
16365
16427
|
time: 0
|
|
16366
16428
|
});
|
|
16429
|
+
stats.tests += unhandledErrors.length;
|
|
16430
|
+
// Plain byte compare (not localeCompare) so output is identical across machines and ICU versions.
|
|
16431
|
+
const orderedSuites = transformed.map((file, i) => {
|
|
16432
|
+
const filename = relative(this.ctx.config.root, file.filepath);
|
|
16433
|
+
return {
|
|
16434
|
+
file,
|
|
16435
|
+
filename,
|
|
16436
|
+
suiteName: this.resolveSuiteNameTemplate(files[i], filename)
|
|
16437
|
+
};
|
|
16438
|
+
}).sort((a, b) => a.suiteName < b.suiteName ? -1 : a.suiteName > b.suiteName ? 1 : 0);
|
|
16367
16439
|
await this.writeElement("testsuites", {
|
|
16368
16440
|
...stats,
|
|
16369
16441
|
time: executionTime(stats.time)
|
|
16370
16442
|
}, async () => {
|
|
16371
|
-
for (
|
|
16372
|
-
|
|
16373
|
-
|
|
16374
|
-
|
|
16375
|
-
|
|
16376
|
-
|
|
16377
|
-
|
|
16378
|
-
|
|
16379
|
-
|
|
16380
|
-
|
|
16381
|
-
|
|
16382
|
-
|
|
16383
|
-
|
|
16384
|
-
skipped: file.stats.skipped,
|
|
16385
|
-
time: getDuration(file)
|
|
16386
|
-
}, async () => {
|
|
16387
|
-
await this.writeTasks(file.tasks, filename, file.filepath);
|
|
16388
|
-
});
|
|
16389
|
-
}
|
|
16443
|
+
for (const { file, filename, suiteName } of orderedSuites) await this.writeElement("testsuite", {
|
|
16444
|
+
name: suiteName,
|
|
16445
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16446
|
+
hostname: this.options.hostname || hostname(),
|
|
16447
|
+
tests: file.tasks.length,
|
|
16448
|
+
failures: file.stats.failures,
|
|
16449
|
+
errors: 0,
|
|
16450
|
+
skipped: file.stats.skipped,
|
|
16451
|
+
time: getDuration(file)
|
|
16452
|
+
}, async () => {
|
|
16453
|
+
await this.writeTasks(file.tasks, filename, file.filepath);
|
|
16454
|
+
});
|
|
16455
|
+
if (unhandledErrors.length) await this.writeUnhandledErrorsTestsuite(unhandledErrors, testModules);
|
|
16390
16456
|
});
|
|
16391
16457
|
if (this.reportFile) this.ctx.logger.log(`JUNIT report written to ${this.reportFile}`);
|
|
16392
16458
|
await this.fileFd?.close();
|
|
@@ -16994,6 +17060,12 @@ class ReportedTaskImplementation {
|
|
|
16994
17060
|
return this.task.meta;
|
|
16995
17061
|
}
|
|
16996
17062
|
/**
|
|
17063
|
+
* Console logs recorded during the test execution.
|
|
17064
|
+
*/
|
|
17065
|
+
logs() {
|
|
17066
|
+
return [...this.task.logs || []];
|
|
17067
|
+
}
|
|
17068
|
+
/**
|
|
16997
17069
|
* Creates a new reported task instance and stores it in the project's state for future use.
|
|
16998
17070
|
* @internal
|
|
16999
17071
|
*/
|
|
@@ -18767,7 +18839,7 @@ class Vitest {
|
|
|
18767
18839
|
await this.report("onInit", this);
|
|
18768
18840
|
const specifications = [];
|
|
18769
18841
|
for (const file of files) {
|
|
18770
|
-
const specification = this.getProjectByName(file.projectName || "").createSpecification(file.filepath, void 0, file.pool, file.
|
|
18842
|
+
const specification = this.getProjectByName(file.projectName || "").createSpecification(file.filepath, void 0, file.pool, file.id);
|
|
18771
18843
|
specifications.push(specification);
|
|
18772
18844
|
}
|
|
18773
18845
|
await this._testRun.start(specifications);
|