vitest 3.2.3 → 4.0.0-beta.1
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 -5
- package/dist/browser.js +1 -1
- package/dist/chunks/{base.Cg0miDlQ.js → base.Bj3pWTr1.js} +1 -1
- package/dist/chunks/browser.d.q8Z0P0q1.d.ts +18 -0
- package/dist/chunks/{cac.Cs_fZ7zn.js → cac.D3EzDDZd.js} +11 -19
- package/dist/chunks/{cli-api.C37Ou0i1.js → cli-api.Dn5gKePv.js} +15 -13
- package/dist/chunks/{config.d.D2ROskhv.d.ts → config.d.HJdfX-8k.d.ts} +1 -2
- package/dist/chunks/{coverage.D1a3dTnj.js → coverage.Cwa-XhJt.js} +68 -26
- package/dist/chunks/{defaults.B7q_naMc.js → defaults.CXFFjsi8.js} +2 -42
- package/dist/chunks/environment.d.CUq4cUgQ.d.ts +44 -0
- package/dist/chunks/{global.d.MAmajcmJ.d.ts → global.d.CVbXEflG.d.ts} +7 -29
- package/dist/chunks/{globals.DEHgCU4V.js → globals.Cxal6MLI.js} +1 -1
- package/dist/chunks/{index.CJ0plNrh.js → index.B521nVV-.js} +4 -2
- package/dist/chunks/{index.CdQS2e2Q.js → index.BWf_gE5n.js} +0 -2
- package/dist/chunks/{index.CX5aIIXH.js → index.CZI_8rVt.js} +231 -240
- package/dist/chunks/{index.BbB8_kAK.js → index.D-VkfKhf.js} +2 -2
- package/dist/chunks/{index.CSxmp_dI.js → index.TfbsX-3I.js} +1 -1
- package/dist/chunks/plugin.d.C2EcJUjo.d.ts +9 -0
- package/dist/chunks/{reporters.d.DL9pg5DB.d.ts → reporters.d.DxZg19fy.d.ts} +2213 -2207
- package/dist/chunks/{rpc.Iovn4oWe.js → rpc.CsFtxqeq.js} +5 -5
- package/dist/chunks/{runBaseTests.Dd85QTll.js → runBaseTests.BC7ZIH5L.js} +5 -5
- package/dist/chunks/{setup-common.Dd054P77.js → setup-common.D7ZqXFx-.js} +1 -1
- package/dist/chunks/{worker.d.DvqK5Vmu.d.ts → worker.d.CmvJfRGs.d.ts} +1 -1
- package/dist/chunks/{worker.d.tQu2eJQy.d.ts → worker.d.DoNjFAiv.d.ts} +7 -13
- package/dist/cli.js +9 -9
- package/dist/config.cjs +2 -49
- package/dist/config.d.ts +36 -30
- package/dist/config.js +2 -8
- package/dist/coverage.d.ts +15 -9
- package/dist/coverage.js +7 -6
- package/dist/environments.d.ts +2 -3
- package/dist/execute.d.ts +3 -5
- package/dist/index.d.ts +23 -177
- package/dist/index.js +1 -1
- package/dist/node.d.ts +38 -26
- package/dist/node.js +15 -21
- package/dist/reporters.d.ts +9 -9
- package/dist/reporters.js +12 -12
- package/dist/runners.d.ts +1 -2
- package/dist/runners.js +3 -2
- package/dist/worker.js +2 -2
- package/dist/workers/forks.js +1 -1
- package/dist/workers/runVmTests.js +5 -5
- package/dist/workers/threads.js +1 -1
- package/dist/workers.d.ts +4 -7
- package/dist/workers.js +3 -3
- package/package.json +16 -16
- package/dist/chunks/environment.d.cL3nLXbE.d.ts +0 -119
- package/dist/chunks/vite.d.CtvOcEqC.d.ts +0 -25
- package/dist/chunks/{typechecker.DRKU1-1g.js → typechecker.CVytUJuF.js} +26 -26
|
@@ -29,8 +29,10 @@ function createBirpc(functions, options) {
|
|
|
29
29
|
return functions;
|
|
30
30
|
if (method === "$close")
|
|
31
31
|
return close;
|
|
32
|
+
if (method === "$closed")
|
|
33
|
+
return closed;
|
|
32
34
|
if (method === "then" && !eventNames.includes("then") && !("then" in functions))
|
|
33
|
-
return
|
|
35
|
+
return undefined;
|
|
34
36
|
const sendEvent = (...args) => {
|
|
35
37
|
post(serialize({ m: method, a: args, t: TYPE_REQUEST }));
|
|
36
38
|
};
|
|
@@ -45,7 +47,7 @@ function createBirpc(functions, options) {
|
|
|
45
47
|
try {
|
|
46
48
|
await _promise;
|
|
47
49
|
} finally {
|
|
48
|
-
_promise =
|
|
50
|
+
_promise = undefined;
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
return new Promise((resolve, reject) => {
|
|
@@ -7,8 +7,6 @@ import { assert, should } from 'chai';
|
|
|
7
7
|
|
|
8
8
|
const assertType = function assertType() {};
|
|
9
9
|
|
|
10
|
-
// TODO: deprecate <reference types="vitest" /> in favor of `<reference types="vitest/config" />`
|
|
11
|
-
|
|
12
10
|
var VitestIndex = /*#__PURE__*/Object.freeze({
|
|
13
11
|
__proto__: null,
|
|
14
12
|
afterAll: afterAll,
|
|
@@ -1,19 +1,230 @@
|
|
|
1
|
+
import { existsSync, readFileSync, promises } from 'node:fs';
|
|
2
|
+
import { mkdir, writeFile, readdir, stat, readFile } from 'node:fs/promises';
|
|
3
|
+
import { resolve, dirname, isAbsolute, relative, basename, normalize } from 'pathe';
|
|
4
|
+
import { g as getOutputFile, h as hasFailedSnapshot, T as TypeCheckError } from './typechecker.CVytUJuF.js';
|
|
1
5
|
import { performance as performance$1 } from 'node:perf_hooks';
|
|
2
|
-
import { getTestName,
|
|
6
|
+
import { getTestName, getFullName, hasFailed, getTests, getSuites, getTasks } from '@vitest/runner/utils';
|
|
3
7
|
import { slash, toArray, isPrimitive, inspect, positionToOffset, lineSplitRE } from '@vitest/utils';
|
|
4
8
|
import { parseStacktrace, parseErrorStacktrace } from '@vitest/utils/source-map';
|
|
5
|
-
import { isAbsolute, relative, dirname, basename, resolve, normalize } from 'pathe';
|
|
6
9
|
import c from 'tinyrainbow';
|
|
7
10
|
import { i as isTTY } from './env.D4Lgay0q.js';
|
|
8
|
-
import { h as hasFailedSnapshot, g as getOutputFile, T as TypeCheckError } from './typechecker.DRKU1-1g.js';
|
|
9
11
|
import { stripVTControlCharacters } from 'node:util';
|
|
10
|
-
import { existsSync, readFileSync, promises } from 'node:fs';
|
|
11
|
-
import { mkdir, writeFile, readdir, stat, readFile } from 'node:fs/promises';
|
|
12
12
|
import { Console } from 'node:console';
|
|
13
13
|
import { Writable } from 'node:stream';
|
|
14
14
|
import { createRequire } from 'node:module';
|
|
15
15
|
import { hostname } from 'node:os';
|
|
16
16
|
|
|
17
|
+
/// <reference types="../types/index.d.ts" />
|
|
18
|
+
|
|
19
|
+
// (c) 2020-present Andrea Giammarchi
|
|
20
|
+
|
|
21
|
+
const {parse: $parse, stringify: $stringify} = JSON;
|
|
22
|
+
const {keys} = Object;
|
|
23
|
+
|
|
24
|
+
const Primitive = String; // it could be Number
|
|
25
|
+
const primitive = 'string'; // it could be 'number'
|
|
26
|
+
|
|
27
|
+
const ignore = {};
|
|
28
|
+
const object = 'object';
|
|
29
|
+
|
|
30
|
+
const noop = (_, value) => value;
|
|
31
|
+
|
|
32
|
+
const primitives = value => (
|
|
33
|
+
value instanceof Primitive ? Primitive(value) : value
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const Primitives = (_, value) => (
|
|
37
|
+
typeof value === primitive ? new Primitive(value) : value
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const revive = (input, parsed, output, $) => {
|
|
41
|
+
const lazy = [];
|
|
42
|
+
for (let ke = keys(output), {length} = ke, y = 0; y < length; y++) {
|
|
43
|
+
const k = ke[y];
|
|
44
|
+
const value = output[k];
|
|
45
|
+
if (value instanceof Primitive) {
|
|
46
|
+
const tmp = input[value];
|
|
47
|
+
if (typeof tmp === object && !parsed.has(tmp)) {
|
|
48
|
+
parsed.add(tmp);
|
|
49
|
+
output[k] = ignore;
|
|
50
|
+
lazy.push({k, a: [input, parsed, tmp, $]});
|
|
51
|
+
}
|
|
52
|
+
else
|
|
53
|
+
output[k] = $.call(output, k, tmp);
|
|
54
|
+
}
|
|
55
|
+
else if (output[k] !== ignore)
|
|
56
|
+
output[k] = $.call(output, k, value);
|
|
57
|
+
}
|
|
58
|
+
for (let {length} = lazy, i = 0; i < length; i++) {
|
|
59
|
+
const {k, a} = lazy[i];
|
|
60
|
+
output[k] = $.call(output, k, revive.apply(null, a));
|
|
61
|
+
}
|
|
62
|
+
return output;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const set = (known, input, value) => {
|
|
66
|
+
const index = Primitive(input.push(value) - 1);
|
|
67
|
+
known.set(value, index);
|
|
68
|
+
return index;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Converts a specialized flatted string into a JS value.
|
|
73
|
+
* @param {string} text
|
|
74
|
+
* @param {(this: any, key: string, value: any) => any} [reviver]
|
|
75
|
+
* @returns {any}
|
|
76
|
+
*/
|
|
77
|
+
const parse = (text, reviver) => {
|
|
78
|
+
const input = $parse(text, Primitives).map(primitives);
|
|
79
|
+
const value = input[0];
|
|
80
|
+
const $ = reviver || noop;
|
|
81
|
+
const tmp = typeof value === object && value ?
|
|
82
|
+
revive(input, new Set, value, $) :
|
|
83
|
+
value;
|
|
84
|
+
return $.call({'': tmp}, '', tmp);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Converts a JS value into a specialized flatted string.
|
|
89
|
+
* @param {any} value
|
|
90
|
+
* @param {((this: any, key: string, value: any) => any) | (string | number)[] | null | undefined} [replacer]
|
|
91
|
+
* @param {string | number | undefined} [space]
|
|
92
|
+
* @returns {string}
|
|
93
|
+
*/
|
|
94
|
+
const stringify = (value, replacer, space) => {
|
|
95
|
+
const $ = replacer && typeof replacer === object ?
|
|
96
|
+
(k, v) => (k === '' || -1 < replacer.indexOf(k) ? v : void 0) :
|
|
97
|
+
(replacer || noop);
|
|
98
|
+
const known = new Map;
|
|
99
|
+
const input = [];
|
|
100
|
+
const output = [];
|
|
101
|
+
let i = +set(known, input, $.call({'': value}, '', value));
|
|
102
|
+
let firstRun = !i;
|
|
103
|
+
while (i < input.length) {
|
|
104
|
+
firstRun = true;
|
|
105
|
+
output[i] = $stringify(input[i++], replace, space);
|
|
106
|
+
}
|
|
107
|
+
return '[' + output.join(',') + ']';
|
|
108
|
+
function replace(key, value) {
|
|
109
|
+
if (firstRun) {
|
|
110
|
+
firstRun = !firstRun;
|
|
111
|
+
return value;
|
|
112
|
+
}
|
|
113
|
+
const after = $.call(this, key, value);
|
|
114
|
+
switch (typeof after) {
|
|
115
|
+
case object:
|
|
116
|
+
if (after === null) return after;
|
|
117
|
+
case primitive:
|
|
118
|
+
return known.get(after) || set(known, input, after);
|
|
119
|
+
}
|
|
120
|
+
return after;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
class BlobReporter {
|
|
125
|
+
start = 0;
|
|
126
|
+
ctx;
|
|
127
|
+
options;
|
|
128
|
+
constructor(options) {
|
|
129
|
+
this.options = options;
|
|
130
|
+
}
|
|
131
|
+
onInit(ctx) {
|
|
132
|
+
if (ctx.config.watch) throw new Error("Blob reporter is not supported in watch mode");
|
|
133
|
+
this.ctx = ctx;
|
|
134
|
+
this.start = performance.now();
|
|
135
|
+
}
|
|
136
|
+
async onFinished(files = [], errors = [], coverage) {
|
|
137
|
+
const executionTime = performance.now() - this.start;
|
|
138
|
+
let outputFile = this.options.outputFile ?? getOutputFile(this.ctx.config, "blob");
|
|
139
|
+
if (!outputFile) {
|
|
140
|
+
const shard = this.ctx.config.shard;
|
|
141
|
+
outputFile = shard ? `.vitest-reports/blob-${shard.index}-${shard.count}.json` : ".vitest-reports/blob.json";
|
|
142
|
+
}
|
|
143
|
+
const modules = this.ctx.projects.map((project) => {
|
|
144
|
+
return [project.name, [...project.vite.moduleGraph.idToModuleMap.entries()].map((mod) => {
|
|
145
|
+
if (!mod[1].file) return null;
|
|
146
|
+
return [
|
|
147
|
+
mod[0],
|
|
148
|
+
mod[1].file,
|
|
149
|
+
mod[1].url
|
|
150
|
+
];
|
|
151
|
+
}).filter((x) => x != null)];
|
|
152
|
+
});
|
|
153
|
+
const report = [
|
|
154
|
+
this.ctx.version,
|
|
155
|
+
files,
|
|
156
|
+
errors,
|
|
157
|
+
modules,
|
|
158
|
+
coverage,
|
|
159
|
+
executionTime
|
|
160
|
+
];
|
|
161
|
+
const reportFile = resolve(this.ctx.config.root, outputFile);
|
|
162
|
+
await writeBlob(report, reportFile);
|
|
163
|
+
this.ctx.logger.log("blob report written to", reportFile);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
async function writeBlob(content, filename) {
|
|
167
|
+
const report = stringify(content);
|
|
168
|
+
const dir = dirname(filename);
|
|
169
|
+
if (!existsSync(dir)) await mkdir(dir, { recursive: true });
|
|
170
|
+
await writeFile(filename, report, "utf-8");
|
|
171
|
+
}
|
|
172
|
+
async function readBlobs(currentVersion, blobsDirectory, projectsArray) {
|
|
173
|
+
// using process.cwd() because --merge-reports can only be used in CLI
|
|
174
|
+
const resolvedDir = resolve(process.cwd(), blobsDirectory);
|
|
175
|
+
const blobsFiles = await readdir(resolvedDir);
|
|
176
|
+
const promises = blobsFiles.map(async (filename) => {
|
|
177
|
+
const fullPath = resolve(resolvedDir, filename);
|
|
178
|
+
const stats = await stat(fullPath);
|
|
179
|
+
if (!stats.isFile()) throw new TypeError(`vitest.mergeReports() expects all paths in "${blobsDirectory}" to be files generated by the blob reporter, but "${filename}" is not a file`);
|
|
180
|
+
const content = await readFile(fullPath, "utf-8");
|
|
181
|
+
const [version, files, errors, moduleKeys, coverage, executionTime] = parse(content);
|
|
182
|
+
if (!version) throw new TypeError(`vitest.mergeReports() expects all paths in "${blobsDirectory}" to be files generated by the blob reporter, but "${filename}" is not a valid blob file`);
|
|
183
|
+
return {
|
|
184
|
+
version,
|
|
185
|
+
files,
|
|
186
|
+
errors,
|
|
187
|
+
moduleKeys,
|
|
188
|
+
coverage,
|
|
189
|
+
file: filename,
|
|
190
|
+
executionTime
|
|
191
|
+
};
|
|
192
|
+
});
|
|
193
|
+
const blobs = await Promise.all(promises);
|
|
194
|
+
if (!blobs.length) throw new Error(`vitest.mergeReports() requires at least one blob file in "${blobsDirectory}" directory, but none were found`);
|
|
195
|
+
const versions = new Set(blobs.map((blob) => blob.version));
|
|
196
|
+
if (versions.size > 1) throw new Error(`vitest.mergeReports() requires all blob files to be generated by the same Vitest version, received\n\n${blobs.map((b) => `- "${b.file}" uses v${b.version}`).join("\n")}`);
|
|
197
|
+
if (!versions.has(currentVersion)) throw new Error(`the blobs in "${blobsDirectory}" were generated by a different version of Vitest. Expected v${currentVersion}, but received v${blobs[0].version}`);
|
|
198
|
+
// fake module graph - it is used to check if module is imported, but we don't use values inside
|
|
199
|
+
const projects = Object.fromEntries(projectsArray.map((p) => [p.name, p]));
|
|
200
|
+
blobs.forEach((blob) => {
|
|
201
|
+
blob.moduleKeys.forEach(([projectName, moduleIds]) => {
|
|
202
|
+
const project = projects[projectName];
|
|
203
|
+
if (!project) return;
|
|
204
|
+
moduleIds.forEach(([moduleId, file, url]) => {
|
|
205
|
+
const moduleNode = project.vite.moduleGraph.createFileOnlyEntry(file);
|
|
206
|
+
moduleNode.url = url;
|
|
207
|
+
moduleNode.id = moduleId;
|
|
208
|
+
project.vite.moduleGraph.idToModuleMap.set(moduleId, moduleNode);
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
const files = blobs.flatMap((blob) => blob.files).sort((f1, f2) => {
|
|
213
|
+
const time1 = f1.result?.startTime || 0;
|
|
214
|
+
const time2 = f2.result?.startTime || 0;
|
|
215
|
+
return time1 - time2;
|
|
216
|
+
});
|
|
217
|
+
const errors = blobs.flatMap((blob) => blob.errors);
|
|
218
|
+
const coverages = blobs.map((blob) => blob.coverage);
|
|
219
|
+
const executionTimes = blobs.map((blob) => blob.executionTime);
|
|
220
|
+
return {
|
|
221
|
+
files,
|
|
222
|
+
errors,
|
|
223
|
+
coverages,
|
|
224
|
+
executionTimes
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
17
228
|
const F_RIGHT = "→";
|
|
18
229
|
const F_DOWN = "↓";
|
|
19
230
|
const F_DOWN_RIGHT = "↳";
|
|
@@ -299,6 +510,9 @@ class BaseReporter {
|
|
|
299
510
|
getTestName(test, separator) {
|
|
300
511
|
return getTestName(test, separator);
|
|
301
512
|
}
|
|
513
|
+
getFullName(test, separator) {
|
|
514
|
+
return getFullName(test, separator);
|
|
515
|
+
}
|
|
302
516
|
formatShortError(error) {
|
|
303
517
|
return `${F_RIGHT} ${error.message}`;
|
|
304
518
|
}
|
|
@@ -361,7 +575,7 @@ class BaseReporter {
|
|
|
361
575
|
const write = (msg) => output.write(msg);
|
|
362
576
|
let headerText = "unknown test";
|
|
363
577
|
const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : void 0;
|
|
364
|
-
if (task) headerText = getFullName(task, c.dim(" > "));
|
|
578
|
+
if (task) headerText = this.getFullName(task, c.dim(" > "));
|
|
365
579
|
else if (log.taskId && log.taskId !== "__vitest__unknown_test__") headerText = log.taskId;
|
|
366
580
|
write(c.gray(log.type + c.dim(` | ${headerText}\n`)) + log.content);
|
|
367
581
|
if (log.origin) {
|
|
@@ -385,8 +599,12 @@ class BaseReporter {
|
|
|
385
599
|
shouldLog(log, taskState) {
|
|
386
600
|
if (this.ctx.config.silent === true) return false;
|
|
387
601
|
if (this.ctx.config.silent === "passed-only" && taskState !== "failed") return false;
|
|
388
|
-
|
|
389
|
-
|
|
602
|
+
if (this.ctx.config.onConsoleLog) {
|
|
603
|
+
const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : void 0;
|
|
604
|
+
const entity = task && this.ctx.state.getReportedEntity(task);
|
|
605
|
+
const shouldLog = this.ctx.config.onConsoleLog(log.content, log.type, entity);
|
|
606
|
+
if (shouldLog === false) return shouldLog;
|
|
607
|
+
}
|
|
390
608
|
return true;
|
|
391
609
|
}
|
|
392
610
|
onServerRestart(reason) {
|
|
@@ -469,7 +687,7 @@ class BaseReporter {
|
|
|
469
687
|
for (const bench of topBenches) {
|
|
470
688
|
const group = bench.suite || bench.file;
|
|
471
689
|
if (!group) continue;
|
|
472
|
-
const groupName = getFullName(group, c.dim(" > "));
|
|
690
|
+
const groupName = this.getFullName(group, c.dim(" > "));
|
|
473
691
|
const project = this.ctx.projects.find((p) => p.name === bench.file.projectName);
|
|
474
692
|
this.log(` ${formatProjectName(project)}${bench.name}${c.dim(` - ${groupName}`)}`);
|
|
475
693
|
const siblings = group.tasks.filter((i) => i.meta.benchmark && i.result?.benchmark && i !== bench).sort((a, b) => a.result.benchmark.rank - b.result.benchmark.rank);
|
|
@@ -502,7 +720,7 @@ class BaseReporter {
|
|
|
502
720
|
const filepath = task?.filepath || "";
|
|
503
721
|
const projectName = task?.projectName || task.file?.projectName || "";
|
|
504
722
|
const project = this.ctx.projects.find((p) => p.name === projectName);
|
|
505
|
-
let name = getFullName(task, c.dim(" > "));
|
|
723
|
+
let name = this.getFullName(task, c.dim(" > "));
|
|
506
724
|
if (filepath) name += c.dim(` [ ${this.relative(filepath)} ]`);
|
|
507
725
|
this.ctx.logger.error(`${c.bgRed(c.bold(" FAIL "))} ${formatProjectName(project)}${name}`);
|
|
508
726
|
}
|
|
@@ -537,233 +755,6 @@ function sum(items, cb) {
|
|
|
537
755
|
}, 0);
|
|
538
756
|
}
|
|
539
757
|
|
|
540
|
-
class BasicReporter extends BaseReporter {
|
|
541
|
-
constructor() {
|
|
542
|
-
super();
|
|
543
|
-
this.isTTY = false;
|
|
544
|
-
}
|
|
545
|
-
onInit(ctx) {
|
|
546
|
-
super.onInit(ctx);
|
|
547
|
-
ctx.logger.deprecate(`'basic' reporter is deprecated and will be removed in Vitest v3.\nRemove 'basic' from 'reporters' option. To match 'basic' reporter 100%, use configuration:\n${JSON.stringify({ test: { reporters: [["default", { summary: false }]] } }, null, 2)}`);
|
|
548
|
-
}
|
|
549
|
-
reportSummary(files, errors) {
|
|
550
|
-
// non-tty mode doesn't add a new line
|
|
551
|
-
this.ctx.logger.log();
|
|
552
|
-
return super.reportSummary(files, errors);
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
/// <reference types="../types/index.d.ts" />
|
|
557
|
-
|
|
558
|
-
// (c) 2020-present Andrea Giammarchi
|
|
559
|
-
|
|
560
|
-
const {parse: $parse, stringify: $stringify} = JSON;
|
|
561
|
-
const {keys} = Object;
|
|
562
|
-
|
|
563
|
-
const Primitive = String; // it could be Number
|
|
564
|
-
const primitive = 'string'; // it could be 'number'
|
|
565
|
-
|
|
566
|
-
const ignore = {};
|
|
567
|
-
const object = 'object';
|
|
568
|
-
|
|
569
|
-
const noop = (_, value) => value;
|
|
570
|
-
|
|
571
|
-
const primitives = value => (
|
|
572
|
-
value instanceof Primitive ? Primitive(value) : value
|
|
573
|
-
);
|
|
574
|
-
|
|
575
|
-
const Primitives = (_, value) => (
|
|
576
|
-
typeof value === primitive ? new Primitive(value) : value
|
|
577
|
-
);
|
|
578
|
-
|
|
579
|
-
const revive = (input, parsed, output, $) => {
|
|
580
|
-
const lazy = [];
|
|
581
|
-
for (let ke = keys(output), {length} = ke, y = 0; y < length; y++) {
|
|
582
|
-
const k = ke[y];
|
|
583
|
-
const value = output[k];
|
|
584
|
-
if (value instanceof Primitive) {
|
|
585
|
-
const tmp = input[value];
|
|
586
|
-
if (typeof tmp === object && !parsed.has(tmp)) {
|
|
587
|
-
parsed.add(tmp);
|
|
588
|
-
output[k] = ignore;
|
|
589
|
-
lazy.push({k, a: [input, parsed, tmp, $]});
|
|
590
|
-
}
|
|
591
|
-
else
|
|
592
|
-
output[k] = $.call(output, k, tmp);
|
|
593
|
-
}
|
|
594
|
-
else if (output[k] !== ignore)
|
|
595
|
-
output[k] = $.call(output, k, value);
|
|
596
|
-
}
|
|
597
|
-
for (let {length} = lazy, i = 0; i < length; i++) {
|
|
598
|
-
const {k, a} = lazy[i];
|
|
599
|
-
output[k] = $.call(output, k, revive.apply(null, a));
|
|
600
|
-
}
|
|
601
|
-
return output;
|
|
602
|
-
};
|
|
603
|
-
|
|
604
|
-
const set = (known, input, value) => {
|
|
605
|
-
const index = Primitive(input.push(value) - 1);
|
|
606
|
-
known.set(value, index);
|
|
607
|
-
return index;
|
|
608
|
-
};
|
|
609
|
-
|
|
610
|
-
/**
|
|
611
|
-
* Converts a specialized flatted string into a JS value.
|
|
612
|
-
* @param {string} text
|
|
613
|
-
* @param {(this: any, key: string, value: any) => any} [reviver]
|
|
614
|
-
* @returns {any}
|
|
615
|
-
*/
|
|
616
|
-
const parse = (text, reviver) => {
|
|
617
|
-
const input = $parse(text, Primitives).map(primitives);
|
|
618
|
-
const value = input[0];
|
|
619
|
-
const $ = reviver || noop;
|
|
620
|
-
const tmp = typeof value === object && value ?
|
|
621
|
-
revive(input, new Set, value, $) :
|
|
622
|
-
value;
|
|
623
|
-
return $.call({'': tmp}, '', tmp);
|
|
624
|
-
};
|
|
625
|
-
|
|
626
|
-
/**
|
|
627
|
-
* Converts a JS value into a specialized flatted string.
|
|
628
|
-
* @param {any} value
|
|
629
|
-
* @param {((this: any, key: string, value: any) => any) | (string | number)[] | null | undefined} [replacer]
|
|
630
|
-
* @param {string | number | undefined} [space]
|
|
631
|
-
* @returns {string}
|
|
632
|
-
*/
|
|
633
|
-
const stringify = (value, replacer, space) => {
|
|
634
|
-
const $ = replacer && typeof replacer === object ?
|
|
635
|
-
(k, v) => (k === '' || -1 < replacer.indexOf(k) ? v : void 0) :
|
|
636
|
-
(replacer || noop);
|
|
637
|
-
const known = new Map;
|
|
638
|
-
const input = [];
|
|
639
|
-
const output = [];
|
|
640
|
-
let i = +set(known, input, $.call({'': value}, '', value));
|
|
641
|
-
let firstRun = !i;
|
|
642
|
-
while (i < input.length) {
|
|
643
|
-
firstRun = true;
|
|
644
|
-
output[i] = $stringify(input[i++], replace, space);
|
|
645
|
-
}
|
|
646
|
-
return '[' + output.join(',') + ']';
|
|
647
|
-
function replace(key, value) {
|
|
648
|
-
if (firstRun) {
|
|
649
|
-
firstRun = !firstRun;
|
|
650
|
-
return value;
|
|
651
|
-
}
|
|
652
|
-
const after = $.call(this, key, value);
|
|
653
|
-
switch (typeof after) {
|
|
654
|
-
case object:
|
|
655
|
-
if (after === null) return after;
|
|
656
|
-
case primitive:
|
|
657
|
-
return known.get(after) || set(known, input, after);
|
|
658
|
-
}
|
|
659
|
-
return after;
|
|
660
|
-
}
|
|
661
|
-
};
|
|
662
|
-
|
|
663
|
-
class BlobReporter {
|
|
664
|
-
start = 0;
|
|
665
|
-
ctx;
|
|
666
|
-
options;
|
|
667
|
-
constructor(options) {
|
|
668
|
-
this.options = options;
|
|
669
|
-
}
|
|
670
|
-
onInit(ctx) {
|
|
671
|
-
if (ctx.config.watch) throw new Error("Blob reporter is not supported in watch mode");
|
|
672
|
-
this.ctx = ctx;
|
|
673
|
-
this.start = performance.now();
|
|
674
|
-
}
|
|
675
|
-
async onFinished(files = [], errors = [], coverage) {
|
|
676
|
-
const executionTime = performance.now() - this.start;
|
|
677
|
-
let outputFile = this.options.outputFile ?? getOutputFile(this.ctx.config, "blob");
|
|
678
|
-
if (!outputFile) {
|
|
679
|
-
const shard = this.ctx.config.shard;
|
|
680
|
-
outputFile = shard ? `.vitest-reports/blob-${shard.index}-${shard.count}.json` : ".vitest-reports/blob.json";
|
|
681
|
-
}
|
|
682
|
-
const modules = this.ctx.projects.map((project) => {
|
|
683
|
-
return [project.name, [...project.vite.moduleGraph.idToModuleMap.entries()].map((mod) => {
|
|
684
|
-
if (!mod[1].file) return null;
|
|
685
|
-
return [
|
|
686
|
-
mod[0],
|
|
687
|
-
mod[1].file,
|
|
688
|
-
mod[1].url
|
|
689
|
-
];
|
|
690
|
-
}).filter((x) => x != null)];
|
|
691
|
-
});
|
|
692
|
-
const report = [
|
|
693
|
-
this.ctx.version,
|
|
694
|
-
files,
|
|
695
|
-
errors,
|
|
696
|
-
modules,
|
|
697
|
-
coverage,
|
|
698
|
-
executionTime
|
|
699
|
-
];
|
|
700
|
-
const reportFile = resolve(this.ctx.config.root, outputFile);
|
|
701
|
-
await writeBlob(report, reportFile);
|
|
702
|
-
this.ctx.logger.log("blob report written to", reportFile);
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
async function writeBlob(content, filename) {
|
|
706
|
-
const report = stringify(content);
|
|
707
|
-
const dir = dirname(filename);
|
|
708
|
-
if (!existsSync(dir)) await mkdir(dir, { recursive: true });
|
|
709
|
-
await writeFile(filename, report, "utf-8");
|
|
710
|
-
}
|
|
711
|
-
async function readBlobs(currentVersion, blobsDirectory, projectsArray) {
|
|
712
|
-
// using process.cwd() because --merge-reports can only be used in CLI
|
|
713
|
-
const resolvedDir = resolve(process.cwd(), blobsDirectory);
|
|
714
|
-
const blobsFiles = await readdir(resolvedDir);
|
|
715
|
-
const promises = blobsFiles.map(async (filename) => {
|
|
716
|
-
const fullPath = resolve(resolvedDir, filename);
|
|
717
|
-
const stats = await stat(fullPath);
|
|
718
|
-
if (!stats.isFile()) throw new TypeError(`vitest.mergeReports() expects all paths in "${blobsDirectory}" to be files generated by the blob reporter, but "${filename}" is not a file`);
|
|
719
|
-
const content = await readFile(fullPath, "utf-8");
|
|
720
|
-
const [version, files, errors, moduleKeys, coverage, executionTime] = parse(content);
|
|
721
|
-
if (!version) throw new TypeError(`vitest.mergeReports() expects all paths in "${blobsDirectory}" to be files generated by the blob reporter, but "${filename}" is not a valid blob file`);
|
|
722
|
-
return {
|
|
723
|
-
version,
|
|
724
|
-
files,
|
|
725
|
-
errors,
|
|
726
|
-
moduleKeys,
|
|
727
|
-
coverage,
|
|
728
|
-
file: filename,
|
|
729
|
-
executionTime
|
|
730
|
-
};
|
|
731
|
-
});
|
|
732
|
-
const blobs = await Promise.all(promises);
|
|
733
|
-
if (!blobs.length) throw new Error(`vitest.mergeReports() requires at least one blob file in "${blobsDirectory}" directory, but none were found`);
|
|
734
|
-
const versions = new Set(blobs.map((blob) => blob.version));
|
|
735
|
-
if (versions.size > 1) throw new Error(`vitest.mergeReports() requires all blob files to be generated by the same Vitest version, received\n\n${blobs.map((b) => `- "${b.file}" uses v${b.version}`).join("\n")}`);
|
|
736
|
-
if (!versions.has(currentVersion)) throw new Error(`the blobs in "${blobsDirectory}" were generated by a different version of Vitest. Expected v${currentVersion}, but received v${blobs[0].version}`);
|
|
737
|
-
// fake module graph - it is used to check if module is imported, but we don't use values inside
|
|
738
|
-
const projects = Object.fromEntries(projectsArray.map((p) => [p.name, p]));
|
|
739
|
-
blobs.forEach((blob) => {
|
|
740
|
-
blob.moduleKeys.forEach(([projectName, moduleIds]) => {
|
|
741
|
-
const project = projects[projectName];
|
|
742
|
-
if (!project) return;
|
|
743
|
-
moduleIds.forEach(([moduleId, file, url]) => {
|
|
744
|
-
const moduleNode = project.vite.moduleGraph.createFileOnlyEntry(file);
|
|
745
|
-
moduleNode.url = url;
|
|
746
|
-
moduleNode.id = moduleId;
|
|
747
|
-
project.vite.moduleGraph.idToModuleMap.set(moduleId, moduleNode);
|
|
748
|
-
});
|
|
749
|
-
});
|
|
750
|
-
});
|
|
751
|
-
const files = blobs.flatMap((blob) => blob.files).sort((f1, f2) => {
|
|
752
|
-
const time1 = f1.result?.startTime || 0;
|
|
753
|
-
const time2 = f2.result?.startTime || 0;
|
|
754
|
-
return time1 - time2;
|
|
755
|
-
});
|
|
756
|
-
const errors = blobs.flatMap((blob) => blob.errors);
|
|
757
|
-
const coverages = blobs.map((blob) => blob.coverage);
|
|
758
|
-
const executionTimes = blobs.map((blob) => blob.executionTime);
|
|
759
|
-
return {
|
|
760
|
-
files,
|
|
761
|
-
errors,
|
|
762
|
-
coverages,
|
|
763
|
-
executionTimes
|
|
764
|
-
};
|
|
765
|
-
}
|
|
766
|
-
|
|
767
758
|
const DEFAULT_RENDER_INTERVAL_MS = 1e3;
|
|
768
759
|
const ESC = "\x1B[";
|
|
769
760
|
const CLEAR_LINE = `${ESC}K`;
|
|
@@ -1364,7 +1355,7 @@ function printErrorInner(error, project, options) {
|
|
|
1364
1355
|
const stacks = options.parseErrorStacktrace(e);
|
|
1365
1356
|
const nearest = error instanceof TypeCheckError ? error.stacks[0] : stacks.find((stack) => {
|
|
1366
1357
|
try {
|
|
1367
|
-
return project.
|
|
1358
|
+
return project._vite && project.getModuleById(stack.file) && existsSync(stack.file);
|
|
1368
1359
|
} catch {
|
|
1369
1360
|
return false;
|
|
1370
1361
|
}
|
|
@@ -2014,6 +2005,7 @@ class JUnitReporter {
|
|
|
2014
2005
|
}
|
|
2015
2006
|
|
|
2016
2007
|
function yamlString(str) {
|
|
2008
|
+
if (!str) return "";
|
|
2017
2009
|
return `"${str.replace(/"/g, "\\\"")}"`;
|
|
2018
2010
|
}
|
|
2019
2011
|
function tapString(str) {
|
|
@@ -2165,7 +2157,6 @@ function getIndentation(suite, level = 1) {
|
|
|
2165
2157
|
|
|
2166
2158
|
const ReportersMap = {
|
|
2167
2159
|
"default": DefaultReporter,
|
|
2168
|
-
"basic": BasicReporter,
|
|
2169
2160
|
"blob": BlobReporter,
|
|
2170
2161
|
"verbose": VerboseReporter,
|
|
2171
2162
|
"dot": DotReporter,
|
|
@@ -2177,4 +2168,4 @@ const ReportersMap = {
|
|
|
2177
2168
|
"github-actions": GithubActionsReporter
|
|
2178
2169
|
};
|
|
2179
2170
|
|
|
2180
|
-
export {
|
|
2171
|
+
export { BlobReporter as B, DefaultReporter as D, F_RIGHT as F, GithubActionsReporter as G, HangingProcessReporter as H, JsonReporter as J, ReportersMap as R, TapFlatReporter as T, VerboseReporter as V, DotReporter as a, JUnitReporter as b, TapReporter as c, printError as d, errorBanner as e, formatProjectName as f, getStateSymbol as g, divider as h, generateCodeFrame as i, parse as p, readBlobs as r, stringify as s, truncateString as t, utils as u, withLabel as w };
|
|
@@ -1,8 +1,8 @@
|
|
|
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.D7ZqXFx-.js';
|
|
4
4
|
import { distDir } from '../path.js';
|
|
5
|
-
import { r as rpc } from './rpc.
|
|
5
|
+
import { r as rpc } from './rpc.CsFtxqeq.js';
|
|
6
6
|
import { g as getWorkerState } from './utils.XdZDrNZV.js';
|
|
7
7
|
|
|
8
8
|
function setupChaiConfig(config) {
|
|
@@ -2,7 +2,7 @@ import fs from 'node:fs';
|
|
|
2
2
|
import { getTasks, getFullName, getTests } from '@vitest/runner/utils';
|
|
3
3
|
import * as pathe from 'pathe';
|
|
4
4
|
import c from 'tinyrainbow';
|
|
5
|
-
import { g as getStateSymbol, t as truncateString, F as F_RIGHT, D as DefaultReporter, f as formatProjectName } from './index.
|
|
5
|
+
import { g as getStateSymbol, t as truncateString, F as F_RIGHT, D as DefaultReporter, f as formatProjectName } from './index.CZI_8rVt.js';
|
|
6
6
|
import { stripVTControlCharacters } from 'node:util';
|
|
7
7
|
import { notNullish } from '@vitest/utils';
|
|
8
8
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { V as Vitest, T as TestProject, a as TestProjectConfiguration } from './reporters.d.DxZg19fy.js';
|
|
2
|
+
|
|
3
|
+
interface VitestPluginContext {
|
|
4
|
+
vitest: Vitest;
|
|
5
|
+
project: TestProject;
|
|
6
|
+
injectTestProjects: (config: TestProjectConfiguration | TestProjectConfiguration[]) => Promise<TestProject[]>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type { VitestPluginContext as V };
|