vitest 4.0.0-beta.5 → 4.0.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +2 -2
- package/dist/chunks/{base.DMfOuRWD.js → base.BXI97p6t.js} +7 -16
- package/dist/chunks/{benchmark.CtuRzf-i.js → benchmark.UW6Ezvxy.js} +4 -9
- package/dist/chunks/{cac.CKnbxhn2.js → cac.WE-urWw5.js} +37 -113
- package/dist/chunks/{cli-api.COn58yrl.js → cli-api.CZz3evYC.js} +505 -1211
- package/dist/chunks/{console.Duv2dVIC.js → console.B0quX7yH.js} +32 -68
- package/dist/chunks/{coverage.B6cReEn1.js → coverage.BPRS6xgn.js} +210 -579
- package/dist/chunks/{creator.DUVZ6rfm.js → creator.KEg6n5IC.js} +28 -74
- package/dist/chunks/{date.Bq6ZW5rf.js → date.-jtEtIeV.js} +6 -17
- package/dist/chunks/{git.BVQ8w_Sw.js → git.BFNcloKD.js} +1 -2
- package/dist/chunks/{globals.CJQ63oO0.js → globals.lgsmH00r.js} +5 -5
- package/dist/chunks/{index.DgN0Zk9a.js → index.7w0eqmYM.js} +14 -24
- package/dist/chunks/{index.QZr3S3vQ.js → index.AR8aAkCC.js} +2 -2
- package/dist/chunks/{index.BRtIe7r8.js → index.BG0gqZH-.js} +39 -102
- package/dist/chunks/{index.oWRWx-nj.js → index.CsFXYRkW.js} +17 -36
- package/dist/chunks/{index.DQhAfQQU.js → index.VNI-1z5c.js} +270 -606
- package/dist/chunks/{inspector.C914Efll.js → inspector.CvQD-Nie.js} +10 -25
- package/dist/chunks/{moduleRunner.d.mmOmOGrW.d.ts → moduleRunner.d.8kKUsuDg.d.ts} +1 -1
- package/dist/chunks/{node.4JV5OXkt.js → node.BOqcT2jW.js} +1 -1
- package/dist/chunks/{plugin.d.CvOlgjxK.d.ts → plugin.d.DuiQJfUL.d.ts} +1 -1
- package/dist/chunks/{reporters.d.CYE9sT5z.d.ts → reporters.d.CqR9-CDJ.d.ts} +16 -33
- package/dist/chunks/{resolver.D5bG4zy5.js → resolver.Bx6lE0iq.js} +21 -64
- package/dist/chunks/{rpc.DGoW_Vl-.js → rpc.RpPylpp0.js} +7 -21
- package/dist/chunks/{runBaseTests.B3KcKqlF.js → runBaseTests.D6sfuWBM.js} +25 -54
- package/dist/chunks/{setup-common.lgPs-bYv.js → setup-common.hLGRxhC8.js} +9 -22
- package/dist/chunks/{startModuleRunner.C8FtT_BY.js → startModuleRunner.C8TW8zTN.js} +83 -205
- package/dist/chunks/{typechecker.BgoW4nTA.js → typechecker.Cd1wvxUM.js} +96 -208
- package/dist/chunks/{utils.CcGm2cd1.js → utils.C2YI6McM.js} +4 -13
- package/dist/chunks/{utils.B9FY3b73.js → utils.C7__0Iv5.js} +5 -14
- package/dist/chunks/{vi.DGAfBY4R.js → vi.BfdOiD4j.js} +110 -267
- package/dist/chunks/{vm.BKfKvaKl.js → vm.BHBje7cC.js} +73 -177
- package/dist/cli.js +3 -3
- package/dist/config.d.ts +4 -4
- package/dist/coverage.d.ts +1 -1
- package/dist/coverage.js +2 -2
- package/dist/environments.js +1 -1
- package/dist/index.js +5 -5
- package/dist/module-evaluator.d.ts +1 -1
- package/dist/module-evaluator.js +33 -84
- package/dist/module-runner.js +2 -2
- package/dist/node.d.ts +3 -3
- package/dist/node.js +13 -19
- package/dist/reporters.d.ts +2 -2
- package/dist/reporters.js +3 -3
- package/dist/runners.js +23 -51
- package/dist/snapshot.js +2 -2
- package/dist/suite.js +2 -2
- package/dist/worker.js +18 -34
- package/dist/workers/forks.js +4 -4
- package/dist/workers/runVmTests.js +19 -37
- package/dist/workers/threads.js +4 -4
- package/dist/workers/vmForks.js +7 -7
- package/dist/workers/vmThreads.js +7 -7
- package/dist/workers.js +11 -11
- package/package.json +11 -11
|
@@ -10,16 +10,13 @@ import { parseAstAsync } from 'vite';
|
|
|
10
10
|
|
|
11
11
|
const REGEXP_WRAP_PREFIX = "$$vitest:";
|
|
12
12
|
function getOutputFile(config, reporter) {
|
|
13
|
-
if (
|
|
14
|
-
if (typeof config.outputFile === "string") return config.outputFile;
|
|
15
|
-
return config.outputFile[reporter];
|
|
13
|
+
if (config?.outputFile) return typeof config.outputFile === "string" ? config.outputFile : config.outputFile[reporter];
|
|
16
14
|
}
|
|
17
15
|
/**
|
|
18
16
|
* Prepares `SerializedConfig` for serialization, e.g. `node:v8.serialize`
|
|
19
17
|
*/
|
|
20
18
|
function wrapSerializableConfig(config) {
|
|
21
|
-
let testNamePattern = config.testNamePattern;
|
|
22
|
-
let defines = config.defines;
|
|
19
|
+
let testNamePattern = config.testNamePattern, defines = config.defines;
|
|
23
20
|
// v8 serialize does not support regex
|
|
24
21
|
if (testNamePattern && typeof testNamePattern !== "string") testNamePattern = `${REGEXP_WRAP_PREFIX}${testNamePattern.toString()}`;
|
|
25
22
|
// v8 serialize drops properties with undefined value
|
|
@@ -40,58 +37,44 @@ function hasFailedSnapshot(suite) {
|
|
|
40
37
|
});
|
|
41
38
|
}
|
|
42
39
|
function convertTasksToEvents(file, onTask) {
|
|
43
|
-
const packs = [];
|
|
44
|
-
const events = [];
|
|
40
|
+
const packs = [], events = [];
|
|
45
41
|
function visit(suite) {
|
|
46
|
-
onTask?.(suite)
|
|
47
|
-
packs.push([
|
|
42
|
+
onTask?.(suite), packs.push([
|
|
48
43
|
suite.id,
|
|
49
44
|
suite.result,
|
|
50
45
|
suite.meta
|
|
51
|
-
])
|
|
52
|
-
events.push([
|
|
46
|
+
]), events.push([
|
|
53
47
|
suite.id,
|
|
54
48
|
"suite-prepare",
|
|
55
49
|
void 0
|
|
56
|
-
])
|
|
57
|
-
suite.tasks.forEach((task) => {
|
|
50
|
+
]), suite.tasks.forEach((task) => {
|
|
58
51
|
if (task.type === "suite") visit(task);
|
|
59
|
-
else
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
events.push([
|
|
80
|
-
task.id,
|
|
81
|
-
"test-finished",
|
|
82
|
-
void 0
|
|
83
|
-
]);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
events.push([
|
|
52
|
+
else if (onTask?.(task), suite.mode !== "skip" && suite.mode !== "todo") packs.push([
|
|
53
|
+
task.id,
|
|
54
|
+
task.result,
|
|
55
|
+
task.meta
|
|
56
|
+
]), events.push([
|
|
57
|
+
task.id,
|
|
58
|
+
"test-prepare",
|
|
59
|
+
void 0
|
|
60
|
+
]), task.annotations.forEach((annotation) => {
|
|
61
|
+
events.push([
|
|
62
|
+
task.id,
|
|
63
|
+
"test-annotation",
|
|
64
|
+
{ annotation }
|
|
65
|
+
]);
|
|
66
|
+
}), events.push([
|
|
67
|
+
task.id,
|
|
68
|
+
"test-finished",
|
|
69
|
+
void 0
|
|
70
|
+
]);
|
|
71
|
+
}), events.push([
|
|
88
72
|
suite.id,
|
|
89
73
|
"suite-finished",
|
|
90
74
|
void 0
|
|
91
75
|
]);
|
|
92
76
|
}
|
|
93
|
-
visit(file)
|
|
94
|
-
return {
|
|
77
|
+
return visit(file), {
|
|
95
78
|
packs,
|
|
96
79
|
events
|
|
97
80
|
};
|
|
@@ -376,11 +359,7 @@ base.MethodDefinition = base.PropertyDefinition = base.Property = function (node
|
|
|
376
359
|
async function collectTests(ctx, filepath) {
|
|
377
360
|
const request = await ctx.vite.environments.ssr.transformRequest(filepath);
|
|
378
361
|
if (!request) return null;
|
|
379
|
-
const ast = await parseAstAsync(request.code)
|
|
380
|
-
const testFilepath = relative(ctx.config.root, filepath);
|
|
381
|
-
const projectName = ctx.name;
|
|
382
|
-
const typecheckSubprojectName = projectName ? `${projectName}:__typecheck__` : "__typecheck__";
|
|
383
|
-
const file = {
|
|
362
|
+
const ast = await parseAstAsync(request.code), testFilepath = relative(ctx.config.root, filepath), projectName = ctx.name, typecheckSubprojectName = projectName ? `${projectName}:__typecheck__` : "__typecheck__", file = {
|
|
384
363
|
filepath,
|
|
385
364
|
type: "suite",
|
|
386
365
|
id: generateHash(`${testFilepath}${typecheckSubprojectName}`),
|
|
@@ -394,24 +373,19 @@ async function collectTests(ctx, filepath) {
|
|
|
394
373
|
file: null
|
|
395
374
|
};
|
|
396
375
|
file.file = file;
|
|
397
|
-
const definitions = []
|
|
398
|
-
const getName = (callee) => {
|
|
376
|
+
const definitions = [], getName = (callee) => {
|
|
399
377
|
if (!callee) return null;
|
|
400
378
|
if (callee.type === "Identifier") return callee.name;
|
|
401
379
|
if (callee.type === "CallExpression") return getName(callee.callee);
|
|
402
380
|
if (callee.type === "TaggedTemplateExpression") return getName(callee.tag);
|
|
403
|
-
if (callee.type === "MemberExpression")
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
if (callee.object?.name?.startsWith("__vite_ssr_")) return getName(callee.property);
|
|
412
|
-
// call as `__vite_ssr__.test.skip()`
|
|
413
|
-
return getName(callee.object?.property);
|
|
414
|
-
}
|
|
381
|
+
if (callee.type === "MemberExpression")
|
|
382
|
+
// call as `__vite_ssr__.test.skip()`
|
|
383
|
+
return callee.object?.type === "Identifier" && [
|
|
384
|
+
"it",
|
|
385
|
+
"test",
|
|
386
|
+
"describe",
|
|
387
|
+
"suite"
|
|
388
|
+
].includes(callee.object.name) ? callee.object?.name : callee.object?.name?.startsWith("__vite_ssr_") ? getName(callee.property) : getName(callee.object?.property);
|
|
415
389
|
// unwrap (0, ...)
|
|
416
390
|
if (callee.type === "SequenceExpression" && callee.expressions.length === 2) {
|
|
417
391
|
const [e0, e1] = callee.expressions;
|
|
@@ -420,10 +394,8 @@ async function collectTests(ctx, filepath) {
|
|
|
420
394
|
return null;
|
|
421
395
|
};
|
|
422
396
|
ancestor(ast, { CallExpression(node) {
|
|
423
|
-
const { callee } = node;
|
|
424
|
-
|
|
425
|
-
if (!name) return;
|
|
426
|
-
if (![
|
|
397
|
+
const { callee } = node, name = getName(callee);
|
|
398
|
+
if (!name || ![
|
|
427
399
|
"it",
|
|
428
400
|
"test",
|
|
429
401
|
"describe",
|
|
@@ -444,9 +416,7 @@ async function collectTests(ctx, filepath) {
|
|
|
444
416
|
if (callee.type === "CallExpression") start = callee.end;
|
|
445
417
|
else if (callee.type === "TaggedTemplateExpression") start = callee.end + 1;
|
|
446
418
|
else start = node.start;
|
|
447
|
-
const { arguments: [messageNode] } = node;
|
|
448
|
-
const isQuoted = messageNode?.type === "Literal" || messageNode?.type === "TemplateLiteral";
|
|
449
|
-
const message = isQuoted ? request.code.slice(messageNode.start + 1, messageNode.end - 1) : request.code.slice(messageNode.start, messageNode.end);
|
|
419
|
+
const { arguments: [messageNode] } = node, isQuoted = messageNode?.type === "Literal" || messageNode?.type === "TemplateLiteral", message = isQuoted ? request.code.slice(messageNode.start + 1, messageNode.end - 1) : request.code.slice(messageNode.start, messageNode.end);
|
|
450
420
|
// cannot statically analyze, so we always skip it
|
|
451
421
|
if (mode === "skipIf" || mode === "runIf") mode = "skip";
|
|
452
422
|
definitions.push({
|
|
@@ -482,9 +452,7 @@ async function collectTests(ctx, filepath) {
|
|
|
482
452
|
start: definition.start,
|
|
483
453
|
meta: { typecheck: true }
|
|
484
454
|
};
|
|
485
|
-
definition.task = task;
|
|
486
|
-
latestSuite.tasks.push(task);
|
|
487
|
-
lastSuite = task;
|
|
455
|
+
definition.task = task, latestSuite.tasks.push(task), lastSuite = task;
|
|
488
456
|
return;
|
|
489
457
|
}
|
|
490
458
|
const task = {
|
|
@@ -501,13 +469,10 @@ async function collectTests(ctx, filepath) {
|
|
|
501
469
|
annotations: [],
|
|
502
470
|
meta: { typecheck: true }
|
|
503
471
|
};
|
|
504
|
-
definition.task = task;
|
|
505
|
-
|
|
506
|
-
});
|
|
507
|
-
calculateSuiteHash(file);
|
|
472
|
+
definition.task = task, latestSuite.tasks.push(task);
|
|
473
|
+
}), calculateSuiteHash(file);
|
|
508
474
|
const hasOnly = someTasksAreOnly(file);
|
|
509
|
-
interpretTaskModes(file, ctx.config.testNamePattern, void 0, hasOnly, false, ctx.config.allowOnly)
|
|
510
|
-
return {
|
|
475
|
+
return interpretTaskModes(file, ctx.config.testNamePattern, void 0, hasOnly, false, ctx.config.allowOnly), {
|
|
511
476
|
file,
|
|
512
477
|
parsed: request.code,
|
|
513
478
|
filepath,
|
|
@@ -516,14 +481,11 @@ async function collectTests(ctx, filepath) {
|
|
|
516
481
|
};
|
|
517
482
|
}
|
|
518
483
|
|
|
519
|
-
const newLineRegExp = /\r?\n/;
|
|
520
|
-
const errCodeRegExp = /error TS(?<errCode>\d+)/;
|
|
484
|
+
const newLineRegExp = /\r?\n/, errCodeRegExp = /error TS(?<errCode>\d+)/;
|
|
521
485
|
async function makeTscErrorInfo(errInfo) {
|
|
522
486
|
const [errFilePathPos = "", ...errMsgRawArr] = errInfo.split(":");
|
|
523
487
|
if (!errFilePathPos || errMsgRawArr.length === 0 || errMsgRawArr.join("").length === 0) return ["unknown filepath", null];
|
|
524
|
-
const errMsgRaw = errMsgRawArr.join("").trim();
|
|
525
|
-
// get filePath, line, col
|
|
526
|
-
const [errFilePath, errPos] = errFilePathPos.slice(0, -1).split("(");
|
|
488
|
+
const errMsgRaw = errMsgRawArr.join("").trim(), [errFilePath, errPos] = errFilePathPos.slice(0, -1).split("(");
|
|
527
489
|
if (!errFilePath || !errPos) return ["unknown filepath", null];
|
|
528
490
|
const [errLine, errCol] = errPos.split(",");
|
|
529
491
|
if (!errLine || !errCol) return [errFilePath, null];
|
|
@@ -532,9 +494,7 @@ async function makeTscErrorInfo(errInfo) {
|
|
|
532
494
|
if (!execArr) return [errFilePath, null];
|
|
533
495
|
const errCodeStr = execArr.groups?.errCode ?? "";
|
|
534
496
|
if (!errCodeStr) return [errFilePath, null];
|
|
535
|
-
const line = Number(errLine);
|
|
536
|
-
const col = Number(errCol);
|
|
537
|
-
const errCode = Number(errCodeStr);
|
|
497
|
+
const line = Number(errLine), col = Number(errCol), errCode = Number(errCodeStr);
|
|
538
498
|
return [errFilePath, {
|
|
539
499
|
filePath: errFilePath,
|
|
540
500
|
errCode,
|
|
@@ -544,43 +504,30 @@ async function makeTscErrorInfo(errInfo) {
|
|
|
544
504
|
}];
|
|
545
505
|
}
|
|
546
506
|
async function getRawErrsMapFromTsCompile(tscErrorStdout) {
|
|
547
|
-
const rawErrsMap = /* @__PURE__ */ new Map()
|
|
548
|
-
// Merge details line with main line (i.e. which contains file path)
|
|
549
|
-
const infos = await Promise.all(tscErrorStdout.split(newLineRegExp).reduce((prev, next) => {
|
|
507
|
+
const rawErrsMap = /* @__PURE__ */ new Map(), infos = await Promise.all(tscErrorStdout.split(newLineRegExp).reduce((prev, next) => {
|
|
550
508
|
if (!next) return prev;
|
|
551
|
-
|
|
509
|
+
if (!next.startsWith(" ")) prev.push(next);
|
|
552
510
|
else prev[prev.length - 1] += `\n${next}`;
|
|
553
511
|
return prev;
|
|
554
512
|
}, []).map((errInfoLine) => makeTscErrorInfo(errInfoLine)));
|
|
555
|
-
infos.forEach(([errFilePath, errInfo]) => {
|
|
556
|
-
if (!errInfo)
|
|
557
|
-
if (!rawErrsMap.has(errFilePath)) rawErrsMap.set(errFilePath, [errInfo]);
|
|
513
|
+
return infos.forEach(([errFilePath, errInfo]) => {
|
|
514
|
+
if (errInfo) if (!rawErrsMap.has(errFilePath)) rawErrsMap.set(errFilePath, [errInfo]);
|
|
558
515
|
else rawErrsMap.get(errFilePath)?.push(errInfo);
|
|
559
|
-
});
|
|
560
|
-
return rawErrsMap;
|
|
516
|
+
}), rawErrsMap;
|
|
561
517
|
}
|
|
562
518
|
|
|
563
519
|
function createIndexMap(source) {
|
|
564
520
|
const map = /* @__PURE__ */ new Map();
|
|
565
|
-
let index = 0;
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
for (const char of source) {
|
|
569
|
-
map.set(`${line}:${column}`, index++);
|
|
570
|
-
if (char === "\n" || char === "\r\n") {
|
|
571
|
-
line++;
|
|
572
|
-
column = 0;
|
|
573
|
-
} else column++;
|
|
574
|
-
}
|
|
521
|
+
let index = 0, line = 1, column = 1;
|
|
522
|
+
for (const char of source) if (map.set(`${line}:${column}`, index++), char === "\n" || char === "\r\n") line++, column = 0;
|
|
523
|
+
else column++;
|
|
575
524
|
return map;
|
|
576
525
|
}
|
|
577
526
|
|
|
578
527
|
class TypeCheckError extends Error {
|
|
579
528
|
name = "TypeCheckError";
|
|
580
529
|
constructor(message, stacks) {
|
|
581
|
-
super(message);
|
|
582
|
-
this.message = message;
|
|
583
|
-
this.stacks = stacks;
|
|
530
|
+
super(message), this.message = message, this.stacks = stacks;
|
|
584
531
|
}
|
|
585
532
|
}
|
|
586
533
|
class Typechecker {
|
|
@@ -620,12 +567,9 @@ class Typechecker {
|
|
|
620
567
|
}
|
|
621
568
|
async collectTests() {
|
|
622
569
|
const tests = (await Promise.all(this.getFiles().map((filepath) => this.collectFileTests(filepath)))).reduce((acc, data) => {
|
|
623
|
-
|
|
624
|
-
acc[data.filepath] = data;
|
|
625
|
-
return acc;
|
|
570
|
+
return data && (acc[data.filepath] = data), acc;
|
|
626
571
|
}, {});
|
|
627
|
-
this._tests = tests;
|
|
628
|
-
return tests;
|
|
572
|
+
return this._tests = tests, tests;
|
|
629
573
|
}
|
|
630
574
|
markPassed(file) {
|
|
631
575
|
if (!file.result?.state) file.result = { state: "pass" };
|
|
@@ -638,26 +582,17 @@ class Typechecker {
|
|
|
638
582
|
markTasks(file.tasks);
|
|
639
583
|
}
|
|
640
584
|
async prepareResults(output) {
|
|
641
|
-
const typeErrors = await this.parseTscLikeOutput(output);
|
|
642
|
-
const testFiles = new Set(this.getFiles());
|
|
585
|
+
const typeErrors = await this.parseTscLikeOutput(output), testFiles = new Set(this.getFiles());
|
|
643
586
|
if (!this._tests) this._tests = await this.collectTests();
|
|
644
|
-
const sourceErrors = [];
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
const errors = typeErrors.get(path);
|
|
649
|
-
files.push(file);
|
|
650
|
-
if (!errors) {
|
|
587
|
+
const sourceErrors = [], files = [];
|
|
588
|
+
return testFiles.forEach((path) => {
|
|
589
|
+
const { file, definitions, map, parsed } = this._tests[path], errors = typeErrors.get(path);
|
|
590
|
+
if (files.push(file), !errors) {
|
|
651
591
|
this.markPassed(file);
|
|
652
592
|
return;
|
|
653
593
|
}
|
|
654
|
-
const sortedDefinitions = [...definitions.sort((a, b) => b.start - a.start)]
|
|
655
|
-
|
|
656
|
-
const traceMap = map && new TraceMap(map);
|
|
657
|
-
const indexMap = createIndexMap(parsed);
|
|
658
|
-
const markState = (task, state) => {
|
|
659
|
-
task.result = { state: task.mode === "run" || task.mode === "only" ? state : task.mode };
|
|
660
|
-
if (task.suite) markState(task.suite, state);
|
|
594
|
+
const sortedDefinitions = [...definitions.sort((a, b) => b.start - a.start)], traceMap = map && new TraceMap(map), indexMap = createIndexMap(parsed), markState = (task, state) => {
|
|
595
|
+
if (task.result = { state: task.mode === "run" || task.mode === "only" ? state : task.mode }, task.suite) markState(task.suite, state);
|
|
661
596
|
else if (task.file && task !== task.file) markState(task.file, state);
|
|
662
597
|
};
|
|
663
598
|
errors.forEach(({ error, originalError }) => {
|
|
@@ -665,53 +600,37 @@ class Typechecker {
|
|
|
665
600
|
line: originalError.line,
|
|
666
601
|
column: originalError.column,
|
|
667
602
|
source: basename(path)
|
|
668
|
-
}) : originalError;
|
|
669
|
-
|
|
670
|
-
const column = processedPos.column ?? originalError.column;
|
|
671
|
-
const index = indexMap.get(`${line}:${column}`);
|
|
672
|
-
const definition = index != null && sortedDefinitions.find((def) => def.start <= index && def.end >= index);
|
|
673
|
-
const suite = definition ? definition.task : file;
|
|
674
|
-
const state = suite.mode === "run" || suite.mode === "only" ? "fail" : suite.mode;
|
|
675
|
-
const errors = suite.result?.errors || [];
|
|
676
|
-
suite.result = {
|
|
603
|
+
}) : originalError, line = processedPos.line ?? originalError.line, column = processedPos.column ?? originalError.column, index = indexMap.get(`${line}:${column}`), definition = index != null && sortedDefinitions.find((def) => def.start <= index && def.end >= index), suite = definition ? definition.task : file, state = suite.mode === "run" || suite.mode === "only" ? "fail" : suite.mode, errors = suite.result?.errors || [];
|
|
604
|
+
if (suite.result = {
|
|
677
605
|
state,
|
|
678
606
|
errors
|
|
679
|
-
}
|
|
680
|
-
errors.push(error);
|
|
681
|
-
if (state === "fail") {
|
|
607
|
+
}, errors.push(error), state === "fail") {
|
|
682
608
|
if (suite.suite) markState(suite.suite, "fail");
|
|
683
609
|
else if (suite.file && suite !== suite.file) markState(suite.file, "fail");
|
|
684
610
|
}
|
|
685
|
-
});
|
|
686
|
-
|
|
687
|
-
});
|
|
688
|
-
typeErrors.forEach((errors, path) => {
|
|
611
|
+
}), this.markPassed(file);
|
|
612
|
+
}), typeErrors.forEach((errors, path) => {
|
|
689
613
|
if (!testFiles.has(path)) sourceErrors.push(...errors.map(({ error }) => error));
|
|
690
|
-
})
|
|
691
|
-
return {
|
|
614
|
+
}), {
|
|
692
615
|
files,
|
|
693
616
|
sourceErrors,
|
|
694
617
|
time: performance.now() - this._startTime
|
|
695
618
|
};
|
|
696
619
|
}
|
|
697
620
|
async parseTscLikeOutput(output) {
|
|
698
|
-
const errorsMap = await getRawErrsMapFromTsCompile(output);
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
const filepath = resolve(this.project.config.root, path);
|
|
702
|
-
const suiteErrors = errors.map((info) => {
|
|
621
|
+
const errorsMap = await getRawErrsMapFromTsCompile(output), typesErrors = /* @__PURE__ */ new Map();
|
|
622
|
+
return errorsMap.forEach((errors, path) => {
|
|
623
|
+
const filepath = resolve(this.project.config.root, path), suiteErrors = errors.map((info) => {
|
|
703
624
|
const limit = Error.stackTraceLimit;
|
|
704
625
|
Error.stackTraceLimit = 0;
|
|
705
626
|
// Some expect-type errors have the most useful information on the second line e.g. `This expression is not callable.\n Type 'ExpectString<number>' has no call signatures.`
|
|
706
|
-
const errMsg = info.errMsg.replace(/\r?\n\s*(Type .* has no call signatures)/g, " $1")
|
|
707
|
-
const error = new TypeCheckError(errMsg, [{
|
|
627
|
+
const errMsg = info.errMsg.replace(/\r?\n\s*(Type .* has no call signatures)/g, " $1"), error = new TypeCheckError(errMsg, [{
|
|
708
628
|
file: filepath,
|
|
709
629
|
line: info.line,
|
|
710
630
|
column: info.column,
|
|
711
631
|
method: ""
|
|
712
632
|
}]);
|
|
713
|
-
Error.stackTraceLimit = limit
|
|
714
|
-
return {
|
|
633
|
+
return Error.stackTraceLimit = limit, {
|
|
715
634
|
originalError: info,
|
|
716
635
|
error: {
|
|
717
636
|
name: error.name,
|
|
@@ -722,12 +641,10 @@ class Typechecker {
|
|
|
722
641
|
};
|
|
723
642
|
});
|
|
724
643
|
typesErrors.set(filepath, suiteErrors);
|
|
725
|
-
});
|
|
726
|
-
return typesErrors;
|
|
644
|
+
}), typesErrors;
|
|
727
645
|
}
|
|
728
646
|
async stop() {
|
|
729
|
-
this.process?.kill();
|
|
730
|
-
this.process = void 0;
|
|
647
|
+
this.process?.kill(), this.process = void 0;
|
|
731
648
|
}
|
|
732
649
|
async ensurePackageInstalled(ctx, checker) {
|
|
733
650
|
if (checker !== "tsc" && checker !== "vue-tsc") return;
|
|
@@ -741,8 +658,7 @@ class Typechecker {
|
|
|
741
658
|
return this._output;
|
|
742
659
|
}
|
|
743
660
|
async spawn() {
|
|
744
|
-
const { root, watch, typecheck } = this.project.config
|
|
745
|
-
const args = [
|
|
661
|
+
const { root, watch, typecheck } = this.project.config, args = [
|
|
746
662
|
"--noEmit",
|
|
747
663
|
"--pretty",
|
|
748
664
|
"false",
|
|
@@ -754,8 +670,7 @@ class Typechecker {
|
|
|
754
670
|
if (watch) args.push("--watch");
|
|
755
671
|
if (typecheck.allowJs) args.push("--allowJs", "--checkJs");
|
|
756
672
|
if (typecheck.tsconfig) args.push("-p", resolve(root, typecheck.tsconfig));
|
|
757
|
-
this._output = "";
|
|
758
|
-
this._startTime = performance.now();
|
|
673
|
+
this._output = "", this._startTime = performance.now();
|
|
759
674
|
const child = x(typecheck.checker, args, {
|
|
760
675
|
nodeOptions: {
|
|
761
676
|
cwd: root,
|
|
@@ -764,44 +679,26 @@ class Typechecker {
|
|
|
764
679
|
throwOnError: false
|
|
765
680
|
});
|
|
766
681
|
this.process = child.process;
|
|
767
|
-
let rerunTriggered = false;
|
|
768
|
-
let dataReceived = false;
|
|
682
|
+
let rerunTriggered = false, dataReceived = false;
|
|
769
683
|
return new Promise((resolve, reject) => {
|
|
770
684
|
if (!child.process || !child.process.stdout) {
|
|
771
685
|
reject(/* @__PURE__ */ new Error(`Failed to initialize ${typecheck.checker}. This is a bug in Vitest - please, open an issue with reproduction.`));
|
|
772
686
|
return;
|
|
773
687
|
}
|
|
774
688
|
child.process.stdout.on("data", (chunk) => {
|
|
775
|
-
dataReceived = true
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
this.
|
|
780
|
-
this._startTime = performance.now();
|
|
781
|
-
this._result.sourceErrors = [];
|
|
782
|
-
this._result.files = [];
|
|
783
|
-
this._tests = null;
|
|
784
|
-
rerunTriggered = true;
|
|
785
|
-
}
|
|
786
|
-
if (/Found \w+ errors*. Watching for/.test(this._output)) {
|
|
787
|
-
rerunTriggered = false;
|
|
788
|
-
this.prepareResults(this._output).then((result) => {
|
|
789
|
-
this._result = result;
|
|
790
|
-
this._onParseEnd?.(result);
|
|
791
|
-
});
|
|
792
|
-
this._output = "";
|
|
689
|
+
if (dataReceived = true, this._output += chunk, watch) {
|
|
690
|
+
if (this._output.includes("File change detected") && !rerunTriggered) this._onWatcherRerun?.(), this._startTime = performance.now(), this._result.sourceErrors = [], this._result.files = [], this._tests = null, rerunTriggered = true;
|
|
691
|
+
if (/Found \w+ errors*. Watching for/.test(this._output)) rerunTriggered = false, this.prepareResults(this._output).then((result) => {
|
|
692
|
+
this._result = result, this._onParseEnd?.(result);
|
|
693
|
+
}), this._output = "";
|
|
793
694
|
}
|
|
794
695
|
});
|
|
795
696
|
const timeout = setTimeout(() => reject(/* @__PURE__ */ new Error(`${typecheck.checker} spawn timed out`)), this.project.config.typecheck.spawnTimeout);
|
|
796
697
|
function onError(cause) {
|
|
797
|
-
clearTimeout(timeout);
|
|
798
|
-
reject(new Error("Spawning typechecker failed - is typescript installed?", { cause }));
|
|
698
|
+
clearTimeout(timeout), reject(new Error("Spawning typechecker failed - is typescript installed?", { cause }));
|
|
799
699
|
}
|
|
800
|
-
child.process.once("spawn", () => {
|
|
801
|
-
this._onParseStart?.()
|
|
802
|
-
child.process?.off("error", onError);
|
|
803
|
-
clearTimeout(timeout);
|
|
804
|
-
if (process.platform === "win32")
|
|
700
|
+
if (child.process.once("spawn", () => {
|
|
701
|
+
if (this._onParseStart?.(), child.process?.off("error", onError), clearTimeout(timeout), process.platform === "win32")
|
|
805
702
|
// on Windows, the process might be spawned but fail to start
|
|
806
703
|
// we wait for a potential error here. if "close" event didn't trigger,
|
|
807
704
|
// we resolve the promise
|
|
@@ -809,8 +706,7 @@ class Typechecker {
|
|
|
809
706
|
resolve({ result: child });
|
|
810
707
|
}, 200);
|
|
811
708
|
else resolve({ result: child });
|
|
812
|
-
})
|
|
813
|
-
if (process.platform === "win32") child.process.once("close", (code) => {
|
|
709
|
+
}), process.platform === "win32") child.process.once("close", (code) => {
|
|
814
710
|
if (code != null && code !== 0 && !dataReceived) onError(/* @__PURE__ */ new Error(`The ${typecheck.checker} command exited with code ${code}.`));
|
|
815
711
|
});
|
|
816
712
|
child.process.once("error", onError);
|
|
@@ -818,13 +714,8 @@ class Typechecker {
|
|
|
818
714
|
}
|
|
819
715
|
async start() {
|
|
820
716
|
if (this.process) return;
|
|
821
|
-
const { watch } = this.project.config;
|
|
822
|
-
|
|
823
|
-
if (!watch) {
|
|
824
|
-
await child;
|
|
825
|
-
this._result = await this.prepareResults(this._output);
|
|
826
|
-
await this._onParseEnd?.(this._result);
|
|
827
|
-
}
|
|
717
|
+
const { watch } = this.project.config, { result: child } = await this.spawn();
|
|
718
|
+
if (!watch) await child, this._result = await this.prepareResults(this._output), await this._onParseEnd?.(this._result);
|
|
828
719
|
}
|
|
829
720
|
getResult() {
|
|
830
721
|
return this._result;
|
|
@@ -833,12 +724,10 @@ class Typechecker {
|
|
|
833
724
|
return Object.values(this._tests || {}).map((i) => i.file);
|
|
834
725
|
}
|
|
835
726
|
getTestPacksAndEvents() {
|
|
836
|
-
const packs = [];
|
|
837
|
-
const events = [];
|
|
727
|
+
const packs = [], events = [];
|
|
838
728
|
for (const { file } of Object.values(this._tests || {})) {
|
|
839
729
|
const result = convertTasksToEvents(file);
|
|
840
|
-
packs.push(...result.packs);
|
|
841
|
-
events.push(...result.events);
|
|
730
|
+
packs.push(...result.packs), events.push(...result.events);
|
|
842
731
|
}
|
|
843
732
|
return {
|
|
844
733
|
packs,
|
|
@@ -861,11 +750,10 @@ function findGeneratedPosition(traceMap, { line, column, source }) {
|
|
|
861
750
|
if (m.source === source && m.originalLine !== null && m.originalColumn !== null && (line === m.originalLine ? column < m.originalColumn : line < m.originalLine)) mappings.push(m);
|
|
862
751
|
});
|
|
863
752
|
const next = mappings.sort((a, b) => a.originalLine === b.originalLine ? a.originalColumn - b.originalColumn : a.originalLine - b.originalLine).at(0);
|
|
864
|
-
|
|
753
|
+
return next ? {
|
|
865
754
|
line: next.generatedLine,
|
|
866
755
|
column: next.generatedColumn
|
|
867
|
-
}
|
|
868
|
-
return {
|
|
756
|
+
} : {
|
|
869
757
|
line: null,
|
|
870
758
|
column: null
|
|
871
759
|
};
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { parseRegexp } from '@vitest/utils';
|
|
2
2
|
|
|
3
|
-
const REGEXP_WRAP_PREFIX = "$$vitest:";
|
|
4
|
-
// Store global APIs in case process is overwritten by tests
|
|
5
|
-
const processSend = process.send?.bind(process);
|
|
6
|
-
const processOn = process.on?.bind(process);
|
|
7
|
-
const processOff = process.off?.bind(process);
|
|
8
|
-
const dispose = [];
|
|
3
|
+
const REGEXP_WRAP_PREFIX = "$$vitest:", processSend = process.send?.bind(process), processOn = process.on?.bind(process), processOff = process.off?.bind(process), dispose = [];
|
|
9
4
|
function createThreadsRpcOptions({ port }) {
|
|
10
5
|
return {
|
|
11
6
|
post: (v) => {
|
|
@@ -31,12 +26,9 @@ function createForksRpcOptions(nodeV8) {
|
|
|
31
26
|
},
|
|
32
27
|
on(fn) {
|
|
33
28
|
const handler = (message, ...extras) => {
|
|
34
|
-
|
|
35
|
-
if (message?.__tinypool_worker_message__) return;
|
|
36
|
-
return fn(message, ...extras);
|
|
29
|
+
if (!message?.__tinypool_worker_message__) return fn(message, ...extras);
|
|
37
30
|
};
|
|
38
|
-
processOn("message", handler);
|
|
39
|
-
dispose.push(() => processOff("message", handler));
|
|
31
|
+
processOn("message", handler), dispose.push(() => processOff("message", handler));
|
|
40
32
|
}
|
|
41
33
|
};
|
|
42
34
|
}
|
|
@@ -49,8 +41,7 @@ function unwrapSerializableConfig(config) {
|
|
|
49
41
|
if (testNamePattern.startsWith(REGEXP_WRAP_PREFIX)) config.testNamePattern = parseRegexp(testNamePattern.slice(9));
|
|
50
42
|
}
|
|
51
43
|
if (config.defines && Array.isArray(config.defines.keys) && config.defines.original) {
|
|
52
|
-
const { keys, original } = config.defines;
|
|
53
|
-
const defines = {};
|
|
44
|
+
const { keys, original } = config.defines, defines = {};
|
|
54
45
|
// Apply all keys from the original. Entries which had undefined value are missing from original now
|
|
55
46
|
for (const key of keys) defines[key] = original[key];
|
|
56
47
|
config.defines = defines;
|
|
@@ -11,13 +11,12 @@ function getWorkerState() {
|
|
|
11
11
|
return workerState;
|
|
12
12
|
}
|
|
13
13
|
function provideWorkerState(context, state) {
|
|
14
|
-
Object.defineProperty(context, NAME_WORKER_STATE, {
|
|
14
|
+
return Object.defineProperty(context, NAME_WORKER_STATE, {
|
|
15
15
|
value: state,
|
|
16
16
|
configurable: true,
|
|
17
17
|
writable: true,
|
|
18
18
|
enumerable: false
|
|
19
|
-
});
|
|
20
|
-
return state;
|
|
19
|
+
}), state;
|
|
21
20
|
}
|
|
22
21
|
function getCurrentEnvironment() {
|
|
23
22
|
const state = getWorkerState();
|
|
@@ -39,11 +38,7 @@ function resetModules(modules, resetMocks = false) {
|
|
|
39
38
|
...!resetMocks ? [/^mock:/] : []
|
|
40
39
|
];
|
|
41
40
|
modules.idToModuleMap.forEach((node, path) => {
|
|
42
|
-
|
|
43
|
-
node.promise = void 0;
|
|
44
|
-
node.exports = void 0;
|
|
45
|
-
node.evaluated = false;
|
|
46
|
-
node.importers.clear();
|
|
41
|
+
skipPaths.some((re) => re.test(path)) || (node.promise = void 0, node.exports = void 0, node.evaluated = false, node.importers.clear());
|
|
47
42
|
});
|
|
48
43
|
}
|
|
49
44
|
function waitNextTick() {
|
|
@@ -52,13 +47,9 @@ function waitNextTick() {
|
|
|
52
47
|
}
|
|
53
48
|
async function waitForImportsToResolve() {
|
|
54
49
|
await waitNextTick();
|
|
55
|
-
const state = getWorkerState();
|
|
56
|
-
const promises = [];
|
|
57
|
-
const resolvingCount = state.resolvingModules.size;
|
|
50
|
+
const state = getWorkerState(), promises = [], resolvingCount = state.resolvingModules.size;
|
|
58
51
|
for (const [_, mod] of state.evaluatedModules.idToModuleMap) if (mod.promise && !mod.evaluated) promises.push(mod.promise);
|
|
59
|
-
|
|
60
|
-
await Promise.allSettled(promises);
|
|
61
|
-
await waitForImportsToResolve();
|
|
52
|
+
!promises.length && !resolvingCount || (await Promise.allSettled(promises), await waitForImportsToResolve());
|
|
62
53
|
}
|
|
63
54
|
|
|
64
55
|
export { getCurrentEnvironment as a, getWorkerState as g, isChildProcess as i, provideWorkerState as p, resetModules as r, setProcessTitle as s, waitForImportsToResolve as w };
|