vitest 1.5.1 → 1.5.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/{integrations-globals.k0N5-dd1.js → integrations-globals.Hr6znn-f.js} +5 -4
- package/dist/chunks/{runtime-console.kbFEN7E-.js → runtime-console.EO5ha7qv.js} +3 -3
- package/dist/chunks/{runtime-runBaseTests.-x-nNuJ_.js → runtime-runBaseTests.l6qXp5eU.js} +11 -10
- package/dist/cli.js +1 -1
- package/dist/config.cjs +2 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -1
- package/dist/coverage.d.ts +1 -1
- package/dist/environments.d.ts +1 -1
- package/dist/execute.d.ts +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +6 -5
- package/dist/node.d.ts +2 -2
- package/dist/node.js +9 -8
- package/dist/{reporters-xEmem8D4.d.ts → reporters-BXNXFKfg.d.ts} +1 -2
- package/dist/reporters.d.ts +1 -1
- package/dist/reporters.js +8 -7
- package/dist/runners.d.ts +1 -1
- package/dist/runners.js +6 -5
- package/dist/{suite-HPAKvIxA.d.ts → suite-KPWE530F.d.ts} +1 -1
- package/dist/suite.d.ts +3 -3
- package/dist/suite.js +5 -4
- package/dist/vendor/{base.gAwDs8Jc.js → base.oIzAvGLe.js} +1 -1
- package/dist/vendor/{benchmark.eeqk2rd8.js → benchmark.yGkUTKnC.js} +1 -1
- package/dist/vendor/{cac.4YOY8W-L.js → cac.RDd_SGOd.js} +2 -2
- package/dist/vendor/{cli-api.5cFYj0Lq.js → cli-api.AmIc1Dmz.js} +21 -10
- package/dist/vendor/env.AtSIuHFg.js +7 -0
- package/dist/vendor/{index.gHZzsRJQ.js → index.Fm6OikHU.js} +1 -1
- package/dist/vendor/{index.0RrMQKD8.js → index.QVcwRDVW.js} +1 -1
- package/dist/vendor/{index.ir9i0ywP.js → index.SMVOaj7F.js} +2 -6
- package/dist/vendor/{index.waF5pgqJ.js → index.X7lgIMc_.js} +519 -529
- package/dist/vendor/{setup-common.7SXMSI--.js → setup-common.5nUd4r76.js} +1 -1
- package/dist/vendor/{vm.I_IsyNig.js → vm.i4FO5N37.js} +4 -2
- package/dist/workers/forks.js +1 -1
- package/dist/workers/runVmTests.js +6 -5
- package/dist/workers/threads.js +1 -1
- package/dist/workers/vmForks.js +4 -4
- package/dist/workers/vmThreads.js +4 -4
- package/dist/workers.d.ts +1 -1
- package/dist/workers.js +5 -5
- package/package.json +9 -9
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { existsSync, promises, readFileSync } from 'node:fs';
|
|
2
2
|
import { basename, dirname, resolve, join, relative, extname, normalize } from 'pathe';
|
|
3
|
-
import { a as isNode, r as relativePath } from './index.ir9i0ywP.js';
|
|
4
3
|
import { generateHash, calculateSuiteHash, someTasksAreOnly, interpretTaskModes, getTasks, getTests, hasFailed, getSuites } from '@vitest/runner/utils';
|
|
4
|
+
import { getSafeTimers, notNullish, highlight, shuffle, inspect, positionToOffset, lineSplitRE } from '@vitest/utils';
|
|
5
|
+
import { i as isNode } from './env.AtSIuHFg.js';
|
|
5
6
|
import c from 'picocolors';
|
|
6
|
-
import { g as getStateSymbol, f as formatProjectName, p as pointer, F as F_RIGHT, r as renderSnapshotSummary, a as getStateString, b as formatTimeString, c as countTestErrors, d as divider, s as stripAnsi, e as getCols, h as getHookStateSymbol, i as F_POINTER } from './utils.VYmeMh-u.js';
|
|
7
|
-
import { getSafeTimers, notNullish, inspect, positionToOffset, lineSplitRE, highlight, shuffle } from '@vitest/utils';
|
|
8
7
|
import { g as getFullName, h as hasFailedSnapshot } from './tasks.IknbGB2n.js';
|
|
8
|
+
import { g as getStateSymbol, f as formatProjectName, p as pointer, F as F_RIGHT, r as renderSnapshotSummary, a as getStateString, b as formatTimeString, c as countTestErrors, d as divider, s as stripAnsi, e as getCols, h as getHookStateSymbol, i as F_POINTER } from './utils.VYmeMh-u.js';
|
|
9
9
|
import { performance } from 'node:perf_hooks';
|
|
10
|
-
import {
|
|
10
|
+
import { r as relativePath } from './index.SMVOaj7F.js';
|
|
11
|
+
import { UNKNOWN_TEST_ID } from '../chunks/runtime-console.EO5ha7qv.js';
|
|
11
12
|
import { t as toArray, b as isPrimitive } from './base.Xt0Omgh7.js';
|
|
12
13
|
import { isCI } from 'std-env';
|
|
13
14
|
import { TraceMap, generatedPositionFor, parseErrorStacktrace } from '@vitest/utils/source-map';
|
|
14
15
|
import nodeos__default, { hostname } from 'node:os';
|
|
15
|
-
import { createRequire } from 'node:module';
|
|
16
16
|
import { Writable } from 'node:stream';
|
|
17
17
|
import { writeFile, rm } from 'node:fs/promises';
|
|
18
18
|
import { execa } from 'execa';
|
|
@@ -29,6 +29,7 @@ import require$$0$2 from 'assert';
|
|
|
29
29
|
import require$$0$1 from 'events';
|
|
30
30
|
import { createHash } from 'node:crypto';
|
|
31
31
|
import { slash } from 'vite-node/utils';
|
|
32
|
+
import { createRequire } from 'node:module';
|
|
32
33
|
|
|
33
34
|
const REGEXP_WRAP_PREFIX = "$$vitest:";
|
|
34
35
|
function getOutputFile(config, reporter) {
|
|
@@ -2454,499 +2455,13 @@ class TapReporter {
|
|
|
2454
2455
|
}
|
|
2455
2456
|
}
|
|
2456
2457
|
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
return [{
|
|
2463
|
-
...task,
|
|
2464
|
-
name: `${base}${task.name}`
|
|
2465
|
-
}];
|
|
2466
|
-
}
|
|
2467
|
-
}
|
|
2468
|
-
function removeInvalidXMLCharacters(value, removeDiscouragedChars) {
|
|
2469
|
-
let regex = /((?:[\0-\x08\x0B\f\x0E-\x1F\uFFFD\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/g;
|
|
2470
|
-
value = String(value || "").replace(regex, "");
|
|
2471
|
-
if (removeDiscouragedChars) {
|
|
2472
|
-
regex = new RegExp(
|
|
2473
|
-
"([\\x7F-\\x84]|[\\x86-\\x9F]|[\\uFDD0-\\uFDEF]|(?:\\uD83F[\\uDFFE\\uDFFF])|(?:\\uD87F[\\uDFFE\\uDFFF])|(?:\\uD8BF[\\uDFFE\\uDFFF])|(?:\\uD8FF[\\uDFFE\\uDFFF])|(?:\\uD93F[\\uDFFE\\uDFFF])|(?:\\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\\x0B\\f\\x0E-\\u2027\\u202A-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))",
|
|
2474
|
-
"g"
|
|
2475
|
-
);
|
|
2476
|
-
value = value.replace(regex, "");
|
|
2477
|
-
}
|
|
2478
|
-
return value;
|
|
2479
|
-
}
|
|
2480
|
-
function escapeXML(value) {
|
|
2481
|
-
return removeInvalidXMLCharacters(
|
|
2482
|
-
String(value).replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">"),
|
|
2483
|
-
true
|
|
2484
|
-
);
|
|
2485
|
-
}
|
|
2486
|
-
function executionTime(durationMS) {
|
|
2487
|
-
return (durationMS / 1e3).toLocaleString("en-US", { useGrouping: false, maximumFractionDigits: 10 });
|
|
2488
|
-
}
|
|
2489
|
-
function getDuration(task) {
|
|
2490
|
-
var _a;
|
|
2491
|
-
const duration = ((_a = task.result) == null ? void 0 : _a.duration) ?? 0;
|
|
2492
|
-
return executionTime(duration);
|
|
2493
|
-
}
|
|
2494
|
-
class JUnitReporter {
|
|
2495
|
-
ctx;
|
|
2496
|
-
reportFile;
|
|
2497
|
-
baseLog;
|
|
2498
|
-
logger;
|
|
2499
|
-
_timeStart = /* @__PURE__ */ new Date();
|
|
2500
|
-
fileFd;
|
|
2501
|
-
options;
|
|
2502
|
-
constructor(options) {
|
|
2503
|
-
this.options = options;
|
|
2504
|
-
}
|
|
2505
|
-
async onInit(ctx) {
|
|
2506
|
-
this.ctx = ctx;
|
|
2507
|
-
const outputFile = this.options.outputFile ?? getOutputFile(this.ctx.config, "junit");
|
|
2508
|
-
if (outputFile) {
|
|
2509
|
-
this.reportFile = resolve(this.ctx.config.root, outputFile);
|
|
2510
|
-
const outputDirectory = dirname(this.reportFile);
|
|
2511
|
-
if (!existsSync(outputDirectory))
|
|
2512
|
-
await promises.mkdir(outputDirectory, { recursive: true });
|
|
2513
|
-
const fileFd = await promises.open(this.reportFile, "w+");
|
|
2514
|
-
this.fileFd = fileFd;
|
|
2515
|
-
this.baseLog = async (text) => {
|
|
2516
|
-
if (!this.fileFd)
|
|
2517
|
-
this.fileFd = await promises.open(this.reportFile, "w+");
|
|
2518
|
-
await promises.writeFile(this.fileFd, `${text}
|
|
2519
|
-
`);
|
|
2520
|
-
};
|
|
2521
|
-
} else {
|
|
2522
|
-
this.baseLog = async (text) => this.ctx.logger.log(text);
|
|
2523
|
-
}
|
|
2524
|
-
this._timeStart = /* @__PURE__ */ new Date();
|
|
2525
|
-
this.logger = new IndentedLogger(this.baseLog);
|
|
2526
|
-
}
|
|
2527
|
-
async writeElement(name, attrs, children) {
|
|
2528
|
-
const pairs = [];
|
|
2529
|
-
for (const key in attrs) {
|
|
2530
|
-
const attr = attrs[key];
|
|
2531
|
-
if (attr === void 0)
|
|
2532
|
-
continue;
|
|
2533
|
-
pairs.push(`${key}="${escapeXML(attr)}"`);
|
|
2534
|
-
}
|
|
2535
|
-
await this.logger.log(`<${name}${pairs.length ? ` ${pairs.join(" ")}` : ""}>`);
|
|
2536
|
-
this.logger.indent();
|
|
2537
|
-
await children.call(this);
|
|
2538
|
-
this.logger.unindent();
|
|
2539
|
-
await this.logger.log(`</${name}>`);
|
|
2540
|
-
}
|
|
2541
|
-
async writeErrorDetails(task, error) {
|
|
2542
|
-
const errorName = error.name ?? error.nameStr ?? "Unknown Error";
|
|
2543
|
-
const errorDetails = `${errorName}: ${error.message}`;
|
|
2544
|
-
await this.baseLog(escapeXML(errorDetails));
|
|
2545
|
-
const project = this.ctx.getProjectByTaskId(task.id);
|
|
2546
|
-
const stack = parseErrorStacktrace(error, {
|
|
2547
|
-
getSourceMap: (file) => project.getBrowserSourceMapModuleById(file),
|
|
2548
|
-
frameFilter: this.ctx.config.onStackTrace
|
|
2549
|
-
});
|
|
2550
|
-
for (const frame of stack) {
|
|
2551
|
-
const path = relative(this.ctx.config.root, frame.file);
|
|
2552
|
-
await this.baseLog(escapeXML(` ${F_POINTER} ${[frame.method, `${path}:${frame.line}:${frame.column}`].filter(Boolean).join(" ")}`));
|
|
2553
|
-
if (frame.file in this.ctx.state.filesMap)
|
|
2554
|
-
break;
|
|
2555
|
-
}
|
|
2556
|
-
}
|
|
2557
|
-
async writeLogs(task, type) {
|
|
2558
|
-
if (task.logs == null || task.logs.length === 0)
|
|
2559
|
-
return;
|
|
2560
|
-
const logType = type === "err" ? "stderr" : "stdout";
|
|
2561
|
-
const logs = task.logs.filter((log) => log.type === logType);
|
|
2562
|
-
if (logs.length === 0)
|
|
2563
|
-
return;
|
|
2564
|
-
await this.writeElement(`system-${type}`, {}, async () => {
|
|
2565
|
-
for (const log of logs)
|
|
2566
|
-
await this.baseLog(escapeXML(log.content));
|
|
2567
|
-
});
|
|
2568
|
-
}
|
|
2569
|
-
async writeTasks(tasks, filename) {
|
|
2570
|
-
for (const task of tasks) {
|
|
2571
|
-
await this.writeElement("testcase", {
|
|
2572
|
-
// TODO: v2.0.0 Remove env variable in favor of custom reporter options, e.g. "reporters: [['json', { classname: 'something' }]]"
|
|
2573
|
-
classname: this.options.classname ?? process.env.VITEST_JUNIT_CLASSNAME ?? filename,
|
|
2574
|
-
name: task.name,
|
|
2575
|
-
time: getDuration(task)
|
|
2576
|
-
}, async () => {
|
|
2577
|
-
var _a;
|
|
2578
|
-
await this.writeLogs(task, "out");
|
|
2579
|
-
await this.writeLogs(task, "err");
|
|
2580
|
-
if (task.mode === "skip" || task.mode === "todo")
|
|
2581
|
-
await this.logger.log("<skipped/>");
|
|
2582
|
-
if (((_a = task.result) == null ? void 0 : _a.state) === "fail") {
|
|
2583
|
-
const errors = task.result.errors || [];
|
|
2584
|
-
for (const error of errors) {
|
|
2585
|
-
await this.writeElement("failure", {
|
|
2586
|
-
message: error == null ? void 0 : error.message,
|
|
2587
|
-
type: (error == null ? void 0 : error.name) ?? (error == null ? void 0 : error.nameStr)
|
|
2588
|
-
}, async () => {
|
|
2589
|
-
if (!error)
|
|
2590
|
-
return;
|
|
2591
|
-
await this.writeErrorDetails(task, error);
|
|
2592
|
-
});
|
|
2593
|
-
}
|
|
2594
|
-
}
|
|
2595
|
-
});
|
|
2596
|
-
}
|
|
2597
|
-
}
|
|
2598
|
-
async onFinished(files = this.ctx.state.getFiles()) {
|
|
2599
|
-
var _a;
|
|
2600
|
-
await this.logger.log('<?xml version="1.0" encoding="UTF-8" ?>');
|
|
2601
|
-
const transformed = files.map((file) => {
|
|
2602
|
-
var _a2, _b;
|
|
2603
|
-
const tasks = file.tasks.flatMap((task) => flattenTasks$1(task));
|
|
2604
|
-
const stats2 = tasks.reduce((stats3, task) => {
|
|
2605
|
-
var _a3, _b2;
|
|
2606
|
-
return {
|
|
2607
|
-
passed: stats3.passed + Number(((_a3 = task.result) == null ? void 0 : _a3.state) === "pass"),
|
|
2608
|
-
failures: stats3.failures + Number(((_b2 = task.result) == null ? void 0 : _b2.state) === "fail"),
|
|
2609
|
-
skipped: stats3.skipped + Number(task.mode === "skip" || task.mode === "todo")
|
|
2610
|
-
};
|
|
2611
|
-
}, {
|
|
2612
|
-
passed: 0,
|
|
2613
|
-
failures: 0,
|
|
2614
|
-
skipped: 0
|
|
2615
|
-
});
|
|
2616
|
-
const suites = getSuites(file);
|
|
2617
|
-
for (const suite of suites) {
|
|
2618
|
-
if ((_a2 = suite.result) == null ? void 0 : _a2.errors) {
|
|
2619
|
-
tasks.push(suite);
|
|
2620
|
-
stats2.failures += 1;
|
|
2621
|
-
}
|
|
2622
|
-
}
|
|
2623
|
-
if (tasks.length === 0 && ((_b = file.result) == null ? void 0 : _b.state) === "fail") {
|
|
2624
|
-
stats2.failures = 1;
|
|
2625
|
-
tasks.push({
|
|
2626
|
-
id: file.id,
|
|
2627
|
-
type: "test",
|
|
2628
|
-
name: file.name,
|
|
2629
|
-
mode: "run",
|
|
2630
|
-
result: file.result,
|
|
2631
|
-
meta: {},
|
|
2632
|
-
// NOTE: not used in JUnitReporter
|
|
2633
|
-
context: null,
|
|
2634
|
-
suite: null
|
|
2635
|
-
});
|
|
2636
|
-
}
|
|
2637
|
-
return {
|
|
2638
|
-
...file,
|
|
2639
|
-
tasks,
|
|
2640
|
-
stats: stats2
|
|
2641
|
-
};
|
|
2642
|
-
});
|
|
2643
|
-
const stats = transformed.reduce((stats2, file) => {
|
|
2644
|
-
stats2.tests += file.tasks.length;
|
|
2645
|
-
stats2.failures += file.stats.failures;
|
|
2646
|
-
return stats2;
|
|
2647
|
-
}, {
|
|
2648
|
-
// TODO: v2.0.0 Remove env variable in favor of custom reporter options, e.g. "reporters: [['json', { suiteName: 'something' }]]"
|
|
2649
|
-
name: this.options.suiteName || process.env.VITEST_JUNIT_SUITE_NAME || "vitest tests",
|
|
2650
|
-
tests: 0,
|
|
2651
|
-
failures: 0,
|
|
2652
|
-
errors: 0,
|
|
2653
|
-
// we cannot detect those
|
|
2654
|
-
time: executionTime((/* @__PURE__ */ new Date()).getTime() - this._timeStart.getTime())
|
|
2655
|
-
});
|
|
2656
|
-
await this.writeElement("testsuites", stats, async () => {
|
|
2657
|
-
for (const file of transformed) {
|
|
2658
|
-
await this.writeElement("testsuite", {
|
|
2659
|
-
name: relative(this.ctx.config.root, file.filepath),
|
|
2660
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2661
|
-
hostname: hostname(),
|
|
2662
|
-
tests: file.tasks.length,
|
|
2663
|
-
failures: file.stats.failures,
|
|
2664
|
-
errors: 0,
|
|
2665
|
-
// An errored test is one that had an unanticipated problem. We cannot detect those.
|
|
2666
|
-
skipped: file.stats.skipped,
|
|
2667
|
-
time: getDuration(file)
|
|
2668
|
-
}, async () => {
|
|
2669
|
-
await this.writeTasks(file.tasks, file.name);
|
|
2670
|
-
});
|
|
2671
|
-
}
|
|
2672
|
-
});
|
|
2673
|
-
if (this.reportFile)
|
|
2674
|
-
this.ctx.logger.log(`JUNIT report written to ${this.reportFile}`);
|
|
2675
|
-
await ((_a = this.fileFd) == null ? void 0 : _a.close());
|
|
2676
|
-
this.fileFd = void 0;
|
|
2677
|
-
}
|
|
2678
|
-
}
|
|
2679
|
-
|
|
2680
|
-
function flattenTasks(task, baseName = "") {
|
|
2681
|
-
const base = baseName ? `${baseName} > ` : "";
|
|
2682
|
-
if (task.type === "suite" && task.tasks.length > 0) {
|
|
2683
|
-
return task.tasks.flatMap((child) => flattenTasks(child, `${base}${task.name}`));
|
|
2684
|
-
} else {
|
|
2685
|
-
return [{
|
|
2686
|
-
...task,
|
|
2687
|
-
name: `${base}${task.name}`
|
|
2688
|
-
}];
|
|
2689
|
-
}
|
|
2690
|
-
}
|
|
2691
|
-
class TapFlatReporter extends TapReporter {
|
|
2692
|
-
onInit(ctx) {
|
|
2693
|
-
super.onInit(ctx);
|
|
2694
|
-
}
|
|
2695
|
-
async onFinished(files = this.ctx.state.getFiles()) {
|
|
2696
|
-
this.ctx.logger.log("TAP version 13");
|
|
2697
|
-
const flatTasks = files.flatMap((task) => flattenTasks(task));
|
|
2698
|
-
this.logTasks(flatTasks);
|
|
2699
|
-
}
|
|
2700
|
-
}
|
|
2458
|
+
const ESC$1 = '\u001B[';
|
|
2459
|
+
const OSC = '\u001B]';
|
|
2460
|
+
const BEL = '\u0007';
|
|
2461
|
+
const SEP = ';';
|
|
2462
|
+
const isTerminalApp = process.env.TERM_PROGRAM === 'Apple_Terminal';
|
|
2701
2463
|
|
|
2702
|
-
|
|
2703
|
-
whyRunning;
|
|
2704
|
-
onInit() {
|
|
2705
|
-
const _require = createRequire(import.meta.url);
|
|
2706
|
-
this.whyRunning = _require("why-is-node-running");
|
|
2707
|
-
}
|
|
2708
|
-
onProcessTimeout() {
|
|
2709
|
-
var _a;
|
|
2710
|
-
(_a = this.whyRunning) == null ? void 0 : _a.call(this);
|
|
2711
|
-
}
|
|
2712
|
-
}
|
|
2713
|
-
|
|
2714
|
-
async function printError(error, project, options) {
|
|
2715
|
-
const { showCodeFrame = true, fullStack = false, type } = options;
|
|
2716
|
-
const logger = options.logger;
|
|
2717
|
-
let e = error;
|
|
2718
|
-
if (isPrimitive(e)) {
|
|
2719
|
-
e = {
|
|
2720
|
-
message: String(error).split(/\n/g)[0],
|
|
2721
|
-
stack: String(error)
|
|
2722
|
-
};
|
|
2723
|
-
}
|
|
2724
|
-
if (!e) {
|
|
2725
|
-
const error2 = new Error("unknown error");
|
|
2726
|
-
e = {
|
|
2727
|
-
message: e ?? error2.message,
|
|
2728
|
-
stack: error2.stack
|
|
2729
|
-
};
|
|
2730
|
-
}
|
|
2731
|
-
if (!project) {
|
|
2732
|
-
printErrorMessage(e, logger);
|
|
2733
|
-
return;
|
|
2734
|
-
}
|
|
2735
|
-
const parserOptions = {
|
|
2736
|
-
// only browser stack traces require remapping
|
|
2737
|
-
getSourceMap: (file) => project.getBrowserSourceMapModuleById(file),
|
|
2738
|
-
frameFilter: project.config.onStackTrace
|
|
2739
|
-
};
|
|
2740
|
-
if (fullStack)
|
|
2741
|
-
parserOptions.ignoreStackEntries = [];
|
|
2742
|
-
const stacks = parseErrorStacktrace(e, parserOptions);
|
|
2743
|
-
const nearest = error instanceof TypeCheckError ? error.stacks[0] : stacks.find(
|
|
2744
|
-
(stack) => {
|
|
2745
|
-
try {
|
|
2746
|
-
return project.server && project.getModuleById(stack.file) && existsSync(stack.file);
|
|
2747
|
-
} catch {
|
|
2748
|
-
return false;
|
|
2749
|
-
}
|
|
2750
|
-
}
|
|
2751
|
-
);
|
|
2752
|
-
const errorProperties = getErrorProperties(e);
|
|
2753
|
-
if (type)
|
|
2754
|
-
printErrorType(type, project.ctx);
|
|
2755
|
-
printErrorMessage(e, logger);
|
|
2756
|
-
if (e.codeFrame)
|
|
2757
|
-
logger.error(`${e.codeFrame}
|
|
2758
|
-
`);
|
|
2759
|
-
if (e.diff)
|
|
2760
|
-
displayDiff(e.diff, logger.console);
|
|
2761
|
-
if (e.frame) {
|
|
2762
|
-
logger.error(c.yellow(e.frame));
|
|
2763
|
-
} else {
|
|
2764
|
-
printStack(logger, project, stacks, nearest, errorProperties, (s) => {
|
|
2765
|
-
if (showCodeFrame && s === nearest && nearest) {
|
|
2766
|
-
const sourceCode = readFileSync(nearest.file, "utf-8");
|
|
2767
|
-
logger.error(generateCodeFrame(sourceCode.length > 1e5 ? sourceCode : logger.highlight(nearest.file, sourceCode), 4, s));
|
|
2768
|
-
}
|
|
2769
|
-
});
|
|
2770
|
-
}
|
|
2771
|
-
const testPath = e.VITEST_TEST_PATH;
|
|
2772
|
-
const testName = e.VITEST_TEST_NAME;
|
|
2773
|
-
const afterEnvTeardown = e.VITEST_AFTER_ENV_TEARDOWN;
|
|
2774
|
-
if (testPath)
|
|
2775
|
-
logger.error(c.red(`This error originated in "${c.bold(testPath)}" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.`));
|
|
2776
|
-
if (testName) {
|
|
2777
|
-
logger.error(c.red(`The latest test that might've caused the error is "${c.bold(testName)}". It might mean one of the following:
|
|
2778
|
-
- The error was thrown, while Vitest was running this test.
|
|
2779
|
-
- If the error occurred after the test had been completed, this was the last documented test before it was thrown.`));
|
|
2780
|
-
}
|
|
2781
|
-
if (afterEnvTeardown) {
|
|
2782
|
-
logger.error(c.red("This error was caught after test environment was torn down. Make sure to cancel any running tasks before test finishes:\n- cancel timeouts using clearTimeout and clearInterval\n- wait for promises to resolve using the await keyword"));
|
|
2783
|
-
}
|
|
2784
|
-
if (typeof e.cause === "object" && e.cause && "name" in e.cause) {
|
|
2785
|
-
e.cause.name = `Caused by: ${e.cause.name}`;
|
|
2786
|
-
await printError(e.cause, project, { fullStack, showCodeFrame: false, logger: options.logger });
|
|
2787
|
-
}
|
|
2788
|
-
handleImportOutsideModuleError(e.stack || e.stackStr || "", logger);
|
|
2789
|
-
return { nearest };
|
|
2790
|
-
}
|
|
2791
|
-
function printErrorType(type, ctx) {
|
|
2792
|
-
ctx.logger.error(`
|
|
2793
|
-
${c.red(divider(c.bold(c.inverse(` ${type} `))))}`);
|
|
2794
|
-
}
|
|
2795
|
-
const skipErrorProperties = /* @__PURE__ */ new Set([
|
|
2796
|
-
"nameStr",
|
|
2797
|
-
"stack",
|
|
2798
|
-
"cause",
|
|
2799
|
-
"stacks",
|
|
2800
|
-
"stackStr",
|
|
2801
|
-
"type",
|
|
2802
|
-
"showDiff",
|
|
2803
|
-
"diff",
|
|
2804
|
-
"codeFrame",
|
|
2805
|
-
"actual",
|
|
2806
|
-
"expected",
|
|
2807
|
-
"diffOptions",
|
|
2808
|
-
"VITEST_TEST_NAME",
|
|
2809
|
-
"VITEST_TEST_PATH",
|
|
2810
|
-
"VITEST_AFTER_ENV_TEARDOWN",
|
|
2811
|
-
...Object.getOwnPropertyNames(Error.prototype),
|
|
2812
|
-
...Object.getOwnPropertyNames(Object.prototype)
|
|
2813
|
-
]);
|
|
2814
|
-
function getErrorProperties(e) {
|
|
2815
|
-
const errorObject = /* @__PURE__ */ Object.create(null);
|
|
2816
|
-
if (e.name === "AssertionError")
|
|
2817
|
-
return errorObject;
|
|
2818
|
-
for (const key of Object.getOwnPropertyNames(e)) {
|
|
2819
|
-
if (!skipErrorProperties.has(key))
|
|
2820
|
-
errorObject[key] = e[key];
|
|
2821
|
-
}
|
|
2822
|
-
return errorObject;
|
|
2823
|
-
}
|
|
2824
|
-
const esmErrors = [
|
|
2825
|
-
"Cannot use import statement outside a module",
|
|
2826
|
-
"Unexpected token 'export'"
|
|
2827
|
-
];
|
|
2828
|
-
function handleImportOutsideModuleError(stack, logger) {
|
|
2829
|
-
if (!esmErrors.some((e) => stack.includes(e)))
|
|
2830
|
-
return;
|
|
2831
|
-
const path = normalize(stack.split("\n")[0].trim());
|
|
2832
|
-
let name = path.split("/node_modules/").pop() || "";
|
|
2833
|
-
if (name == null ? void 0 : name.startsWith("@"))
|
|
2834
|
-
name = name.split("/").slice(0, 2).join("/");
|
|
2835
|
-
else
|
|
2836
|
-
name = name.split("/")[0];
|
|
2837
|
-
if (name)
|
|
2838
|
-
printModuleWarningForPackage(logger, path, name);
|
|
2839
|
-
else
|
|
2840
|
-
printModuleWarningForSourceCode(logger, path);
|
|
2841
|
-
}
|
|
2842
|
-
function printModuleWarningForPackage(logger, path, name) {
|
|
2843
|
-
logger.error(c.yellow(
|
|
2844
|
-
`Module ${path} seems to be an ES Module but shipped in a CommonJS package. You might want to create an issue to the package ${c.bold(`"${name}"`)} asking them to ship the file in .mjs extension or add "type": "module" in their package.json.
|
|
2845
|
-
|
|
2846
|
-
As a temporary workaround you can try to inline the package by updating your config:
|
|
2847
|
-
|
|
2848
|
-
` + c.gray(c.dim("// vitest.config.js")) + "\n" + c.green(`export default {
|
|
2849
|
-
test: {
|
|
2850
|
-
server: {
|
|
2851
|
-
deps: {
|
|
2852
|
-
inline: [
|
|
2853
|
-
${c.yellow(c.bold(`"${name}"`))}
|
|
2854
|
-
]
|
|
2855
|
-
}
|
|
2856
|
-
}
|
|
2857
|
-
}
|
|
2858
|
-
}
|
|
2859
|
-
`)
|
|
2860
|
-
));
|
|
2861
|
-
}
|
|
2862
|
-
function printModuleWarningForSourceCode(logger, path) {
|
|
2863
|
-
logger.error(c.yellow(
|
|
2864
|
-
`Module ${path} seems to be an ES Module but shipped in a CommonJS package. To fix this issue, change the file extension to .mjs or add "type": "module" in your package.json.`
|
|
2865
|
-
));
|
|
2866
|
-
}
|
|
2867
|
-
function displayDiff(diff, console) {
|
|
2868
|
-
if (diff)
|
|
2869
|
-
console.error(`
|
|
2870
|
-
${diff}
|
|
2871
|
-
`);
|
|
2872
|
-
}
|
|
2873
|
-
function printErrorMessage(error, logger) {
|
|
2874
|
-
const errorName = error.name || error.nameStr || "Unknown Error";
|
|
2875
|
-
if (!error.message) {
|
|
2876
|
-
logger.error(error);
|
|
2877
|
-
return;
|
|
2878
|
-
}
|
|
2879
|
-
if (error.message.length > 5e3) {
|
|
2880
|
-
logger.error(`${c.red(c.bold(errorName))}: ${error.message}`);
|
|
2881
|
-
} else {
|
|
2882
|
-
logger.error(c.red(`${c.bold(errorName)}: ${error.message}`));
|
|
2883
|
-
}
|
|
2884
|
-
}
|
|
2885
|
-
function printStack(logger, project, stack, highlight, errorProperties, onStack) {
|
|
2886
|
-
for (const frame of stack) {
|
|
2887
|
-
const color = frame === highlight ? c.cyan : c.gray;
|
|
2888
|
-
const path = relative(project.config.root, frame.file);
|
|
2889
|
-
logger.error(color(` ${c.dim(F_POINTER)} ${[frame.method, `${path}:${c.dim(`${frame.line}:${frame.column}`)}`].filter(Boolean).join(" ")}`));
|
|
2890
|
-
onStack == null ? void 0 : onStack(frame);
|
|
2891
|
-
}
|
|
2892
|
-
if (stack.length)
|
|
2893
|
-
logger.error();
|
|
2894
|
-
const hasProperties = Object.keys(errorProperties).length > 0;
|
|
2895
|
-
if (hasProperties) {
|
|
2896
|
-
logger.error(c.red(c.dim(divider())));
|
|
2897
|
-
const propertiesString = inspect(errorProperties);
|
|
2898
|
-
logger.error(c.red(c.bold("Serialized Error:")), c.gray(propertiesString));
|
|
2899
|
-
}
|
|
2900
|
-
}
|
|
2901
|
-
function generateCodeFrame(source, indent = 0, loc, range = 2) {
|
|
2902
|
-
var _a;
|
|
2903
|
-
const start = typeof loc === "object" ? positionToOffset(source, loc.line, loc.column) : loc;
|
|
2904
|
-
const end = start;
|
|
2905
|
-
const lines = source.split(lineSplitRE);
|
|
2906
|
-
const nl = /\r\n/.test(source) ? 2 : 1;
|
|
2907
|
-
let count = 0;
|
|
2908
|
-
let res = [];
|
|
2909
|
-
const columns = ((_a = process.stdout) == null ? void 0 : _a.columns) || 80;
|
|
2910
|
-
function lineNo(no = "") {
|
|
2911
|
-
return c.gray(`${String(no).padStart(3, " ")}| `);
|
|
2912
|
-
}
|
|
2913
|
-
for (let i = 0; i < lines.length; i++) {
|
|
2914
|
-
count += lines[i].length + nl;
|
|
2915
|
-
if (count >= start) {
|
|
2916
|
-
for (let j = i - range; j <= i + range || end > count; j++) {
|
|
2917
|
-
if (j < 0 || j >= lines.length)
|
|
2918
|
-
continue;
|
|
2919
|
-
const lineLength = lines[j].length;
|
|
2920
|
-
if (stripAnsi(lines[j]).length > 200)
|
|
2921
|
-
return "";
|
|
2922
|
-
res.push(lineNo(j + 1) + cliTruncate(lines[j].replace(/\t/g, " "), columns - 5 - indent));
|
|
2923
|
-
if (j === i) {
|
|
2924
|
-
const pad = start - (count - lineLength) + (nl - 1);
|
|
2925
|
-
const length = Math.max(1, end > count ? lineLength - pad : end - start);
|
|
2926
|
-
res.push(lineNo() + " ".repeat(pad) + c.red("^".repeat(length)));
|
|
2927
|
-
} else if (j > i) {
|
|
2928
|
-
if (end > count) {
|
|
2929
|
-
const length = Math.max(1, Math.min(end - count, lineLength));
|
|
2930
|
-
res.push(lineNo() + c.red("^".repeat(length)));
|
|
2931
|
-
}
|
|
2932
|
-
count += lineLength + 1;
|
|
2933
|
-
}
|
|
2934
|
-
}
|
|
2935
|
-
break;
|
|
2936
|
-
}
|
|
2937
|
-
}
|
|
2938
|
-
if (indent)
|
|
2939
|
-
res = res.map((line) => " ".repeat(indent) + line);
|
|
2940
|
-
return res.join("\n");
|
|
2941
|
-
}
|
|
2942
|
-
|
|
2943
|
-
const ESC$1 = '\u001B[';
|
|
2944
|
-
const OSC = '\u001B]';
|
|
2945
|
-
const BEL = '\u0007';
|
|
2946
|
-
const SEP = ';';
|
|
2947
|
-
const isTerminalApp = process.env.TERM_PROGRAM === 'Apple_Terminal';
|
|
2948
|
-
|
|
2949
|
-
const ansiEscapes = {};
|
|
2464
|
+
const ansiEscapes = {};
|
|
2950
2465
|
|
|
2951
2466
|
ansiEscapes.cursorTo = (x, y) => {
|
|
2952
2467
|
if (typeof x !== 'number') {
|
|
@@ -4139,7 +3654,7 @@ createLogUpdate(process$2.stdout);
|
|
|
4139
3654
|
|
|
4140
3655
|
createLogUpdate(process$2.stderr);
|
|
4141
3656
|
|
|
4142
|
-
var version = "1.5.
|
|
3657
|
+
var version = "1.5.3";
|
|
4143
3658
|
|
|
4144
3659
|
const HIGHLIGHT_SUPPORTED_EXTS = new Set(["js", "ts"].flatMap((lang) => [
|
|
4145
3660
|
`.${lang}`,
|
|
@@ -4379,23 +3894,512 @@ Vitest found ${errors.length} error${errors.length > 1 ? "s" : ""} not related t
|
|
|
4379
3894
|
}
|
|
4380
3895
|
}
|
|
4381
3896
|
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
var _a, _b;
|
|
4389
|
-
const projectErrors = new Array();
|
|
4390
|
-
for (const error of errors) {
|
|
4391
|
-
projectErrors.push({
|
|
4392
|
-
project: this.ctx.getCoreWorkspaceProject(),
|
|
4393
|
-
title: "Unhandled error",
|
|
4394
|
-
error
|
|
4395
|
-
});
|
|
3897
|
+
async function captuerPrintError(error, ctx, project) {
|
|
3898
|
+
let output = "";
|
|
3899
|
+
const writable = new Writable({
|
|
3900
|
+
write(chunk, _encoding, callback) {
|
|
3901
|
+
output += String(chunk);
|
|
3902
|
+
callback();
|
|
4396
3903
|
}
|
|
4397
|
-
|
|
4398
|
-
|
|
3904
|
+
});
|
|
3905
|
+
const result = await printError(error, project, {
|
|
3906
|
+
showCodeFrame: false,
|
|
3907
|
+
logger: new Logger(ctx, writable, writable)
|
|
3908
|
+
});
|
|
3909
|
+
return { nearest: result == null ? void 0 : result.nearest, output };
|
|
3910
|
+
}
|
|
3911
|
+
async function printError(error, project, options) {
|
|
3912
|
+
const { showCodeFrame = true, fullStack = false, type } = options;
|
|
3913
|
+
const logger = options.logger;
|
|
3914
|
+
let e = error;
|
|
3915
|
+
if (isPrimitive(e)) {
|
|
3916
|
+
e = {
|
|
3917
|
+
message: String(error).split(/\n/g)[0],
|
|
3918
|
+
stack: String(error)
|
|
3919
|
+
};
|
|
3920
|
+
}
|
|
3921
|
+
if (!e) {
|
|
3922
|
+
const error2 = new Error("unknown error");
|
|
3923
|
+
e = {
|
|
3924
|
+
message: e ?? error2.message,
|
|
3925
|
+
stack: error2.stack
|
|
3926
|
+
};
|
|
3927
|
+
}
|
|
3928
|
+
if (!project) {
|
|
3929
|
+
printErrorMessage(e, logger);
|
|
3930
|
+
return;
|
|
3931
|
+
}
|
|
3932
|
+
const parserOptions = {
|
|
3933
|
+
// only browser stack traces require remapping
|
|
3934
|
+
getSourceMap: (file) => project.getBrowserSourceMapModuleById(file),
|
|
3935
|
+
frameFilter: project.config.onStackTrace
|
|
3936
|
+
};
|
|
3937
|
+
if (fullStack)
|
|
3938
|
+
parserOptions.ignoreStackEntries = [];
|
|
3939
|
+
const stacks = parseErrorStacktrace(e, parserOptions);
|
|
3940
|
+
const nearest = error instanceof TypeCheckError ? error.stacks[0] : stacks.find(
|
|
3941
|
+
(stack) => {
|
|
3942
|
+
try {
|
|
3943
|
+
return project.server && project.getModuleById(stack.file) && existsSync(stack.file);
|
|
3944
|
+
} catch {
|
|
3945
|
+
return false;
|
|
3946
|
+
}
|
|
3947
|
+
}
|
|
3948
|
+
);
|
|
3949
|
+
const errorProperties = getErrorProperties(e);
|
|
3950
|
+
if (type)
|
|
3951
|
+
printErrorType(type, project.ctx);
|
|
3952
|
+
printErrorMessage(e, logger);
|
|
3953
|
+
if (e.codeFrame)
|
|
3954
|
+
logger.error(`${e.codeFrame}
|
|
3955
|
+
`);
|
|
3956
|
+
if (e.diff)
|
|
3957
|
+
displayDiff(e.diff, logger.console);
|
|
3958
|
+
if (e.frame) {
|
|
3959
|
+
logger.error(c.yellow(e.frame));
|
|
3960
|
+
} else {
|
|
3961
|
+
printStack(logger, project, stacks, nearest, errorProperties, (s) => {
|
|
3962
|
+
if (showCodeFrame && s === nearest && nearest) {
|
|
3963
|
+
const sourceCode = readFileSync(nearest.file, "utf-8");
|
|
3964
|
+
logger.error(generateCodeFrame(sourceCode.length > 1e5 ? sourceCode : logger.highlight(nearest.file, sourceCode), 4, s));
|
|
3965
|
+
}
|
|
3966
|
+
});
|
|
3967
|
+
}
|
|
3968
|
+
const testPath = e.VITEST_TEST_PATH;
|
|
3969
|
+
const testName = e.VITEST_TEST_NAME;
|
|
3970
|
+
const afterEnvTeardown = e.VITEST_AFTER_ENV_TEARDOWN;
|
|
3971
|
+
if (testPath)
|
|
3972
|
+
logger.error(c.red(`This error originated in "${c.bold(testPath)}" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.`));
|
|
3973
|
+
if (testName) {
|
|
3974
|
+
logger.error(c.red(`The latest test that might've caused the error is "${c.bold(testName)}". It might mean one of the following:
|
|
3975
|
+
- The error was thrown, while Vitest was running this test.
|
|
3976
|
+
- If the error occurred after the test had been completed, this was the last documented test before it was thrown.`));
|
|
3977
|
+
}
|
|
3978
|
+
if (afterEnvTeardown) {
|
|
3979
|
+
logger.error(c.red("This error was caught after test environment was torn down. Make sure to cancel any running tasks before test finishes:\n- cancel timeouts using clearTimeout and clearInterval\n- wait for promises to resolve using the await keyword"));
|
|
3980
|
+
}
|
|
3981
|
+
if (typeof e.cause === "object" && e.cause && "name" in e.cause) {
|
|
3982
|
+
e.cause.name = `Caused by: ${e.cause.name}`;
|
|
3983
|
+
await printError(e.cause, project, { fullStack, showCodeFrame: false, logger: options.logger });
|
|
3984
|
+
}
|
|
3985
|
+
handleImportOutsideModuleError(e.stack || e.stackStr || "", logger);
|
|
3986
|
+
return { nearest };
|
|
3987
|
+
}
|
|
3988
|
+
function printErrorType(type, ctx) {
|
|
3989
|
+
ctx.logger.error(`
|
|
3990
|
+
${c.red(divider(c.bold(c.inverse(` ${type} `))))}`);
|
|
3991
|
+
}
|
|
3992
|
+
const skipErrorProperties = /* @__PURE__ */ new Set([
|
|
3993
|
+
"nameStr",
|
|
3994
|
+
"stack",
|
|
3995
|
+
"cause",
|
|
3996
|
+
"stacks",
|
|
3997
|
+
"stackStr",
|
|
3998
|
+
"type",
|
|
3999
|
+
"showDiff",
|
|
4000
|
+
"diff",
|
|
4001
|
+
"codeFrame",
|
|
4002
|
+
"actual",
|
|
4003
|
+
"expected",
|
|
4004
|
+
"diffOptions",
|
|
4005
|
+
"VITEST_TEST_NAME",
|
|
4006
|
+
"VITEST_TEST_PATH",
|
|
4007
|
+
"VITEST_AFTER_ENV_TEARDOWN",
|
|
4008
|
+
...Object.getOwnPropertyNames(Error.prototype),
|
|
4009
|
+
...Object.getOwnPropertyNames(Object.prototype)
|
|
4010
|
+
]);
|
|
4011
|
+
function getErrorProperties(e) {
|
|
4012
|
+
const errorObject = /* @__PURE__ */ Object.create(null);
|
|
4013
|
+
if (e.name === "AssertionError")
|
|
4014
|
+
return errorObject;
|
|
4015
|
+
for (const key of Object.getOwnPropertyNames(e)) {
|
|
4016
|
+
if (!skipErrorProperties.has(key))
|
|
4017
|
+
errorObject[key] = e[key];
|
|
4018
|
+
}
|
|
4019
|
+
return errorObject;
|
|
4020
|
+
}
|
|
4021
|
+
const esmErrors = [
|
|
4022
|
+
"Cannot use import statement outside a module",
|
|
4023
|
+
"Unexpected token 'export'"
|
|
4024
|
+
];
|
|
4025
|
+
function handleImportOutsideModuleError(stack, logger) {
|
|
4026
|
+
if (!esmErrors.some((e) => stack.includes(e)))
|
|
4027
|
+
return;
|
|
4028
|
+
const path = normalize(stack.split("\n")[0].trim());
|
|
4029
|
+
let name = path.split("/node_modules/").pop() || "";
|
|
4030
|
+
if (name == null ? void 0 : name.startsWith("@"))
|
|
4031
|
+
name = name.split("/").slice(0, 2).join("/");
|
|
4032
|
+
else
|
|
4033
|
+
name = name.split("/")[0];
|
|
4034
|
+
if (name)
|
|
4035
|
+
printModuleWarningForPackage(logger, path, name);
|
|
4036
|
+
else
|
|
4037
|
+
printModuleWarningForSourceCode(logger, path);
|
|
4038
|
+
}
|
|
4039
|
+
function printModuleWarningForPackage(logger, path, name) {
|
|
4040
|
+
logger.error(c.yellow(
|
|
4041
|
+
`Module ${path} seems to be an ES Module but shipped in a CommonJS package. You might want to create an issue to the package ${c.bold(`"${name}"`)} asking them to ship the file in .mjs extension or add "type": "module" in their package.json.
|
|
4042
|
+
|
|
4043
|
+
As a temporary workaround you can try to inline the package by updating your config:
|
|
4044
|
+
|
|
4045
|
+
` + c.gray(c.dim("// vitest.config.js")) + "\n" + c.green(`export default {
|
|
4046
|
+
test: {
|
|
4047
|
+
server: {
|
|
4048
|
+
deps: {
|
|
4049
|
+
inline: [
|
|
4050
|
+
${c.yellow(c.bold(`"${name}"`))}
|
|
4051
|
+
]
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4054
|
+
}
|
|
4055
|
+
}
|
|
4056
|
+
`)
|
|
4057
|
+
));
|
|
4058
|
+
}
|
|
4059
|
+
function printModuleWarningForSourceCode(logger, path) {
|
|
4060
|
+
logger.error(c.yellow(
|
|
4061
|
+
`Module ${path} seems to be an ES Module but shipped in a CommonJS package. To fix this issue, change the file extension to .mjs or add "type": "module" in your package.json.`
|
|
4062
|
+
));
|
|
4063
|
+
}
|
|
4064
|
+
function displayDiff(diff, console) {
|
|
4065
|
+
if (diff)
|
|
4066
|
+
console.error(`
|
|
4067
|
+
${diff}
|
|
4068
|
+
`);
|
|
4069
|
+
}
|
|
4070
|
+
function printErrorMessage(error, logger) {
|
|
4071
|
+
const errorName = error.name || error.nameStr || "Unknown Error";
|
|
4072
|
+
if (!error.message) {
|
|
4073
|
+
logger.error(error);
|
|
4074
|
+
return;
|
|
4075
|
+
}
|
|
4076
|
+
if (error.message.length > 5e3) {
|
|
4077
|
+
logger.error(`${c.red(c.bold(errorName))}: ${error.message}`);
|
|
4078
|
+
} else {
|
|
4079
|
+
logger.error(c.red(`${c.bold(errorName)}: ${error.message}`));
|
|
4080
|
+
}
|
|
4081
|
+
}
|
|
4082
|
+
function printStack(logger, project, stack, highlight, errorProperties, onStack) {
|
|
4083
|
+
for (const frame of stack) {
|
|
4084
|
+
const color = frame === highlight ? c.cyan : c.gray;
|
|
4085
|
+
const path = relative(project.config.root, frame.file);
|
|
4086
|
+
logger.error(color(` ${c.dim(F_POINTER)} ${[frame.method, `${path}:${c.dim(`${frame.line}:${frame.column}`)}`].filter(Boolean).join(" ")}`));
|
|
4087
|
+
onStack == null ? void 0 : onStack(frame);
|
|
4088
|
+
}
|
|
4089
|
+
if (stack.length)
|
|
4090
|
+
logger.error();
|
|
4091
|
+
const hasProperties = Object.keys(errorProperties).length > 0;
|
|
4092
|
+
if (hasProperties) {
|
|
4093
|
+
logger.error(c.red(c.dim(divider())));
|
|
4094
|
+
const propertiesString = inspect(errorProperties);
|
|
4095
|
+
logger.error(c.red(c.bold("Serialized Error:")), c.gray(propertiesString));
|
|
4096
|
+
}
|
|
4097
|
+
}
|
|
4098
|
+
function generateCodeFrame(source, indent = 0, loc, range = 2) {
|
|
4099
|
+
var _a;
|
|
4100
|
+
const start = typeof loc === "object" ? positionToOffset(source, loc.line, loc.column) : loc;
|
|
4101
|
+
const end = start;
|
|
4102
|
+
const lines = source.split(lineSplitRE);
|
|
4103
|
+
const nl = /\r\n/.test(source) ? 2 : 1;
|
|
4104
|
+
let count = 0;
|
|
4105
|
+
let res = [];
|
|
4106
|
+
const columns = ((_a = process.stdout) == null ? void 0 : _a.columns) || 80;
|
|
4107
|
+
function lineNo(no = "") {
|
|
4108
|
+
return c.gray(`${String(no).padStart(3, " ")}| `);
|
|
4109
|
+
}
|
|
4110
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4111
|
+
count += lines[i].length + nl;
|
|
4112
|
+
if (count >= start) {
|
|
4113
|
+
for (let j = i - range; j <= i + range || end > count; j++) {
|
|
4114
|
+
if (j < 0 || j >= lines.length)
|
|
4115
|
+
continue;
|
|
4116
|
+
const lineLength = lines[j].length;
|
|
4117
|
+
if (stripAnsi(lines[j]).length > 200)
|
|
4118
|
+
return "";
|
|
4119
|
+
res.push(lineNo(j + 1) + cliTruncate(lines[j].replace(/\t/g, " "), columns - 5 - indent));
|
|
4120
|
+
if (j === i) {
|
|
4121
|
+
const pad = start - (count - lineLength) + (nl - 1);
|
|
4122
|
+
const length = Math.max(1, end > count ? lineLength - pad : end - start);
|
|
4123
|
+
res.push(lineNo() + " ".repeat(pad) + c.red("^".repeat(length)));
|
|
4124
|
+
} else if (j > i) {
|
|
4125
|
+
if (end > count) {
|
|
4126
|
+
const length = Math.max(1, Math.min(end - count, lineLength));
|
|
4127
|
+
res.push(lineNo() + c.red("^".repeat(length)));
|
|
4128
|
+
}
|
|
4129
|
+
count += lineLength + 1;
|
|
4130
|
+
}
|
|
4131
|
+
}
|
|
4132
|
+
break;
|
|
4133
|
+
}
|
|
4134
|
+
}
|
|
4135
|
+
if (indent)
|
|
4136
|
+
res = res.map((line) => " ".repeat(indent) + line);
|
|
4137
|
+
return res.join("\n");
|
|
4138
|
+
}
|
|
4139
|
+
|
|
4140
|
+
function flattenTasks$1(task, baseName = "") {
|
|
4141
|
+
const base = baseName ? `${baseName} > ` : "";
|
|
4142
|
+
if (task.type === "suite") {
|
|
4143
|
+
return task.tasks.flatMap((child) => flattenTasks$1(child, `${base}${task.name}`));
|
|
4144
|
+
} else {
|
|
4145
|
+
return [{
|
|
4146
|
+
...task,
|
|
4147
|
+
name: `${base}${task.name}`
|
|
4148
|
+
}];
|
|
4149
|
+
}
|
|
4150
|
+
}
|
|
4151
|
+
function removeInvalidXMLCharacters(value, removeDiscouragedChars) {
|
|
4152
|
+
let regex = /((?:[\0-\x08\x0B\f\x0E-\x1F\uFFFD\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/g;
|
|
4153
|
+
value = String(value || "").replace(regex, "");
|
|
4154
|
+
if (removeDiscouragedChars) {
|
|
4155
|
+
regex = new RegExp(
|
|
4156
|
+
"([\\x7F-\\x84]|[\\x86-\\x9F]|[\\uFDD0-\\uFDEF]|(?:\\uD83F[\\uDFFE\\uDFFF])|(?:\\uD87F[\\uDFFE\\uDFFF])|(?:\\uD8BF[\\uDFFE\\uDFFF])|(?:\\uD8FF[\\uDFFE\\uDFFF])|(?:\\uD93F[\\uDFFE\\uDFFF])|(?:\\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\\x0B\\f\\x0E-\\u2027\\u202A-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))",
|
|
4157
|
+
"g"
|
|
4158
|
+
);
|
|
4159
|
+
value = value.replace(regex, "");
|
|
4160
|
+
}
|
|
4161
|
+
return value;
|
|
4162
|
+
}
|
|
4163
|
+
function escapeXML(value) {
|
|
4164
|
+
return removeInvalidXMLCharacters(
|
|
4165
|
+
String(value).replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">"),
|
|
4166
|
+
true
|
|
4167
|
+
);
|
|
4168
|
+
}
|
|
4169
|
+
function executionTime(durationMS) {
|
|
4170
|
+
return (durationMS / 1e3).toLocaleString("en-US", { useGrouping: false, maximumFractionDigits: 10 });
|
|
4171
|
+
}
|
|
4172
|
+
function getDuration(task) {
|
|
4173
|
+
var _a;
|
|
4174
|
+
const duration = ((_a = task.result) == null ? void 0 : _a.duration) ?? 0;
|
|
4175
|
+
return executionTime(duration);
|
|
4176
|
+
}
|
|
4177
|
+
class JUnitReporter {
|
|
4178
|
+
ctx;
|
|
4179
|
+
reportFile;
|
|
4180
|
+
baseLog;
|
|
4181
|
+
logger;
|
|
4182
|
+
_timeStart = /* @__PURE__ */ new Date();
|
|
4183
|
+
fileFd;
|
|
4184
|
+
options;
|
|
4185
|
+
constructor(options) {
|
|
4186
|
+
this.options = options;
|
|
4187
|
+
}
|
|
4188
|
+
async onInit(ctx) {
|
|
4189
|
+
this.ctx = ctx;
|
|
4190
|
+
const outputFile = this.options.outputFile ?? getOutputFile(this.ctx.config, "junit");
|
|
4191
|
+
if (outputFile) {
|
|
4192
|
+
this.reportFile = resolve(this.ctx.config.root, outputFile);
|
|
4193
|
+
const outputDirectory = dirname(this.reportFile);
|
|
4194
|
+
if (!existsSync(outputDirectory))
|
|
4195
|
+
await promises.mkdir(outputDirectory, { recursive: true });
|
|
4196
|
+
const fileFd = await promises.open(this.reportFile, "w+");
|
|
4197
|
+
this.fileFd = fileFd;
|
|
4198
|
+
this.baseLog = async (text) => {
|
|
4199
|
+
if (!this.fileFd)
|
|
4200
|
+
this.fileFd = await promises.open(this.reportFile, "w+");
|
|
4201
|
+
await promises.writeFile(this.fileFd, `${text}
|
|
4202
|
+
`);
|
|
4203
|
+
};
|
|
4204
|
+
} else {
|
|
4205
|
+
this.baseLog = async (text) => this.ctx.logger.log(text);
|
|
4206
|
+
}
|
|
4207
|
+
this._timeStart = /* @__PURE__ */ new Date();
|
|
4208
|
+
this.logger = new IndentedLogger(this.baseLog);
|
|
4209
|
+
}
|
|
4210
|
+
async writeElement(name, attrs, children) {
|
|
4211
|
+
const pairs = [];
|
|
4212
|
+
for (const key in attrs) {
|
|
4213
|
+
const attr = attrs[key];
|
|
4214
|
+
if (attr === void 0)
|
|
4215
|
+
continue;
|
|
4216
|
+
pairs.push(`${key}="${escapeXML(attr)}"`);
|
|
4217
|
+
}
|
|
4218
|
+
await this.logger.log(`<${name}${pairs.length ? ` ${pairs.join(" ")}` : ""}>`);
|
|
4219
|
+
this.logger.indent();
|
|
4220
|
+
await children.call(this);
|
|
4221
|
+
this.logger.unindent();
|
|
4222
|
+
await this.logger.log(`</${name}>`);
|
|
4223
|
+
}
|
|
4224
|
+
async writeLogs(task, type) {
|
|
4225
|
+
if (task.logs == null || task.logs.length === 0)
|
|
4226
|
+
return;
|
|
4227
|
+
const logType = type === "err" ? "stderr" : "stdout";
|
|
4228
|
+
const logs = task.logs.filter((log) => log.type === logType);
|
|
4229
|
+
if (logs.length === 0)
|
|
4230
|
+
return;
|
|
4231
|
+
await this.writeElement(`system-${type}`, {}, async () => {
|
|
4232
|
+
for (const log of logs)
|
|
4233
|
+
await this.baseLog(escapeXML(log.content));
|
|
4234
|
+
});
|
|
4235
|
+
}
|
|
4236
|
+
async writeTasks(tasks, filename) {
|
|
4237
|
+
for (const task of tasks) {
|
|
4238
|
+
await this.writeElement("testcase", {
|
|
4239
|
+
// TODO: v2.0.0 Remove env variable in favor of custom reporter options, e.g. "reporters: [['json', { classname: 'something' }]]"
|
|
4240
|
+
classname: this.options.classname ?? process.env.VITEST_JUNIT_CLASSNAME ?? filename,
|
|
4241
|
+
name: task.name,
|
|
4242
|
+
time: getDuration(task)
|
|
4243
|
+
}, async () => {
|
|
4244
|
+
var _a;
|
|
4245
|
+
await this.writeLogs(task, "out");
|
|
4246
|
+
await this.writeLogs(task, "err");
|
|
4247
|
+
if (task.mode === "skip" || task.mode === "todo")
|
|
4248
|
+
await this.logger.log("<skipped/>");
|
|
4249
|
+
if (((_a = task.result) == null ? void 0 : _a.state) === "fail") {
|
|
4250
|
+
const errors = task.result.errors || [];
|
|
4251
|
+
for (const error of errors) {
|
|
4252
|
+
await this.writeElement("failure", {
|
|
4253
|
+
message: error == null ? void 0 : error.message,
|
|
4254
|
+
type: (error == null ? void 0 : error.name) ?? (error == null ? void 0 : error.nameStr)
|
|
4255
|
+
}, async () => {
|
|
4256
|
+
if (!error)
|
|
4257
|
+
return;
|
|
4258
|
+
const result = await captuerPrintError(
|
|
4259
|
+
error,
|
|
4260
|
+
this.ctx,
|
|
4261
|
+
this.ctx.getProjectByTaskId(task.id)
|
|
4262
|
+
);
|
|
4263
|
+
await this.baseLog(escapeXML(stripAnsi(result.output.trim())));
|
|
4264
|
+
});
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
4267
|
+
});
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
4270
|
+
async onFinished(files = this.ctx.state.getFiles()) {
|
|
4271
|
+
var _a;
|
|
4272
|
+
await this.logger.log('<?xml version="1.0" encoding="UTF-8" ?>');
|
|
4273
|
+
const transformed = files.map((file) => {
|
|
4274
|
+
var _a2, _b;
|
|
4275
|
+
const tasks = file.tasks.flatMap((task) => flattenTasks$1(task));
|
|
4276
|
+
const stats2 = tasks.reduce((stats3, task) => {
|
|
4277
|
+
var _a3, _b2;
|
|
4278
|
+
return {
|
|
4279
|
+
passed: stats3.passed + Number(((_a3 = task.result) == null ? void 0 : _a3.state) === "pass"),
|
|
4280
|
+
failures: stats3.failures + Number(((_b2 = task.result) == null ? void 0 : _b2.state) === "fail"),
|
|
4281
|
+
skipped: stats3.skipped + Number(task.mode === "skip" || task.mode === "todo")
|
|
4282
|
+
};
|
|
4283
|
+
}, {
|
|
4284
|
+
passed: 0,
|
|
4285
|
+
failures: 0,
|
|
4286
|
+
skipped: 0
|
|
4287
|
+
});
|
|
4288
|
+
const suites = getSuites(file);
|
|
4289
|
+
for (const suite of suites) {
|
|
4290
|
+
if ((_a2 = suite.result) == null ? void 0 : _a2.errors) {
|
|
4291
|
+
tasks.push(suite);
|
|
4292
|
+
stats2.failures += 1;
|
|
4293
|
+
}
|
|
4294
|
+
}
|
|
4295
|
+
if (tasks.length === 0 && ((_b = file.result) == null ? void 0 : _b.state) === "fail") {
|
|
4296
|
+
stats2.failures = 1;
|
|
4297
|
+
tasks.push({
|
|
4298
|
+
id: file.id,
|
|
4299
|
+
type: "test",
|
|
4300
|
+
name: file.name,
|
|
4301
|
+
mode: "run",
|
|
4302
|
+
result: file.result,
|
|
4303
|
+
meta: {},
|
|
4304
|
+
// NOTE: not used in JUnitReporter
|
|
4305
|
+
context: null,
|
|
4306
|
+
suite: null
|
|
4307
|
+
});
|
|
4308
|
+
}
|
|
4309
|
+
return {
|
|
4310
|
+
...file,
|
|
4311
|
+
tasks,
|
|
4312
|
+
stats: stats2
|
|
4313
|
+
};
|
|
4314
|
+
});
|
|
4315
|
+
const stats = transformed.reduce((stats2, file) => {
|
|
4316
|
+
stats2.tests += file.tasks.length;
|
|
4317
|
+
stats2.failures += file.stats.failures;
|
|
4318
|
+
return stats2;
|
|
4319
|
+
}, {
|
|
4320
|
+
// TODO: v2.0.0 Remove env variable in favor of custom reporter options, e.g. "reporters: [['json', { suiteName: 'something' }]]"
|
|
4321
|
+
name: this.options.suiteName || process.env.VITEST_JUNIT_SUITE_NAME || "vitest tests",
|
|
4322
|
+
tests: 0,
|
|
4323
|
+
failures: 0,
|
|
4324
|
+
errors: 0,
|
|
4325
|
+
// we cannot detect those
|
|
4326
|
+
time: executionTime((/* @__PURE__ */ new Date()).getTime() - this._timeStart.getTime())
|
|
4327
|
+
});
|
|
4328
|
+
await this.writeElement("testsuites", stats, async () => {
|
|
4329
|
+
for (const file of transformed) {
|
|
4330
|
+
await this.writeElement("testsuite", {
|
|
4331
|
+
name: relative(this.ctx.config.root, file.filepath),
|
|
4332
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4333
|
+
hostname: hostname(),
|
|
4334
|
+
tests: file.tasks.length,
|
|
4335
|
+
failures: file.stats.failures,
|
|
4336
|
+
errors: 0,
|
|
4337
|
+
// An errored test is one that had an unanticipated problem. We cannot detect those.
|
|
4338
|
+
skipped: file.stats.skipped,
|
|
4339
|
+
time: getDuration(file)
|
|
4340
|
+
}, async () => {
|
|
4341
|
+
await this.writeTasks(file.tasks, file.name);
|
|
4342
|
+
});
|
|
4343
|
+
}
|
|
4344
|
+
});
|
|
4345
|
+
if (this.reportFile)
|
|
4346
|
+
this.ctx.logger.log(`JUNIT report written to ${this.reportFile}`);
|
|
4347
|
+
await ((_a = this.fileFd) == null ? void 0 : _a.close());
|
|
4348
|
+
this.fileFd = void 0;
|
|
4349
|
+
}
|
|
4350
|
+
}
|
|
4351
|
+
|
|
4352
|
+
function flattenTasks(task, baseName = "") {
|
|
4353
|
+
const base = baseName ? `${baseName} > ` : "";
|
|
4354
|
+
if (task.type === "suite" && task.tasks.length > 0) {
|
|
4355
|
+
return task.tasks.flatMap((child) => flattenTasks(child, `${base}${task.name}`));
|
|
4356
|
+
} else {
|
|
4357
|
+
return [{
|
|
4358
|
+
...task,
|
|
4359
|
+
name: `${base}${task.name}`
|
|
4360
|
+
}];
|
|
4361
|
+
}
|
|
4362
|
+
}
|
|
4363
|
+
class TapFlatReporter extends TapReporter {
|
|
4364
|
+
onInit(ctx) {
|
|
4365
|
+
super.onInit(ctx);
|
|
4366
|
+
}
|
|
4367
|
+
async onFinished(files = this.ctx.state.getFiles()) {
|
|
4368
|
+
this.ctx.logger.log("TAP version 13");
|
|
4369
|
+
const flatTasks = files.flatMap((task) => flattenTasks(task));
|
|
4370
|
+
this.logTasks(flatTasks);
|
|
4371
|
+
}
|
|
4372
|
+
}
|
|
4373
|
+
|
|
4374
|
+
class HangingProcessReporter {
|
|
4375
|
+
whyRunning;
|
|
4376
|
+
onInit() {
|
|
4377
|
+
const _require = createRequire(import.meta.url);
|
|
4378
|
+
this.whyRunning = _require("why-is-node-running");
|
|
4379
|
+
}
|
|
4380
|
+
onProcessTimeout() {
|
|
4381
|
+
var _a;
|
|
4382
|
+
(_a = this.whyRunning) == null ? void 0 : _a.call(this);
|
|
4383
|
+
}
|
|
4384
|
+
}
|
|
4385
|
+
|
|
4386
|
+
class GithubActionsReporter {
|
|
4387
|
+
ctx = void 0;
|
|
4388
|
+
onInit(ctx) {
|
|
4389
|
+
this.ctx = ctx;
|
|
4390
|
+
}
|
|
4391
|
+
async onFinished(files = [], errors = []) {
|
|
4392
|
+
var _a, _b;
|
|
4393
|
+
const projectErrors = new Array();
|
|
4394
|
+
for (const error of errors) {
|
|
4395
|
+
projectErrors.push({
|
|
4396
|
+
project: this.ctx.getCoreWorkspaceProject(),
|
|
4397
|
+
title: "Unhandled error",
|
|
4398
|
+
error
|
|
4399
|
+
});
|
|
4400
|
+
}
|
|
4401
|
+
for (const file of files) {
|
|
4402
|
+
const tasks = getTasks(file);
|
|
4399
4403
|
const project = this.ctx.getProjectByTaskId(file.id);
|
|
4400
4404
|
for (const task of tasks) {
|
|
4401
4405
|
if (((_a = task.result) == null ? void 0 : _a.state) !== "fail")
|
|
@@ -4411,7 +4415,7 @@ class GithubActionsReporter {
|
|
|
4411
4415
|
}
|
|
4412
4416
|
}
|
|
4413
4417
|
for (const { project, title, error } of projectErrors) {
|
|
4414
|
-
const result = await
|
|
4418
|
+
const result = await captuerPrintError(error, this.ctx, project);
|
|
4415
4419
|
const stack = result == null ? void 0 : result.nearest;
|
|
4416
4420
|
if (!stack)
|
|
4417
4421
|
continue;
|
|
@@ -4430,20 +4434,6 @@ ${formatted}`);
|
|
|
4430
4434
|
}
|
|
4431
4435
|
}
|
|
4432
4436
|
}
|
|
4433
|
-
async function printErrorWrapper(error, ctx, project) {
|
|
4434
|
-
let output = "";
|
|
4435
|
-
const writable = new Writable({
|
|
4436
|
-
write(chunk, _encoding, callback) {
|
|
4437
|
-
output += String(chunk);
|
|
4438
|
-
callback();
|
|
4439
|
-
}
|
|
4440
|
-
});
|
|
4441
|
-
const result = await printError(error, project, {
|
|
4442
|
-
showCodeFrame: false,
|
|
4443
|
-
logger: new Logger(ctx, writable, writable)
|
|
4444
|
-
});
|
|
4445
|
-
return { nearest: result == null ? void 0 : result.nearest, output };
|
|
4446
|
-
}
|
|
4447
4437
|
function formatMessage({
|
|
4448
4438
|
command,
|
|
4449
4439
|
properties,
|