vitest 3.2.0-beta.2 → 3.2.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +1 -1
- package/dist/chunks/{base.DwtwORaC.js → base.D4119yLM.js} +4 -3
- package/dist/chunks/{benchmark.BoF7jW0Q.js → benchmark.Cf_PACH1.js} +1 -1
- package/dist/chunks/{cac.I9MLYfT-.js → cac.DWaWHIIE.js} +18 -15
- package/dist/chunks/{cli-api.d6IK1pnk.js → cli-api.CnmEXkxs.js} +250 -49
- package/dist/chunks/{config.d.UqE-KR0o.d.ts → config.d.D2ROskhv.d.ts} +2 -0
- package/dist/chunks/{console.K1NMVOSc.js → console.Cwr-MFPV.js} +3 -2
- package/dist/chunks/{constants.BZZyIeIE.js → constants.DnKduX2e.js} +1 -0
- package/dist/chunks/{coverage.OGU09Jbh.js → coverage.C73DaDgS.js} +116 -12
- package/dist/chunks/{creator.DGAdZ4Hj.js → creator.C8WKy2eW.js} +10 -7
- package/dist/chunks/{date.CDOsz-HY.js → date.ByMsSlOr.js} +25 -0
- package/dist/chunks/{defaults.DSxsTG0h.js → defaults.DpVH7vbg.js} +1 -0
- package/dist/chunks/{environment.d.D8YDy2v5.d.ts → environment.d.cL3nLXbE.d.ts} +1 -0
- package/dist/chunks/{execute.JlGHLJZT.js → execute.B3q-2LPV.js} +25 -0
- package/dist/chunks/{global.d.BPa1eL3O.d.ts → global.d.BNLIi6yo.d.ts} +3 -1
- package/dist/chunks/{globals.CpxW8ccg.js → globals.CI21aWXF.js} +7 -6
- package/dist/chunks/{index.DFXFpH3w.js → index.2jgTs_Q5.js} +19 -1
- package/dist/chunks/{index.CV36oG_L.js → index.Bter3jj9.js} +83 -16
- package/dist/chunks/{index.DswW_LEs.js → index.CbT4iuwc.js} +7 -4
- package/dist/chunks/index.D3XRDfWc.js +213 -0
- package/dist/chunks/{index.CfXMNXHg.js → index.DNgLEKsQ.js} +4 -2
- package/dist/chunks/{index.CmC5OK9L.js → index.JOzufsrU.js} +2 -1
- package/dist/chunks/{inspector.DbDkSkFn.js → inspector.BFsh5KO0.js} +3 -0
- package/dist/chunks/{node.3xsWotC9.js → node.Be-ntJnD.js} +1 -1
- package/dist/chunks/{reporters.d.CLC9rhKy.d.ts → reporters.d.Bt4IGtsa.d.ts} +24 -6
- package/dist/chunks/{rpc.D9_013TY.js → rpc.BKExFSRG.js} +2 -1
- package/dist/chunks/{runBaseTests.Dn2vyej_.js → runBaseTests.B_M1TTsK.js} +19 -10
- package/dist/chunks/{setup-common.CYo3Y0dD.js → setup-common.CF-O-dZX.js} +2 -1
- package/dist/chunks/{typechecker.DnTrplSJ.js → typechecker.BgzF-6iO.js} +78 -21
- package/dist/chunks/{utils.CgTj3MsC.js → utils.BlI4TC7Y.js} +1 -0
- package/dist/chunks/{utils.BfxieIyZ.js → utils.DPCq3gzW.js} +3 -0
- package/dist/chunks/{vi.BFR5YIgu.js → vi.pkoYCV6A.js} +25 -2
- package/dist/chunks/{vite.d.CBZ3M_ru.d.ts → vite.d.B-Kx3KCF.d.ts} +3 -1
- package/dist/chunks/{vm.C1HHjtNS.js → vm.DPYem2so.js} +72 -4
- package/dist/chunks/{worker.d.CoCI7hzP.d.ts → worker.d.BKbBp2ga.d.ts} +2 -2
- package/dist/chunks/{worker.d.D5Xdi-Zr.d.ts → worker.d.Bl1O4kuf.d.ts} +1 -1
- package/dist/cli.js +4 -4
- package/dist/config.cjs +2 -0
- package/dist/config.d.ts +7 -6
- package/dist/config.js +2 -2
- package/dist/coverage.d.ts +4 -4
- package/dist/coverage.js +5 -5
- package/dist/environments.d.ts +6 -2
- package/dist/environments.js +1 -1
- package/dist/execute.d.ts +9 -3
- package/dist/execute.js +1 -1
- package/dist/index.d.ts +24 -12
- package/dist/index.js +5 -5
- package/dist/node.d.ts +18 -10
- package/dist/node.js +14 -12
- package/dist/reporters.d.ts +4 -4
- package/dist/reporters.js +3 -3
- package/dist/runners.d.ts +1 -1
- package/dist/runners.js +13 -5
- package/dist/snapshot.js +2 -2
- package/dist/suite.js +2 -2
- package/dist/worker.js +9 -5
- package/dist/workers/forks.js +6 -4
- package/dist/workers/runVmTests.js +14 -9
- package/dist/workers/threads.js +4 -4
- package/dist/workers/vmForks.js +6 -6
- package/dist/workers/vmThreads.js +6 -6
- package/dist/workers.d.ts +4 -4
- package/dist/workers.js +10 -10
- package/package.json +18 -18
- package/dist/chunks/index.CK1YOQaa.js +0 -143
|
@@ -5,7 +5,7 @@ import { parseStacktrace, parseErrorStacktrace } from '@vitest/utils/source-map'
|
|
|
5
5
|
import { isAbsolute, relative, dirname, basename, resolve, normalize } from 'pathe';
|
|
6
6
|
import c from 'tinyrainbow';
|
|
7
7
|
import { i as isTTY } from './env.Dq0hM4Xv.js';
|
|
8
|
-
import { h as hasFailedSnapshot, g as getOutputFile, T as TypeCheckError } from './typechecker.
|
|
8
|
+
import { h as hasFailedSnapshot, g as getOutputFile, T as TypeCheckError } from './typechecker.BgzF-6iO.js';
|
|
9
9
|
import { stripVTControlCharacters } from 'node:util';
|
|
10
10
|
import { existsSync, readFileSync, promises } from 'node:fs';
|
|
11
11
|
import { mkdir, writeFile, readdir, stat, readFile } from 'node:fs/promises';
|
|
@@ -283,6 +283,8 @@ class BaseReporter {
|
|
|
283
283
|
let testsCount = 0;
|
|
284
284
|
let failedCount = 0;
|
|
285
285
|
let skippedCount = 0;
|
|
286
|
+
// delaying logs to calculate the test stats first
|
|
287
|
+
// which minimizes the amount of for loops
|
|
286
288
|
const logs = [];
|
|
287
289
|
const originalLog = this.log.bind(this);
|
|
288
290
|
this.log = (msg) => logs.push(msg);
|
|
@@ -290,6 +292,7 @@ class BaseReporter {
|
|
|
290
292
|
for (const child of children) {
|
|
291
293
|
if (child.type === "suite") {
|
|
292
294
|
const suiteState = child.state();
|
|
295
|
+
// Skipped suites are hidden when --hideSkippedTests, print otherwise
|
|
293
296
|
if (!this.ctx.config.hideSkippedTests || suiteState !== "skipped") {
|
|
294
297
|
this.printTestSuite(child);
|
|
295
298
|
}
|
|
@@ -303,6 +306,7 @@ class BaseReporter {
|
|
|
303
306
|
skippedCount++;
|
|
304
307
|
}
|
|
305
308
|
if (this.ctx.config.hideSkippedTests && suiteState === "skipped") {
|
|
309
|
+
// Skipped suites are hidden when --hideSkippedTests
|
|
306
310
|
continue;
|
|
307
311
|
}
|
|
308
312
|
this.printTestCase(moduleState, child);
|
|
@@ -334,6 +338,7 @@ class BaseReporter {
|
|
|
334
338
|
}
|
|
335
339
|
if (testResult.state === "failed") {
|
|
336
340
|
this.log(c.red(` ${padding}${taskFail} ${this.getTestName(test.task, c.dim(" > "))}`) + suffix);
|
|
341
|
+
// print short errors, full errors will be at the end in summary
|
|
337
342
|
testResult.errors.forEach((error) => {
|
|
338
343
|
const message = this.formatShortError(error);
|
|
339
344
|
if (message) {
|
|
@@ -370,7 +375,9 @@ class BaseReporter {
|
|
|
370
375
|
}
|
|
371
376
|
return ` ${title} ${testModule.task.name} ${suffix}`;
|
|
372
377
|
}
|
|
373
|
-
printTestSuite(_suite) {
|
|
378
|
+
printTestSuite(_suite) {
|
|
379
|
+
// Suite name is included in getTestName by default
|
|
380
|
+
}
|
|
374
381
|
getTestName(test, separator) {
|
|
375
382
|
return getTestName(test, separator);
|
|
376
383
|
}
|
|
@@ -407,6 +414,7 @@ class BaseReporter {
|
|
|
407
414
|
onWatcherRerun(files, trigger) {
|
|
408
415
|
this.watchFilters = files;
|
|
409
416
|
this.failedUnwatchedFiles = this.ctx.state.getTestModules().filter((testModule) => !files.includes(testModule.task.filepath) && testModule.state() === "failed");
|
|
417
|
+
// Update re-run count for each file
|
|
410
418
|
files.forEach((filepath) => {
|
|
411
419
|
let reruns = this._filesInWatchMode.get(filepath) ?? 0;
|
|
412
420
|
this._filesInWatchMode.set(filepath, ++reruns);
|
|
@@ -449,6 +457,7 @@ class BaseReporter {
|
|
|
449
457
|
}
|
|
450
458
|
write(c.gray(log.type + c.dim(` | ${headerText}\n`)) + log.content);
|
|
451
459
|
if (log.origin) {
|
|
460
|
+
// browser logs don't have an extra end of line at the end like Node.js does
|
|
452
461
|
if (log.browser) {
|
|
453
462
|
write("\n");
|
|
454
463
|
}
|
|
@@ -520,6 +529,7 @@ class BaseReporter {
|
|
|
520
529
|
this.log(padSummaryTitle("Duration"), formatTime(collectTime + testsTime + setupTime));
|
|
521
530
|
} else {
|
|
522
531
|
const blobs = this.ctx.state.blobs;
|
|
532
|
+
// Execution time is either sum of all runs of `--merge-reports` or the current run's time
|
|
523
533
|
const executionTime = blobs?.executionTimes ? sum(blobs.executionTimes, (time) => time) : this.end - this.start;
|
|
524
534
|
const environmentTime = sum(files, (file) => file.environmentLoad);
|
|
525
535
|
const prepareTime = sum(files, (file) => file.prepareDuration);
|
|
@@ -585,6 +595,7 @@ class BaseReporter {
|
|
|
585
595
|
printTaskErrors(tasks, errorDivider) {
|
|
586
596
|
const errorsQueue = [];
|
|
587
597
|
for (const task of tasks) {
|
|
598
|
+
// Merge identical errors
|
|
588
599
|
task.result?.errors?.forEach((error) => {
|
|
589
600
|
let previous;
|
|
590
601
|
if (error?.stackStr) {
|
|
@@ -642,6 +653,7 @@ class BasicReporter extends BaseReporter {
|
|
|
642
653
|
ctx.logger.deprecate(`'basic' reporter is deprecated and will be removed in Vitest v3.\n` + `Remove 'basic' from 'reporters' option. To match 'basic' reporter 100%, use configuration:\n${JSON.stringify({ test: { reporters: [["default", { summary: false }]] } }, null, 2)}`);
|
|
643
654
|
}
|
|
644
655
|
reportSummary(files, errors) {
|
|
656
|
+
// non-tty mode doesn't add a new line
|
|
645
657
|
this.ctx.logger.log();
|
|
646
658
|
return super.reportSummary(files, errors);
|
|
647
659
|
}
|
|
@@ -809,6 +821,7 @@ async function writeBlob(content, filename) {
|
|
|
809
821
|
await writeFile(filename, report, "utf-8");
|
|
810
822
|
}
|
|
811
823
|
async function readBlobs(currentVersion, blobsDirectory, projectsArray) {
|
|
824
|
+
// using process.cwd() because --merge-reports can only be used in CLI
|
|
812
825
|
const resolvedDir = resolve(process.cwd(), blobsDirectory);
|
|
813
826
|
const blobsFiles = await readdir(resolvedDir);
|
|
814
827
|
const promises = blobsFiles.map(async (filename) => {
|
|
@@ -843,6 +856,7 @@ async function readBlobs(currentVersion, blobsDirectory, projectsArray) {
|
|
|
843
856
|
if (!versions.has(currentVersion)) {
|
|
844
857
|
throw new Error(`the blobs in "${blobsDirectory}" were generated by a different version of Vitest. Expected v${currentVersion}, but received v${blobs[0].version}`);
|
|
845
858
|
}
|
|
859
|
+
// fake module graph - it is used to check if module is imported, but we don't use values inside
|
|
846
860
|
const projects = Object.fromEntries(projectsArray.map((p) => [p.name, p]));
|
|
847
861
|
blobs.forEach((blob) => {
|
|
848
862
|
blob.moduleKeys.forEach(([projectName, moduleIds]) => {
|
|
@@ -903,6 +917,7 @@ class WindowRenderer {
|
|
|
903
917
|
error: options.logger.errorStream.write.bind(options.logger.errorStream)
|
|
904
918
|
};
|
|
905
919
|
this.cleanups.push(this.interceptStream(process.stdout, "output"), this.interceptStream(process.stderr, "error"));
|
|
920
|
+
// Write buffered content on unexpected exits, e.g. direct `process.exit()` calls
|
|
906
921
|
this.options.logger.onTerminalCleanup(() => {
|
|
907
922
|
this.flushBuffer();
|
|
908
923
|
this.stop();
|
|
@@ -943,6 +958,7 @@ class WindowRenderer {
|
|
|
943
958
|
return this.render();
|
|
944
959
|
}
|
|
945
960
|
let current;
|
|
961
|
+
// Concatenate same types into a single render
|
|
946
962
|
for (const next of this.buffer.splice(0)) {
|
|
947
963
|
if (!current) {
|
|
948
964
|
current = next;
|
|
@@ -994,6 +1010,7 @@ class WindowRenderer {
|
|
|
994
1010
|
}
|
|
995
1011
|
interceptStream(stream, type) {
|
|
996
1012
|
const original = stream.write;
|
|
1013
|
+
// @ts-expect-error -- not sure how 2 overloads should be typed
|
|
997
1014
|
stream.write = (chunk, _, callback) => {
|
|
998
1015
|
if (chunk) {
|
|
999
1016
|
if (this.finished) {
|
|
@@ -1077,6 +1094,7 @@ class SummaryReporter {
|
|
|
1077
1094
|
clearInterval(this.durationInterval);
|
|
1078
1095
|
}
|
|
1079
1096
|
onTestModuleQueued(module) {
|
|
1097
|
+
// When new test module starts, take the place of previously finished test module, if any
|
|
1080
1098
|
if (this.finishedModules.size) {
|
|
1081
1099
|
const finished = this.finishedModules.keys().next().value;
|
|
1082
1100
|
this.removeTestModule(finished);
|
|
@@ -1123,6 +1141,7 @@ class SummaryReporter {
|
|
|
1123
1141
|
stats.hook.visible = false;
|
|
1124
1142
|
}
|
|
1125
1143
|
onTestCaseReady(test) {
|
|
1144
|
+
// Track slow running tests only on verbose mode
|
|
1126
1145
|
if (!this.options.verbose) {
|
|
1127
1146
|
return;
|
|
1128
1147
|
}
|
|
@@ -1176,16 +1195,22 @@ class SummaryReporter {
|
|
|
1176
1195
|
this.modules.skipped++;
|
|
1177
1196
|
}
|
|
1178
1197
|
const left = this.modules.total - this.modules.completed;
|
|
1198
|
+
// Keep finished tests visible in summary for a while if there are more tests left.
|
|
1199
|
+
// When a new test starts in onTestModuleQueued it will take this ones place.
|
|
1200
|
+
// This reduces flickering by making summary more stable.
|
|
1179
1201
|
if (left > this.maxParallelTests) {
|
|
1180
1202
|
this.finishedModules.set(module.id, setTimeout(() => {
|
|
1181
1203
|
this.removeTestModule(module.id);
|
|
1182
1204
|
}, FINISHED_TEST_CLEANUP_TIME_MS).unref());
|
|
1183
1205
|
} else {
|
|
1206
|
+
// Run is about to end as there are less tests left than whole run had parallel at max.
|
|
1207
|
+
// Remove finished test immediately.
|
|
1184
1208
|
this.removeTestModule(module.id);
|
|
1185
1209
|
}
|
|
1186
1210
|
this.renderer.schedule();
|
|
1187
1211
|
}
|
|
1188
1212
|
getHookStats({ entity }) {
|
|
1213
|
+
// Track slow running hooks only on verbose mode
|
|
1189
1214
|
if (!this.options.verbose) {
|
|
1190
1215
|
return;
|
|
1191
1216
|
}
|
|
@@ -1300,6 +1325,14 @@ class DefaultReporter extends BaseReporter {
|
|
|
1300
1325
|
}
|
|
1301
1326
|
}
|
|
1302
1327
|
onTestRunStart(specifications) {
|
|
1328
|
+
if (this.isTTY) {
|
|
1329
|
+
if (this.renderSucceed === undefined) {
|
|
1330
|
+
this.renderSucceed = !!this.renderSucceed;
|
|
1331
|
+
}
|
|
1332
|
+
if (this.renderSucceed !== true) {
|
|
1333
|
+
this.renderSucceed = specifications.length <= 1;
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1303
1336
|
this.summary?.onTestRunStart(specifications);
|
|
1304
1337
|
}
|
|
1305
1338
|
onTestModuleQueued(file) {
|
|
@@ -1329,16 +1362,6 @@ class DefaultReporter extends BaseReporter {
|
|
|
1329
1362
|
super.onInit(ctx);
|
|
1330
1363
|
this.summary?.onInit(ctx, { verbose: this.verbose });
|
|
1331
1364
|
}
|
|
1332
|
-
onPathsCollected(paths = []) {
|
|
1333
|
-
if (this.isTTY) {
|
|
1334
|
-
if (this.renderSucceed === undefined) {
|
|
1335
|
-
this.renderSucceed = !!this.renderSucceed;
|
|
1336
|
-
}
|
|
1337
|
-
if (this.renderSucceed !== true) {
|
|
1338
|
-
this.renderSucceed = paths.length <= 1;
|
|
1339
|
-
}
|
|
1340
|
-
}
|
|
1341
|
-
}
|
|
1342
1365
|
onTestRunEnd() {
|
|
1343
1366
|
this.summary?.onTestRunEnd();
|
|
1344
1367
|
}
|
|
@@ -1379,6 +1402,7 @@ class DotReporter extends BaseReporter {
|
|
|
1379
1402
|
}
|
|
1380
1403
|
onTestModuleCollected(module) {
|
|
1381
1404
|
for (const test of module.children.allTests()) {
|
|
1405
|
+
// Dot reporter marks pending tests as running
|
|
1382
1406
|
this.onTestCaseReady(test);
|
|
1383
1407
|
}
|
|
1384
1408
|
}
|
|
@@ -1408,6 +1432,7 @@ class DotReporter extends BaseReporter {
|
|
|
1408
1432
|
if (finishedTests.length < columns) {
|
|
1409
1433
|
return;
|
|
1410
1434
|
}
|
|
1435
|
+
// Remove finished tests from state and render them in static output
|
|
1411
1436
|
const states = [];
|
|
1412
1437
|
let count = 0;
|
|
1413
1438
|
for (const [id, state] of finishedTests) {
|
|
@@ -1424,6 +1449,7 @@ class DotReporter extends BaseReporter {
|
|
|
1424
1449
|
return [formatTests(Array.from(this.tests.values())), ""];
|
|
1425
1450
|
}
|
|
1426
1451
|
}
|
|
1452
|
+
// These are compared with reference equality in formatTests
|
|
1427
1453
|
const pass = {
|
|
1428
1454
|
char: "·",
|
|
1429
1455
|
color: c.green
|
|
@@ -1463,6 +1489,7 @@ function formatTests(states) {
|
|
|
1463
1489
|
continue;
|
|
1464
1490
|
}
|
|
1465
1491
|
output += currentIcon.color(currentIcon.char.repeat(count));
|
|
1492
|
+
// Start tracking new group
|
|
1466
1493
|
count = 1;
|
|
1467
1494
|
currentIcon = icon;
|
|
1468
1495
|
}
|
|
@@ -1470,6 +1497,7 @@ function formatTests(states) {
|
|
|
1470
1497
|
return output;
|
|
1471
1498
|
}
|
|
1472
1499
|
|
|
1500
|
+
// use Logger with custom Console to capture entire error printing
|
|
1473
1501
|
function capturePrintError(error, ctx, options) {
|
|
1474
1502
|
let output = "";
|
|
1475
1503
|
const writable = new Writable({ write(chunk, _encoding, callback) {
|
|
@@ -1499,9 +1527,12 @@ function printError(error, ctx, logger, options) {
|
|
|
1499
1527
|
screenshotPaths: options.screenshotPaths,
|
|
1500
1528
|
printProperties: options.verbose,
|
|
1501
1529
|
parseErrorStacktrace(error) {
|
|
1530
|
+
// browser stack trace needs to be processed differently,
|
|
1531
|
+
// so there is a separate method for that
|
|
1502
1532
|
if (options.task?.file.pool === "browser" && project.browser) {
|
|
1503
1533
|
return project.browser.parseErrorStacktrace(error, { ignoreStackEntries: options.fullStack ? [] : undefined });
|
|
1504
1534
|
}
|
|
1535
|
+
// node.js stack trace already has correct source map locations
|
|
1505
1536
|
return parseErrorStacktrace(error, {
|
|
1506
1537
|
frameFilter: project.config.onStackTrace,
|
|
1507
1538
|
ignoreStackEntries: options.fullStack ? [] : undefined
|
|
@@ -1526,6 +1557,7 @@ function printErrorInner(error, project, options) {
|
|
|
1526
1557
|
stack: error.stack
|
|
1527
1558
|
};
|
|
1528
1559
|
}
|
|
1560
|
+
// Error may have occurred even before the configuration was resolved
|
|
1529
1561
|
if (!project) {
|
|
1530
1562
|
printErrorMessage(e, logger);
|
|
1531
1563
|
return;
|
|
@@ -1554,6 +1586,7 @@ function printErrorInner(error, project, options) {
|
|
|
1554
1586
|
logger.error(`${e.codeFrame}\n`);
|
|
1555
1587
|
}
|
|
1556
1588
|
if ("__vitest_rollup_error__" in e) {
|
|
1589
|
+
// https://github.com/vitejs/vite/blob/95020ab49e12d143262859e095025cf02423c1d9/packages/vite/src/node/server/middlewares/error.ts#L25-L36
|
|
1557
1590
|
const err = e.__vitest_rollup_error__;
|
|
1558
1591
|
logger.error([
|
|
1559
1592
|
err.plugin && ` Plugin: ${c.magenta(err.plugin)}`,
|
|
@@ -1561,9 +1594,11 @@ function printErrorInner(error, project, options) {
|
|
|
1561
1594
|
err.frame && c.yellow(err.frame.split(/\r?\n/g).map((l) => ` `.repeat(2) + l).join(`\n`))
|
|
1562
1595
|
].filter(Boolean).join("\n"));
|
|
1563
1596
|
}
|
|
1597
|
+
// E.g. AssertionError from assert does not set showDiff but has both actual and expected properties
|
|
1564
1598
|
if (e.diff) {
|
|
1565
1599
|
logger.error(`\n${e.diff}\n`);
|
|
1566
1600
|
}
|
|
1601
|
+
// if the error provide the frame
|
|
1567
1602
|
if (e.frame) {
|
|
1568
1603
|
logger.error(c.yellow(e.frame));
|
|
1569
1604
|
} else {
|
|
@@ -1578,6 +1613,7 @@ function printErrorInner(error, project, options) {
|
|
|
1578
1613
|
const testPath = e.VITEST_TEST_PATH;
|
|
1579
1614
|
const testName = e.VITEST_TEST_NAME;
|
|
1580
1615
|
const afterEnvTeardown = e.VITEST_AFTER_ENV_TEARDOWN;
|
|
1616
|
+
// testName has testPath inside
|
|
1581
1617
|
if (testPath) {
|
|
1582
1618
|
logger.error(c.red(`This error originated in "${c.bold(relative(project.config.root, testPath))}" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.`));
|
|
1583
1619
|
}
|
|
@@ -1603,7 +1639,6 @@ function printErrorType(type, ctx) {
|
|
|
1603
1639
|
}
|
|
1604
1640
|
const skipErrorProperties = new Set([
|
|
1605
1641
|
"nameStr",
|
|
1606
|
-
"stack",
|
|
1607
1642
|
"cause",
|
|
1608
1643
|
"stacks",
|
|
1609
1644
|
"stackStr",
|
|
@@ -1634,7 +1669,10 @@ function getErrorProperties(e) {
|
|
|
1634
1669
|
return errorObject;
|
|
1635
1670
|
}
|
|
1636
1671
|
for (const key of Object.getOwnPropertyNames(e)) {
|
|
1637
|
-
if
|
|
1672
|
+
// print the original stack if it was ever changed manually by the user
|
|
1673
|
+
if (key === "stack" && e[key] != null && typeof e[key] !== "string") {
|
|
1674
|
+
errorObject[key] = e[key];
|
|
1675
|
+
} else if (key !== "stack" && !skipErrorProperties.has(key)) {
|
|
1638
1676
|
errorObject[key] = e[key];
|
|
1639
1677
|
}
|
|
1640
1678
|
}
|
|
@@ -1681,6 +1719,7 @@ function printErrorMessage(error, logger) {
|
|
|
1681
1719
|
return;
|
|
1682
1720
|
}
|
|
1683
1721
|
if (error.message.length > 5e3) {
|
|
1722
|
+
// Protect against infinite stack trace in tinyrainbow
|
|
1684
1723
|
logger.error(`${c.red(c.bold(errorName))}: ${error.message}`);
|
|
1685
1724
|
} else {
|
|
1686
1725
|
logger.error(c.red(`${c.bold(errorName)}: ${error.message}`));
|
|
@@ -1703,6 +1742,7 @@ function printStack(logger, project, stack, highlight, errorProperties, onStack)
|
|
|
1703
1742
|
}
|
|
1704
1743
|
}
|
|
1705
1744
|
function hasProperties(obj) {
|
|
1745
|
+
// eslint-disable-next-line no-unreachable-loop
|
|
1706
1746
|
for (const _key in obj) {
|
|
1707
1747
|
return true;
|
|
1708
1748
|
}
|
|
@@ -1724,11 +1764,13 @@ function generateCodeFrame(source, indent = 0, loc, range = 2) {
|
|
|
1724
1764
|
continue;
|
|
1725
1765
|
}
|
|
1726
1766
|
const lineLength = lines[j].length;
|
|
1767
|
+
// too long, maybe it's a minified file, skip for codeframe
|
|
1727
1768
|
if (stripVTControlCharacters(lines[j]).length > 200) {
|
|
1728
1769
|
return "";
|
|
1729
1770
|
}
|
|
1730
1771
|
res.push(lineNo(j + 1) + truncateString(lines[j].replace(/\t/g, " "), columns - 5 - indent));
|
|
1731
1772
|
if (j === i) {
|
|
1773
|
+
// push underline
|
|
1732
1774
|
const pad = start - (count - lineLength) + (nl - 1);
|
|
1733
1775
|
const length = Math.max(1, end > count ? lineLength - pad : end - start);
|
|
1734
1776
|
res.push(lineNo() + " ".repeat(pad) + c.red("^".repeat(length)));
|
|
@@ -1754,10 +1796,15 @@ function lineNo(no = "") {
|
|
|
1754
1796
|
|
|
1755
1797
|
class GithubActionsReporter {
|
|
1756
1798
|
ctx = undefined;
|
|
1799
|
+
options;
|
|
1800
|
+
constructor(options = {}) {
|
|
1801
|
+
this.options = options;
|
|
1802
|
+
}
|
|
1757
1803
|
onInit(ctx) {
|
|
1758
1804
|
this.ctx = ctx;
|
|
1759
1805
|
}
|
|
1760
1806
|
onFinished(files = [], errors = []) {
|
|
1807
|
+
// collect all errors and associate them with projects
|
|
1761
1808
|
const projectErrors = new Array();
|
|
1762
1809
|
for (const error of errors) {
|
|
1763
1810
|
projectErrors.push({
|
|
@@ -1784,6 +1831,8 @@ class GithubActionsReporter {
|
|
|
1784
1831
|
}
|
|
1785
1832
|
}
|
|
1786
1833
|
}
|
|
1834
|
+
const onWritePath = this.options.onWritePath ?? defaultOnWritePath;
|
|
1835
|
+
// format errors via `printError`
|
|
1787
1836
|
for (const { project, title, error, file } of projectErrors) {
|
|
1788
1837
|
const result = capturePrintError(error, this.ctx, {
|
|
1789
1838
|
project,
|
|
@@ -1796,7 +1845,7 @@ class GithubActionsReporter {
|
|
|
1796
1845
|
const formatted = formatMessage({
|
|
1797
1846
|
command: "error",
|
|
1798
1847
|
properties: {
|
|
1799
|
-
file: stack.file,
|
|
1848
|
+
file: onWritePath(stack.file),
|
|
1800
1849
|
title,
|
|
1801
1850
|
line: String(stack.line),
|
|
1802
1851
|
column: String(stack.column)
|
|
@@ -1807,6 +1856,12 @@ class GithubActionsReporter {
|
|
|
1807
1856
|
}
|
|
1808
1857
|
}
|
|
1809
1858
|
}
|
|
1859
|
+
function defaultOnWritePath(path) {
|
|
1860
|
+
return path;
|
|
1861
|
+
}
|
|
1862
|
+
// workflow command formatting based on
|
|
1863
|
+
// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message
|
|
1864
|
+
// https://github.com/actions/toolkit/blob/f1d9b4b985e6f0f728b4b766db73498403fd5ca3/packages/core/src/command.ts#L80-L85
|
|
1810
1865
|
function formatMessage({ command, properties, message }) {
|
|
1811
1866
|
let result = `::${command}`;
|
|
1812
1867
|
Object.entries(properties).forEach(([k, v], i) => {
|
|
@@ -1976,16 +2031,18 @@ function flattenTasks$1(task, baseName = "") {
|
|
|
1976
2031
|
}];
|
|
1977
2032
|
}
|
|
1978
2033
|
}
|
|
2034
|
+
// https://gist.github.com/john-doherty/b9195065884cdbfd2017a4756e6409cc
|
|
1979
2035
|
function removeInvalidXMLCharacters(value, removeDiscouragedChars) {
|
|
1980
2036
|
let regex = /([\0-\x08\v\f\x0E-\x1F\uFFFD\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g;
|
|
1981
2037
|
value = String(value || "").replace(regex, "");
|
|
1982
2038
|
{
|
|
2039
|
+
// remove everything discouraged by XML 1.0 specifications
|
|
1983
2040
|
regex = new RegExp(
|
|
1984
2041
|
/* eslint-disable regexp/prefer-character-class, regexp/no-obscure-range, regexp/no-useless-non-capturing-group */
|
|
1985
2042
|
"([\\x7F-\\x84]|[\\x86-\\x9F]|[\\uFDD0-\\uFDEF]|\\uD83F[\\uDFFE\\uDFFF]|(?:\\uD87F[\\uDF" + "FE\\uDFFF])|\\uD8BF[\\uDFFE\\uDFFF]|\\uD8FF[\\uDFFE\\uDFFF]|(?:\\uD93F[\\uDFFE\\uD" + "FFF])|\\uD97F[\\uDFFE\\uDFFF]|\\uD9BF[\\uDFFE\\uDFFF]|\\uD9FF[\\uDFFE\\uDFFF]" + "|\\uDA3F[\\uDFFE\\uDFFF]|\\uDA7F[\\uDFFE\\uDFFF]|\\uDABF[\\uDFFE\\uDFFF]|(?:\\" + "uDAFF[\\uDFFE\\uDFFF])|\\uDB3F[\\uDFFE\\uDFFF]|\\uDB7F[\\uDFFE\\uDFFF]|(?:\\uDBBF" + "[\\uDFFE\\uDFFF])|\\uDBFF[\\uDFFE\\uDFFF](?:[\\0-\\t\\v\\f\\x0E-\\u2027\\u202A-\\uD7FF\\" + "uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|" + "(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))",
|
|
1986
2043
|
"g"
|
|
1987
2044
|
/* eslint-enable */
|
|
1988
|
-
);
|
|
2045
|
+
);
|
|
1989
2046
|
value = value.replace(regex, "");
|
|
1990
2047
|
}
|
|
1991
2048
|
return value;
|
|
@@ -2131,6 +2188,7 @@ class JUnitReporter {
|
|
|
2131
2188
|
failures: 0,
|
|
2132
2189
|
skipped: 0
|
|
2133
2190
|
});
|
|
2191
|
+
// inject failed suites to surface errors during beforeAll/afterAll
|
|
2134
2192
|
const suites = getSuites(file);
|
|
2135
2193
|
for (const suite of suites) {
|
|
2136
2194
|
if (suite.result?.errors) {
|
|
@@ -2138,6 +2196,7 @@ class JUnitReporter {
|
|
|
2138
2196
|
stats.failures += 1;
|
|
2139
2197
|
}
|
|
2140
2198
|
}
|
|
2199
|
+
// If there are no tests, but the file failed to load, we still want to report it as a failure
|
|
2141
2200
|
if (tasks.length === 0 && file.result?.state === "fail") {
|
|
2142
2201
|
stats.failures = 1;
|
|
2143
2202
|
tasks.push({
|
|
@@ -2228,6 +2287,7 @@ class TapReporter {
|
|
|
2228
2287
|
this.logger.log(`name: ${yamlString(String(errorName))}`);
|
|
2229
2288
|
this.logger.log(`message: ${yamlString(String(error.message))}`);
|
|
2230
2289
|
if (stack) {
|
|
2290
|
+
// For compatibility with tap-mocha-reporter
|
|
2231
2291
|
this.logger.log(`stack: ${yamlString(`${stack.file}:${stack.line}:${stack.column}`)}`);
|
|
2232
2292
|
}
|
|
2233
2293
|
}
|
|
@@ -2302,12 +2362,18 @@ class VerboseReporter extends DefaultReporter {
|
|
|
2302
2362
|
verbose = true;
|
|
2303
2363
|
renderSucceed = true;
|
|
2304
2364
|
printTestModule(module) {
|
|
2365
|
+
// still print the test module in TTY,
|
|
2366
|
+
// but don't print it in the CLI because we
|
|
2367
|
+
// print all the tests when they finish
|
|
2368
|
+
// instead of printing them when the test file finishes
|
|
2305
2369
|
if (this.isTTY) {
|
|
2306
2370
|
return super.printTestModule(module);
|
|
2307
2371
|
}
|
|
2308
2372
|
}
|
|
2309
2373
|
onTestCaseResult(test) {
|
|
2310
2374
|
super.onTestCaseResult(test);
|
|
2375
|
+
// don't print tests in TTY as they go, only print them
|
|
2376
|
+
// in the CLI when they finish
|
|
2311
2377
|
if (this.isTTY) {
|
|
2312
2378
|
return;
|
|
2313
2379
|
}
|
|
@@ -2346,6 +2412,7 @@ class VerboseReporter extends DefaultReporter {
|
|
|
2346
2412
|
return " ".repeat(getIndentation(test));
|
|
2347
2413
|
}
|
|
2348
2414
|
formatShortError() {
|
|
2415
|
+
// Short errors are not shown in tree-view
|
|
2349
2416
|
return "";
|
|
2350
2417
|
}
|
|
2351
2418
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as chai from 'chai';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
|
-
import { l as loadDiffConfig, b as loadSnapshotSerializers, t as takeCoverageInsideWorker } from './setup-common.
|
|
3
|
+
import { l as loadDiffConfig, b as loadSnapshotSerializers, t as takeCoverageInsideWorker } from './setup-common.CF-O-dZX.js';
|
|
4
4
|
import { distDir } from '../path.js';
|
|
5
|
-
import { r as rpc } from './rpc.
|
|
6
|
-
import { g as getWorkerState } from './utils.
|
|
5
|
+
import { r as rpc } from './rpc.BKExFSRG.js';
|
|
6
|
+
import { g as getWorkerState } from './utils.BlI4TC7Y.js';
|
|
7
7
|
|
|
8
8
|
function setupChaiConfig(config) {
|
|
9
9
|
Object.assign(chai.config, config);
|
|
@@ -11,7 +11,7 @@ function setupChaiConfig(config) {
|
|
|
11
11
|
|
|
12
12
|
async function resolveSnapshotEnvironment(config, executor) {
|
|
13
13
|
if (!config.snapshotEnvironment) {
|
|
14
|
-
const { VitestNodeSnapshotEnvironment } = await import('./node.
|
|
14
|
+
const { VitestNodeSnapshotEnvironment } = await import('./node.Be-ntJnD.js');
|
|
15
15
|
return new VitestNodeSnapshotEnvironment();
|
|
16
16
|
}
|
|
17
17
|
const mod = await executor.executeId(config.snapshotEnvironment);
|
|
@@ -36,6 +36,7 @@ async function getTestRunnerConstructor(config, executor) {
|
|
|
36
36
|
async function resolveTestRunner(config, executor) {
|
|
37
37
|
const TestRunner = await getTestRunnerConstructor(config, executor);
|
|
38
38
|
const testRunner = new TestRunner(config);
|
|
39
|
+
// inject private executor to every runner
|
|
39
40
|
Object.defineProperty(testRunner, "__vitest_executor", {
|
|
40
41
|
value: executor,
|
|
41
42
|
enumerable: false,
|
|
@@ -49,6 +50,7 @@ async function resolveTestRunner(config, executor) {
|
|
|
49
50
|
}
|
|
50
51
|
const [diffOptions] = await Promise.all([loadDiffConfig(config, executor), loadSnapshotSerializers(config, executor)]);
|
|
51
52
|
testRunner.config.diffOptions = diffOptions;
|
|
53
|
+
// patch some methods, so custom runners don't need to call RPC
|
|
52
54
|
const originalOnTaskUpdate = testRunner.onTaskUpdate;
|
|
53
55
|
testRunner.onTaskUpdate = async (task, events) => {
|
|
54
56
|
const p = rpc().onTaskUpdate(task, events);
|
|
@@ -66,6 +68,7 @@ async function resolveTestRunner(config, executor) {
|
|
|
66
68
|
files.forEach((file) => {
|
|
67
69
|
file.prepareDuration = state.durations.prepare;
|
|
68
70
|
file.environmentLoad = state.durations.environment;
|
|
71
|
+
// should be collected only for a single test file in a batch
|
|
69
72
|
state.durations.prepare = 0;
|
|
70
73
|
state.durations.environment = 0;
|
|
71
74
|
});
|