vitest 2.1.4 → 2.2.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 +11 -11
- package/dist/browser.js +1 -1
- package/dist/chunks/{base.C3xNdjV6.js → base.BS0HhLXd.js} +1 -1
- package/dist/chunks/{cac.DrfPaMvZ.js → cac.Z91LBqmg.js} +56 -7
- package/dist/chunks/{cli-api.CKrRYkw8.js → cli-api.DVJJMJHj.js} +123 -80
- package/dist/chunks/{config.Crbj2GAb.d.ts → config.CPguQ7J1.d.ts} +2 -2
- package/dist/chunks/{environment.LoooBwUu.d.ts → environment.CT0jpO-1.d.ts} +2 -1
- package/dist/chunks/{globals.Bp645TTJ.js → globals.BCGEw6ON.js} +2 -2
- package/dist/chunks/{index.D3d79vc8.js → index.BjjsHdBb.js} +1 -1
- package/dist/chunks/{index.Dqe5k2Rk.js → index.DD5eTY2y.js} +2 -8
- package/dist/chunks/{index.Bn81VaWg.js → index.DLRzErGF.js} +240 -318
- package/dist/chunks/{index.BMoXz_-n.js → index.K90BXFOx.js} +1 -1
- package/dist/chunks/{reporters.anwo7Y6a.d.ts → reporters.B_9uUTGW.d.ts} +148 -22
- package/dist/chunks/{resolveConfig.DPmbhVlP.js → resolveConfig.CQIc6fe7.js} +8 -4
- package/dist/chunks/{runBaseTests.Dm-659zB.js → runBaseTests.B7hcVT-s.js} +4 -4
- package/dist/chunks/{setup-common.DDmVKp6O.js → setup-common.BfGt8K-K.js} +4 -1
- package/dist/chunks/{utils.BB4zjzR8.js → utils.DNoFbBUZ.js} +6 -2
- package/dist/chunks/{vi.JMQoNY_Z.js → vi.BlPttogV.js} +91 -4
- package/dist/chunks/{vite.BdBj-UWY.d.ts → vite.Bvms8Xir.d.ts} +1 -1
- package/dist/chunks/{vm.jpyrB0xy.js → vm.Zr4qWzDJ.js} +3 -0
- package/dist/chunks/{worker.BAlI9hII.d.ts → worker.9VY11NZs.d.ts} +3 -2
- package/dist/chunks/{worker.DHnGaO2M.d.ts → worker.Qz1UB4Fv.d.ts} +1 -1
- package/dist/cli.js +1 -1
- package/dist/config.d.ts +10 -9
- package/dist/coverage.d.ts +9 -112
- package/dist/coverage.js +1 -1
- package/dist/environments.d.ts +2 -2
- package/dist/environments.js +1 -1
- package/dist/execute.d.ts +4 -3
- package/dist/index.d.ts +39 -10
- package/dist/index.js +2 -2
- package/dist/node.d.ts +13 -11
- package/dist/node.js +7 -7
- package/dist/reporters.d.ts +10 -9
- package/dist/reporters.js +2 -2
- package/dist/runners.d.ts +3 -1
- package/dist/runners.js +4 -1
- package/dist/worker.js +6 -2
- package/dist/workers/forks.js +1 -1
- package/dist/workers/runVmTests.js +4 -4
- package/dist/workers/threads.js +1 -1
- package/dist/workers/vmForks.js +1 -1
- package/dist/workers/vmThreads.js +1 -1
- package/dist/workers.d.ts +5 -4
- package/dist/workers.js +4 -3
- package/package.json +15 -15
|
@@ -3,7 +3,7 @@ import { getTests, getTestName, hasFailed, getFullName, getSuites, getTasks } fr
|
|
|
3
3
|
import * as pathe from 'pathe';
|
|
4
4
|
import { extname, relative, normalize, resolve, dirname } from 'pathe';
|
|
5
5
|
import c from 'tinyrainbow';
|
|
6
|
-
import { d as divider, F as F_POINTER,
|
|
6
|
+
import { d as divider, F as F_POINTER, w as withLabel, f as formatProjectName, a as formatTimeString, g as getStateSymbol, t as taskFail, b as F_RIGHT, c as F_CHECK, r as renderSnapshotSummary, e as getStateString, h as countTestErrors, i as getCols, j as getHookStateSymbol } from './utils.DNoFbBUZ.js';
|
|
7
7
|
import { stripVTControlCharacters } from 'node:util';
|
|
8
8
|
import { highlight, isPrimitive, inspect, positionToOffset, lineSplitRE, toArray, notNullish } from '@vitest/utils';
|
|
9
9
|
import { performance } from 'node:perf_hooks';
|
|
@@ -31,6 +31,10 @@ class TestProject {
|
|
|
31
31
|
* @experimental The public Vitest API is experimental and does not follow semver.
|
|
32
32
|
*/
|
|
33
33
|
workspaceProject;
|
|
34
|
+
/**
|
|
35
|
+
* Vite's dev server instance. Every workspace project has its own server.
|
|
36
|
+
*/
|
|
37
|
+
vite;
|
|
34
38
|
/**
|
|
35
39
|
* Resolved project configuration.
|
|
36
40
|
*/
|
|
@@ -46,6 +50,7 @@ class TestProject {
|
|
|
46
50
|
constructor(workspaceProject) {
|
|
47
51
|
this.workspaceProject = workspaceProject;
|
|
48
52
|
this.vitest = workspaceProject.ctx;
|
|
53
|
+
this.vite = workspaceProject.server;
|
|
49
54
|
this.globalConfig = workspaceProject.ctx.config;
|
|
50
55
|
this.config = workspaceProject.config;
|
|
51
56
|
this.name = workspaceProject.getName();
|
|
@@ -165,9 +170,22 @@ class TestCase extends ReportedTaskImplementation {
|
|
|
165
170
|
return void 0;
|
|
166
171
|
}
|
|
167
172
|
const state = result.state === "fail" ? "failed" : result.state === "pass" ? "passed" : "skipped";
|
|
173
|
+
if (state === "skipped") {
|
|
174
|
+
return {
|
|
175
|
+
state,
|
|
176
|
+
note: result.note,
|
|
177
|
+
errors: void 0
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
if (state === "passed") {
|
|
181
|
+
return {
|
|
182
|
+
state,
|
|
183
|
+
errors: result.errors
|
|
184
|
+
};
|
|
185
|
+
}
|
|
168
186
|
return {
|
|
169
187
|
state,
|
|
170
|
-
errors: result.errors
|
|
188
|
+
errors: result.errors || []
|
|
171
189
|
};
|
|
172
190
|
}
|
|
173
191
|
/**
|
|
@@ -2398,8 +2416,10 @@ function isWide(x) {
|
|
|
2398
2416
|
|| x === 0x25FE
|
|
2399
2417
|
|| x === 0x2614
|
|
2400
2418
|
|| x === 0x2615
|
|
2419
|
+
|| x >= 0x2630 && x <= 0x2637
|
|
2401
2420
|
|| x >= 0x2648 && x <= 0x2653
|
|
2402
2421
|
|| x === 0x267F
|
|
2422
|
+
|| x >= 0x268A && x <= 0x268F
|
|
2403
2423
|
|| x === 0x2693
|
|
2404
2424
|
|| x === 0x26A1
|
|
2405
2425
|
|| x === 0x26AA
|
|
@@ -2440,11 +2460,10 @@ function isWide(x) {
|
|
|
2440
2460
|
|| x >= 0x3099 && x <= 0x30FF
|
|
2441
2461
|
|| x >= 0x3105 && x <= 0x312F
|
|
2442
2462
|
|| x >= 0x3131 && x <= 0x318E
|
|
2443
|
-
|| x >= 0x3190 && x <=
|
|
2463
|
+
|| x >= 0x3190 && x <= 0x31E5
|
|
2444
2464
|
|| x >= 0x31EF && x <= 0x321E
|
|
2445
2465
|
|| x >= 0x3220 && x <= 0x3247
|
|
2446
|
-
|| x >= 0x3250 && x <=
|
|
2447
|
-
|| x >= 0x4E00 && x <= 0xA48C
|
|
2466
|
+
|| x >= 0x3250 && x <= 0xA48C
|
|
2448
2467
|
|| x >= 0xA490 && x <= 0xA4C6
|
|
2449
2468
|
|| x >= 0xA960 && x <= 0xA97C
|
|
2450
2469
|
|| x >= 0xAC00 && x <= 0xD7A3
|
|
@@ -2458,7 +2477,7 @@ function isWide(x) {
|
|
|
2458
2477
|
|| x === 0x16FF1
|
|
2459
2478
|
|| x >= 0x17000 && x <= 0x187F7
|
|
2460
2479
|
|| x >= 0x18800 && x <= 0x18CD5
|
|
2461
|
-
|| x >=
|
|
2480
|
+
|| x >= 0x18CFF && x <= 0x18D08
|
|
2462
2481
|
|| x >= 0x1AFF0 && x <= 0x1AFF3
|
|
2463
2482
|
|| x >= 0x1AFF5 && x <= 0x1AFFB
|
|
2464
2483
|
|| x === 0x1AFFD
|
|
@@ -2469,6 +2488,8 @@ function isWide(x) {
|
|
|
2469
2488
|
|| x === 0x1B155
|
|
2470
2489
|
|| x >= 0x1B164 && x <= 0x1B167
|
|
2471
2490
|
|| x >= 0x1B170 && x <= 0x1B2FB
|
|
2491
|
+
|| x >= 0x1D300 && x <= 0x1D356
|
|
2492
|
+
|| x >= 0x1D360 && x <= 0x1D376
|
|
2472
2493
|
|| x === 0x1F004
|
|
2473
2494
|
|| x === 0x1F0CF
|
|
2474
2495
|
|| x === 0x1F18E
|
|
@@ -2512,11 +2533,10 @@ function isWide(x) {
|
|
|
2512
2533
|
|| x >= 0x1F93C && x <= 0x1F945
|
|
2513
2534
|
|| x >= 0x1F947 && x <= 0x1F9FF
|
|
2514
2535
|
|| x >= 0x1FA70 && x <= 0x1FA7C
|
|
2515
|
-
|| x >= 0x1FA80 && x <=
|
|
2516
|
-
|| x >=
|
|
2517
|
-
|| x >=
|
|
2518
|
-
|| x >=
|
|
2519
|
-
|| x >= 0x1FAE0 && x <= 0x1FAE8
|
|
2536
|
+
|| x >= 0x1FA80 && x <= 0x1FA89
|
|
2537
|
+
|| x >= 0x1FA8F && x <= 0x1FAC6
|
|
2538
|
+
|| x >= 0x1FACE && x <= 0x1FADC
|
|
2539
|
+
|| x >= 0x1FADF && x <= 0x1FAE9
|
|
2520
2540
|
|| x >= 0x1FAF0 && x <= 0x1FAF8
|
|
2521
2541
|
|| x >= 0x20000 && x <= 0x2FFFD
|
|
2522
2542
|
|| x >= 0x30000 && x <= 0x3FFFD;
|
|
@@ -3005,6 +3025,7 @@ function lineNo(no = "") {
|
|
|
3005
3025
|
return c.gray(`${String(no).padStart(3, " ")}| `);
|
|
3006
3026
|
}
|
|
3007
3027
|
|
|
3028
|
+
const PAD = " ";
|
|
3008
3029
|
const ESC = "\x1B[";
|
|
3009
3030
|
const ERASE_DOWN = `${ESC}J`;
|
|
3010
3031
|
const ERASE_SCROLLBACK = `${ESC}3J`;
|
|
@@ -3018,6 +3039,7 @@ class Logger {
|
|
|
3018
3039
|
this.console = new Console({ stdout: outputStream, stderr: errorStream });
|
|
3019
3040
|
this.logUpdate = createLogUpdate(this.outputStream);
|
|
3020
3041
|
this._highlights.clear();
|
|
3042
|
+
this.registerUnhandledRejection();
|
|
3021
3043
|
}
|
|
3022
3044
|
logUpdate;
|
|
3023
3045
|
_clearScreenPending;
|
|
@@ -3035,12 +3057,16 @@ class Logger {
|
|
|
3035
3057
|
this._clearScreen();
|
|
3036
3058
|
this.console.warn(...args);
|
|
3037
3059
|
}
|
|
3038
|
-
clearFullScreen(message) {
|
|
3060
|
+
clearFullScreen(message = "") {
|
|
3039
3061
|
if (!this.ctx.config.clearScreen) {
|
|
3040
3062
|
this.console.log(message);
|
|
3041
3063
|
return;
|
|
3042
3064
|
}
|
|
3043
|
-
|
|
3065
|
+
if (message) {
|
|
3066
|
+
this.console.log(`${CLEAR_SCREEN}${ERASE_SCROLLBACK}${message}`);
|
|
3067
|
+
} else {
|
|
3068
|
+
this.outputStream.write(`${CLEAR_SCREEN}${ERASE_SCROLLBACK}`);
|
|
3069
|
+
}
|
|
3044
3070
|
}
|
|
3045
3071
|
clearScreen(message, force = false) {
|
|
3046
3072
|
if (!this.ctx.config.clearScreen) {
|
|
@@ -3152,68 +3178,53 @@ No ${config.mode} files found, exiting with code 1`)
|
|
|
3152
3178
|
}
|
|
3153
3179
|
printBanner() {
|
|
3154
3180
|
this.log();
|
|
3155
|
-
const
|
|
3156
|
-
const mode = this.ctx.config.watch ?
|
|
3157
|
-
this.log(
|
|
3158
|
-
`${c.inverse(c.bold(mode))} ${versionTest} ${c.gray(
|
|
3159
|
-
this.ctx.config.root
|
|
3160
|
-
)}`
|
|
3161
|
-
);
|
|
3181
|
+
const color = this.ctx.config.watch ? "blue" : "cyan";
|
|
3182
|
+
const mode = this.ctx.config.watch ? "DEV" : "RUN";
|
|
3183
|
+
this.log(withLabel(color, mode, `v${this.ctx.version} `) + c.gray(this.ctx.config.root));
|
|
3162
3184
|
if (this.ctx.config.sequence.sequencer === RandomSequencer) {
|
|
3163
|
-
this.log(
|
|
3164
|
-
c.gray(
|
|
3165
|
-
` Running tests with seed "${this.ctx.config.sequence.seed}"`
|
|
3166
|
-
)
|
|
3167
|
-
);
|
|
3185
|
+
this.log(PAD + c.gray(`Running tests with seed "${this.ctx.config.sequence.seed}"`));
|
|
3168
3186
|
}
|
|
3169
|
-
this.ctx.projects.forEach((project) => {
|
|
3170
|
-
if (!project.browser) {
|
|
3171
|
-
return;
|
|
3172
|
-
}
|
|
3173
|
-
const name = project.getName();
|
|
3174
|
-
const output = project.isCore() ? "" : ` [${name}]`;
|
|
3175
|
-
const resolvedUrls = project.browser.vite.resolvedUrls;
|
|
3176
|
-
const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
|
|
3177
|
-
const provider = project.browser.provider.name;
|
|
3178
|
-
const providerString = provider === "preview" ? "" : ` by ${provider}`;
|
|
3179
|
-
this.log(
|
|
3180
|
-
c.dim(
|
|
3181
|
-
c.green(
|
|
3182
|
-
` ${output} Browser runner started${providerString} at ${new URL("/", origin)}`
|
|
3183
|
-
)
|
|
3184
|
-
)
|
|
3185
|
-
);
|
|
3186
|
-
});
|
|
3187
3187
|
if (this.ctx.config.ui) {
|
|
3188
|
-
this.
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
)
|
|
3193
|
-
)
|
|
3194
|
-
);
|
|
3188
|
+
const host = this.ctx.config.api?.host || "localhost";
|
|
3189
|
+
const port = this.ctx.server.config.server.port;
|
|
3190
|
+
const base = this.ctx.config.uiBase;
|
|
3191
|
+
this.log(PAD + c.dim(c.green(`UI started at http://${host}:${c.bold(port)}${base}`)));
|
|
3195
3192
|
} else if (this.ctx.config.api?.port) {
|
|
3196
3193
|
const resolvedUrls = this.ctx.server.resolvedUrls;
|
|
3197
3194
|
const fallbackUrl = `http://${this.ctx.config.api.host || "localhost"}:${this.ctx.config.api.port}`;
|
|
3198
3195
|
const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0] ?? fallbackUrl;
|
|
3199
|
-
this.log(c.dim(c.green(`
|
|
3196
|
+
this.log(PAD + c.dim(c.green(`API started at ${new URL("/", origin)}`)));
|
|
3200
3197
|
}
|
|
3201
3198
|
if (this.ctx.coverageProvider) {
|
|
3202
|
-
this.log(
|
|
3203
|
-
c.dim(" Coverage enabled with ") + c.yellow(this.ctx.coverageProvider.name)
|
|
3204
|
-
);
|
|
3199
|
+
this.log(PAD + c.dim("Coverage enabled with ") + c.yellow(this.ctx.coverageProvider.name));
|
|
3205
3200
|
}
|
|
3206
3201
|
if (this.ctx.config.standalone) {
|
|
3207
|
-
this.log(
|
|
3208
|
-
|
|
3209
|
-
`
|
|
3210
|
-
Vitest is running in standalone mode. Edit a test file to rerun tests.`
|
|
3211
|
-
)
|
|
3212
|
-
);
|
|
3202
|
+
this.log(c.yellow(`
|
|
3203
|
+
Vitest is running in standalone mode. Edit a test file to rerun tests.`));
|
|
3213
3204
|
} else {
|
|
3214
3205
|
this.log();
|
|
3215
3206
|
}
|
|
3216
3207
|
}
|
|
3208
|
+
printBrowserBanner(project) {
|
|
3209
|
+
if (!project.browser) {
|
|
3210
|
+
return;
|
|
3211
|
+
}
|
|
3212
|
+
const resolvedUrls = project.browser.vite.resolvedUrls;
|
|
3213
|
+
const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
|
|
3214
|
+
if (!origin) {
|
|
3215
|
+
return;
|
|
3216
|
+
}
|
|
3217
|
+
const name = project.getName();
|
|
3218
|
+
const output = project.isCore() ? "" : formatProjectName(name);
|
|
3219
|
+
const provider = project.browser.provider.name;
|
|
3220
|
+
const providerString = provider === "preview" ? "" : ` by ${c.reset(c.bold(provider))}`;
|
|
3221
|
+
this.log(
|
|
3222
|
+
c.dim(
|
|
3223
|
+
`${output}Browser runner started${providerString} ${c.dim("at")} ${c.blue(new URL("/", origin))}
|
|
3224
|
+
`
|
|
3225
|
+
)
|
|
3226
|
+
);
|
|
3227
|
+
}
|
|
3217
3228
|
printUnhandledErrors(errors) {
|
|
3218
3229
|
const errorMessage = c.red(
|
|
3219
3230
|
c.bold(
|
|
@@ -3246,6 +3257,21 @@ Vitest found ${errors.length} error${errors.length > 1 ? "s" : ""} not related t
|
|
|
3246
3257
|
});
|
|
3247
3258
|
this.log(c.red(divider()));
|
|
3248
3259
|
}
|
|
3260
|
+
registerUnhandledRejection() {
|
|
3261
|
+
const onUnhandledRejection = (err) => {
|
|
3262
|
+
process.exitCode = 1;
|
|
3263
|
+
this.printError(err, {
|
|
3264
|
+
fullStack: true,
|
|
3265
|
+
type: "Unhandled Rejection"
|
|
3266
|
+
});
|
|
3267
|
+
this.error("\n\n");
|
|
3268
|
+
process.exit();
|
|
3269
|
+
};
|
|
3270
|
+
process.on("unhandledRejection", onUnhandledRejection);
|
|
3271
|
+
this.ctx.onClose(() => {
|
|
3272
|
+
process.off("unhandledRejection", onUnhandledRejection);
|
|
3273
|
+
});
|
|
3274
|
+
}
|
|
3249
3275
|
}
|
|
3250
3276
|
|
|
3251
3277
|
class BlobReporter {
|
|
@@ -3376,21 +3402,6 @@ function hasFailedSnapshot(suite) {
|
|
|
3376
3402
|
}
|
|
3377
3403
|
|
|
3378
3404
|
const BADGE_PADDING = " ";
|
|
3379
|
-
const HELP_HINT = `${c.dim("press ")}${c.bold("h")}${c.dim(" to show help")}`;
|
|
3380
|
-
const HELP_UPDATE_SNAP = c.dim("press ") + c.bold(c.yellow("u")) + c.dim(" to update snapshot");
|
|
3381
|
-
const HELP_QUITE = `${c.dim("press ")}${c.bold("q")}${c.dim(" to quit")}`;
|
|
3382
|
-
const WAIT_FOR_CHANGE_PASS = `
|
|
3383
|
-
${c.bold(
|
|
3384
|
-
c.inverse(c.green(" PASS "))
|
|
3385
|
-
)}${c.green(" Waiting for file changes...")}`;
|
|
3386
|
-
const WAIT_FOR_CHANGE_FAIL = `
|
|
3387
|
-
${c.bold(c.inverse(c.red(" FAIL ")))}${c.red(
|
|
3388
|
-
" Tests failed. Watching for file changes..."
|
|
3389
|
-
)}`;
|
|
3390
|
-
const WAIT_FOR_CHANGE_CANCELLED = `
|
|
3391
|
-
${c.bold(
|
|
3392
|
-
c.inverse(c.red(" CANCELLED "))
|
|
3393
|
-
)}${c.red(" Test run cancelled. Watching for file changes...")}`;
|
|
3394
3405
|
const LAST_RUN_LOG_TIMEOUT = 1500;
|
|
3395
3406
|
class BaseReporter {
|
|
3396
3407
|
start = 0;
|
|
@@ -3401,37 +3412,30 @@ class BaseReporter {
|
|
|
3401
3412
|
ctx = void 0;
|
|
3402
3413
|
verbose = false;
|
|
3403
3414
|
_filesInWatchMode = /* @__PURE__ */ new Map();
|
|
3415
|
+
_timeStart = formatTimeString(/* @__PURE__ */ new Date());
|
|
3404
3416
|
_lastRunTimeout = 0;
|
|
3405
3417
|
_lastRunTimer;
|
|
3406
3418
|
_lastRunCount = 0;
|
|
3407
|
-
_timeStart = /* @__PURE__ */ new Date();
|
|
3408
|
-
_offUnhandledRejection;
|
|
3409
3419
|
constructor(options = {}) {
|
|
3410
3420
|
this.isTTY = options.isTTY ?? ((isNode || isDeno) && process.stdout?.isTTY && !isCI);
|
|
3411
|
-
this.registerUnhandledRejection();
|
|
3412
|
-
}
|
|
3413
|
-
get mode() {
|
|
3414
|
-
return this.ctx.config.mode;
|
|
3415
3421
|
}
|
|
3416
3422
|
onInit(ctx) {
|
|
3417
3423
|
this.ctx = ctx;
|
|
3418
|
-
ctx.
|
|
3419
|
-
this._offUnhandledRejection?.();
|
|
3420
|
-
});
|
|
3421
|
-
ctx.logger.printBanner();
|
|
3424
|
+
this.ctx.logger.printBanner();
|
|
3422
3425
|
this.start = performance.now();
|
|
3423
3426
|
}
|
|
3427
|
+
log(...messages) {
|
|
3428
|
+
this.ctx.logger.log(...messages);
|
|
3429
|
+
}
|
|
3430
|
+
error(...messages) {
|
|
3431
|
+
this.ctx.logger.error(...messages);
|
|
3432
|
+
}
|
|
3424
3433
|
relative(path) {
|
|
3425
3434
|
return relative(this.ctx.config.root, path);
|
|
3426
3435
|
}
|
|
3427
3436
|
onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
|
|
3428
3437
|
this.end = performance.now();
|
|
3429
3438
|
this.reportSummary(files, errors);
|
|
3430
|
-
if (errors.length) {
|
|
3431
|
-
if (!this.ctx.config.dangerouslyIgnoreUnhandledErrors) {
|
|
3432
|
-
process.exitCode = 1;
|
|
3433
|
-
}
|
|
3434
|
-
}
|
|
3435
3439
|
}
|
|
3436
3440
|
onTaskUpdate(packs) {
|
|
3437
3441
|
if (this.isTTY) {
|
|
@@ -3448,48 +3452,39 @@ class BaseReporter {
|
|
|
3448
3452
|
if (!("filepath" in task) || !task.result?.state || task.result?.state === "run") {
|
|
3449
3453
|
return;
|
|
3450
3454
|
}
|
|
3451
|
-
const logger = this.ctx.logger;
|
|
3452
3455
|
const tests = getTests(task);
|
|
3453
3456
|
const failed = tests.filter((t) => t.result?.state === "fail");
|
|
3454
|
-
const skipped = tests.filter(
|
|
3455
|
-
(t) => t.mode === "skip" || t.mode === "todo"
|
|
3456
|
-
);
|
|
3457
|
+
const skipped = tests.filter((t) => t.mode === "skip" || t.mode === "todo");
|
|
3457
3458
|
let state = c.dim(`${tests.length} test${tests.length > 1 ? "s" : ""}`);
|
|
3458
3459
|
if (failed.length) {
|
|
3459
|
-
state +=
|
|
3460
|
+
state += c.dim(" | ") + c.red(`${failed.length} failed`);
|
|
3460
3461
|
}
|
|
3461
3462
|
if (skipped.length) {
|
|
3462
|
-
state +=
|
|
3463
|
+
state += c.dim(" | ") + c.yellow(`${skipped.length} skipped`);
|
|
3463
3464
|
}
|
|
3464
|
-
let suffix = c.dim("
|
|
3465
|
-
suffix += this.getDurationPrefix(task);
|
|
3465
|
+
let suffix = c.dim("(") + state + c.dim(")") + this.getDurationPrefix(task);
|
|
3466
3466
|
if (this.ctx.config.logHeapUsage && task.result.heap != null) {
|
|
3467
|
-
suffix += c.magenta(
|
|
3468
|
-
` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`
|
|
3469
|
-
);
|
|
3467
|
+
suffix += c.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`);
|
|
3470
3468
|
}
|
|
3471
|
-
let title =
|
|
3469
|
+
let title = getStateSymbol(task);
|
|
3472
3470
|
if (task.meta.typecheck) {
|
|
3473
|
-
title +=
|
|
3471
|
+
title += ` ${c.bgBlue(c.bold(" TS "))}`;
|
|
3474
3472
|
}
|
|
3475
3473
|
if (task.projectName) {
|
|
3476
|
-
title += formatProjectName(task.projectName)
|
|
3474
|
+
title += ` ${formatProjectName(task.projectName, "")}`;
|
|
3477
3475
|
}
|
|
3478
|
-
title
|
|
3479
|
-
logger.log(title);
|
|
3476
|
+
this.log(` ${title} ${task.name} ${suffix}`);
|
|
3480
3477
|
for (const test of tests) {
|
|
3481
3478
|
const duration = test.result?.duration;
|
|
3482
3479
|
if (test.result?.state === "fail") {
|
|
3483
3480
|
const suffix2 = this.getDurationPrefix(test);
|
|
3484
|
-
|
|
3481
|
+
this.log(c.red(` ${taskFail} ${getTestName(test, c.dim(" > "))}${suffix2}`));
|
|
3485
3482
|
test.result?.errors?.forEach((e) => {
|
|
3486
|
-
|
|
3483
|
+
this.log(c.red(` ${F_RIGHT} ${e?.message}`));
|
|
3487
3484
|
});
|
|
3488
3485
|
} else if (duration && duration > this.ctx.config.slowTestThreshold) {
|
|
3489
|
-
|
|
3490
|
-
` ${c.yellow(c.dim(F_CHECK))} ${getTestName(test, c.dim(" > "))}${c.yellow(
|
|
3491
|
-
` ${Math.round(duration)}${c.dim("ms")}`
|
|
3492
|
-
)}`
|
|
3486
|
+
this.log(
|
|
3487
|
+
` ${c.yellow(c.dim(F_CHECK))} ${getTestName(test, c.dim(" > "))} ${c.yellow(Math.round(duration) + c.dim("ms"))}`
|
|
3493
3488
|
);
|
|
3494
3489
|
}
|
|
3495
3490
|
}
|
|
@@ -3504,23 +3499,20 @@ class BaseReporter {
|
|
|
3504
3499
|
onWatcherStart(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
|
|
3505
3500
|
this.resetLastRunLog();
|
|
3506
3501
|
const failed = errors.length > 0 || hasFailed(files);
|
|
3507
|
-
const failedSnap = hasFailedSnapshot(files);
|
|
3508
|
-
const cancelled = this.ctx.isCancelling;
|
|
3509
3502
|
if (failed) {
|
|
3510
|
-
this.
|
|
3511
|
-
} else if (
|
|
3512
|
-
this.
|
|
3503
|
+
this.log(withLabel("red", "FAIL", "Tests failed. Watching for file changes..."));
|
|
3504
|
+
} else if (this.ctx.isCancelling) {
|
|
3505
|
+
this.log(withLabel("red", "CANCELLED", "Test run cancelled. Watching for file changes..."));
|
|
3513
3506
|
} else {
|
|
3514
|
-
this.
|
|
3507
|
+
this.log(withLabel("green", "PASS", "Waiting for file changes..."));
|
|
3515
3508
|
}
|
|
3516
|
-
const hints = [];
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
hints.unshift(HELP_UPDATE_SNAP);
|
|
3509
|
+
const hints = [c.dim("press ") + c.bold("h") + c.dim(" to show help")];
|
|
3510
|
+
if (hasFailedSnapshot(files)) {
|
|
3511
|
+
hints.unshift(c.dim("press ") + c.bold(c.yellow("u")) + c.dim(" to update snapshot"));
|
|
3520
3512
|
} else {
|
|
3521
|
-
hints.push(
|
|
3513
|
+
hints.push(c.dim("press ") + c.bold("q") + c.dim(" to quit"));
|
|
3522
3514
|
}
|
|
3523
|
-
this.
|
|
3515
|
+
this.log(BADGE_PADDING + hints.join(c.dim(", ")));
|
|
3524
3516
|
if (this._lastRunCount) {
|
|
3525
3517
|
const LAST_RUN_TEXT = `rerun x${this._lastRunCount}`;
|
|
3526
3518
|
const LAST_RUN_TEXTS = [
|
|
@@ -3550,90 +3542,79 @@ class BaseReporter {
|
|
|
3550
3542
|
onWatcherRerun(files, trigger) {
|
|
3551
3543
|
this.resetLastRunLog();
|
|
3552
3544
|
this.watchFilters = files;
|
|
3553
|
-
this.failedUnwatchedFiles = this.ctx.state.getFiles().filter(
|
|
3554
|
-
|
|
3555
|
-
|
|
3545
|
+
this.failedUnwatchedFiles = this.ctx.state.getFiles().filter(
|
|
3546
|
+
(file) => !files.includes(file.filepath) && hasFailed(file)
|
|
3547
|
+
);
|
|
3556
3548
|
files.forEach((filepath) => {
|
|
3557
3549
|
let reruns = this._filesInWatchMode.get(filepath) ?? 0;
|
|
3558
3550
|
this._filesInWatchMode.set(filepath, ++reruns);
|
|
3559
3551
|
});
|
|
3560
|
-
|
|
3561
|
-
const TRIGGER = trigger ? c.dim(` ${this.relative(trigger)}`) : "";
|
|
3562
|
-
const FILENAME_PATTERN = this.ctx.filenamePattern ? `${BADGE_PADDING} ${c.dim("Filename pattern: ")}${c.blue(
|
|
3563
|
-
this.ctx.filenamePattern
|
|
3564
|
-
)}
|
|
3565
|
-
` : "";
|
|
3566
|
-
const TESTNAME_PATTERN = this.ctx.configOverride.testNamePattern ? `${BADGE_PADDING} ${c.dim("Test name pattern: ")}${c.blue(
|
|
3567
|
-
String(this.ctx.configOverride.testNamePattern)
|
|
3568
|
-
)}
|
|
3569
|
-
` : "";
|
|
3570
|
-
const PROJECT_FILTER = this.ctx.configOverride.project ? `${BADGE_PADDING} ${c.dim("Project name: ")}${c.blue(
|
|
3571
|
-
toArray(this.ctx.configOverride.project).join(", ")
|
|
3572
|
-
)}
|
|
3573
|
-
` : "";
|
|
3552
|
+
let banner = trigger ? c.dim(`${this.relative(trigger)} `) : "";
|
|
3574
3553
|
if (files.length > 1 || !files.length) {
|
|
3575
|
-
this.ctx.logger.clearFullScreen(
|
|
3576
|
-
`
|
|
3577
|
-
${BADGE}${TRIGGER}
|
|
3578
|
-
${PROJECT_FILTER}${FILENAME_PATTERN}${TESTNAME_PATTERN}`
|
|
3579
|
-
);
|
|
3580
3554
|
this._lastRunCount = 0;
|
|
3581
3555
|
} else if (files.length === 1) {
|
|
3582
3556
|
const rerun = this._filesInWatchMode.get(files[0]) ?? 1;
|
|
3583
|
-
|
|
3584
|
-
this.ctx.logger.clearFullScreen(
|
|
3585
|
-
`
|
|
3586
|
-
${BADGE}${TRIGGER} ${c.blue(
|
|
3587
|
-
`x${rerun}`
|
|
3588
|
-
)}
|
|
3589
|
-
${PROJECT_FILTER}${FILENAME_PATTERN}${TESTNAME_PATTERN}`
|
|
3590
|
-
);
|
|
3557
|
+
banner += c.blue(`x${rerun} `);
|
|
3591
3558
|
}
|
|
3559
|
+
this.ctx.logger.clearFullScreen();
|
|
3560
|
+
this.log(withLabel("blue", "RERUN", banner));
|
|
3561
|
+
if (this.ctx.configOverride.project) {
|
|
3562
|
+
this.log(BADGE_PADDING + c.dim(" Project name: ") + c.blue(toArray(this.ctx.configOverride.project).join(", ")));
|
|
3563
|
+
}
|
|
3564
|
+
if (this.ctx.filenamePattern) {
|
|
3565
|
+
this.log(BADGE_PADDING + c.dim(" Filename pattern: ") + c.blue(this.ctx.filenamePattern));
|
|
3566
|
+
}
|
|
3567
|
+
if (this.ctx.configOverride.testNamePattern) {
|
|
3568
|
+
this.log(BADGE_PADDING + c.dim(" Test name pattern: ") + c.blue(String(this.ctx.configOverride.testNamePattern)));
|
|
3569
|
+
}
|
|
3570
|
+
this.log("");
|
|
3592
3571
|
if (!this.isTTY) {
|
|
3593
3572
|
for (const task of this.failedUnwatchedFiles) {
|
|
3594
3573
|
this.printTask(task);
|
|
3595
3574
|
}
|
|
3596
3575
|
}
|
|
3597
|
-
this._timeStart = /* @__PURE__ */ new Date();
|
|
3576
|
+
this._timeStart = formatTimeString(/* @__PURE__ */ new Date());
|
|
3598
3577
|
this.start = performance.now();
|
|
3599
3578
|
}
|
|
3600
3579
|
onUserConsoleLog(log) {
|
|
3601
3580
|
if (!this.shouldLog(log)) {
|
|
3602
3581
|
return;
|
|
3603
3582
|
}
|
|
3604
|
-
const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : void 0;
|
|
3605
|
-
const header = c.gray(
|
|
3606
|
-
log.type + c.dim(
|
|
3607
|
-
` | ${task ? getFullName(task, c.dim(" > ")) : log.taskId !== "__vitest__unknown_test__" ? log.taskId : "unknown test"}`
|
|
3608
|
-
)
|
|
3609
|
-
);
|
|
3610
3583
|
const output = log.type === "stdout" ? this.ctx.logger.outputStream : this.ctx.logger.errorStream;
|
|
3611
3584
|
const write = (msg) => output.write(msg);
|
|
3612
|
-
|
|
3613
|
-
|
|
3585
|
+
let headerText = "unknown test";
|
|
3586
|
+
const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : void 0;
|
|
3587
|
+
if (task) {
|
|
3588
|
+
headerText = getFullName(task, c.dim(" > "));
|
|
3589
|
+
} else if (log.taskId && log.taskId !== "__vitest__unknown_test__") {
|
|
3590
|
+
headerText = log.taskId;
|
|
3591
|
+
}
|
|
3592
|
+
write(c.gray(log.type + c.dim(` | ${headerText}
|
|
3593
|
+
`)) + log.content);
|
|
3614
3594
|
if (log.origin) {
|
|
3615
3595
|
if (log.browser) {
|
|
3616
3596
|
write("\n");
|
|
3617
3597
|
}
|
|
3618
3598
|
const project = log.taskId ? this.ctx.getProjectByTaskId(log.taskId) : this.ctx.getCoreWorkspaceProject();
|
|
3619
3599
|
const stack = log.browser ? project.browser?.parseStacktrace(log.origin) || [] : parseStacktrace(log.origin);
|
|
3620
|
-
const highlight = task
|
|
3600
|
+
const highlight = task && stack.find((i) => i.file === task.file.filepath);
|
|
3621
3601
|
for (const frame of stack) {
|
|
3622
3602
|
const color = frame === highlight ? c.cyan : c.gray;
|
|
3623
3603
|
const path = relative(project.config.root, frame.file);
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
`
|
|
3631
|
-
)
|
|
3632
|
-
);
|
|
3604
|
+
const positions = [
|
|
3605
|
+
frame.method,
|
|
3606
|
+
`${path}:${c.dim(`${frame.line}:${frame.column}`)}`
|
|
3607
|
+
].filter(Boolean).join(" ");
|
|
3608
|
+
write(color(` ${c.dim(F_POINTER)} ${positions}
|
|
3609
|
+
`));
|
|
3633
3610
|
}
|
|
3634
3611
|
}
|
|
3635
3612
|
write("\n");
|
|
3636
3613
|
}
|
|
3614
|
+
onTestRemoved(trigger) {
|
|
3615
|
+
this.log(c.yellow("Test removed...") + (trigger ? c.dim(` [ ${this.relative(trigger)} ]
|
|
3616
|
+
`) : ""));
|
|
3617
|
+
}
|
|
3637
3618
|
shouldLog(log) {
|
|
3638
3619
|
if (this.ctx.config.silent) {
|
|
3639
3620
|
return false;
|
|
@@ -3645,17 +3626,13 @@ ${log.content}`);
|
|
|
3645
3626
|
return true;
|
|
3646
3627
|
}
|
|
3647
3628
|
onServerRestart(reason) {
|
|
3648
|
-
this.
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
reason === "config" ? "\nRestarting due to config changes..." : "\nRestarting Vitest..."
|
|
3652
|
-
)
|
|
3653
|
-
)
|
|
3654
|
-
);
|
|
3629
|
+
this.log(c.bold(c.magenta(
|
|
3630
|
+
reason === "config" ? "\nRestarting due to config changes..." : "\nRestarting Vitest..."
|
|
3631
|
+
)));
|
|
3655
3632
|
}
|
|
3656
3633
|
reportSummary(files, errors) {
|
|
3657
3634
|
this.printErrorsSummary(files, errors);
|
|
3658
|
-
if (this.mode === "benchmark") {
|
|
3635
|
+
if (this.ctx.config.mode === "benchmark") {
|
|
3659
3636
|
this.reportBenchmarkSummary(files);
|
|
3660
3637
|
} else {
|
|
3661
3638
|
this.reportTestSummary(files, errors);
|
|
@@ -3667,167 +3644,117 @@ ${log.content}`);
|
|
|
3667
3644
|
...files
|
|
3668
3645
|
];
|
|
3669
3646
|
const tests = getTests(affectedFiles);
|
|
3670
|
-
const logger = this.ctx.logger;
|
|
3671
|
-
const executionTime = this.end - this.start;
|
|
3672
|
-
const collectTime = files.reduce(
|
|
3673
|
-
(acc, test) => acc + Math.max(0, test.collectDuration || 0),
|
|
3674
|
-
0
|
|
3675
|
-
);
|
|
3676
|
-
const setupTime = files.reduce(
|
|
3677
|
-
(acc, test) => acc + Math.max(0, test.setupDuration || 0),
|
|
3678
|
-
0
|
|
3679
|
-
);
|
|
3680
|
-
const testsTime = files.reduce(
|
|
3681
|
-
(acc, test) => acc + Math.max(0, test.result?.duration || 0),
|
|
3682
|
-
0
|
|
3683
|
-
);
|
|
3684
|
-
const transformTime = this.ctx.projects.flatMap((w) => w.vitenode.getTotalDuration()).reduce((a, b) => a + b, 0);
|
|
3685
|
-
const environmentTime = files.reduce(
|
|
3686
|
-
(acc, file) => acc + Math.max(0, file.environmentLoad || 0),
|
|
3687
|
-
0
|
|
3688
|
-
);
|
|
3689
|
-
const prepareTime = files.reduce(
|
|
3690
|
-
(acc, file) => acc + Math.max(0, file.prepareDuration || 0),
|
|
3691
|
-
0
|
|
3692
|
-
);
|
|
3693
|
-
const threadTime = collectTime + testsTime + setupTime;
|
|
3694
3647
|
const snapshotOutput = renderSnapshotSummary(
|
|
3695
3648
|
this.ctx.config.root,
|
|
3696
3649
|
this.ctx.snapshot.summary
|
|
3697
3650
|
);
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
);
|
|
3704
|
-
if (snapshotOutput.length > 1) {
|
|
3705
|
-
logger.log();
|
|
3706
|
-
}
|
|
3651
|
+
for (const [index, snapshot] of snapshotOutput.entries()) {
|
|
3652
|
+
const title = index === 0 ? "Snapshots" : "";
|
|
3653
|
+
this.log(`${padTitle(title)} ${snapshot}`);
|
|
3654
|
+
}
|
|
3655
|
+
if (snapshotOutput.length > 1) {
|
|
3656
|
+
this.log();
|
|
3707
3657
|
}
|
|
3708
|
-
|
|
3709
|
-
|
|
3658
|
+
this.log(padTitle("Test Files"), getStateString(affectedFiles));
|
|
3659
|
+
this.log(padTitle("Tests"), getStateString(tests));
|
|
3710
3660
|
if (this.ctx.projects.some((c2) => c2.config.typecheck.enabled)) {
|
|
3711
|
-
const failed = tests.filter(
|
|
3712
|
-
|
|
3713
|
-
);
|
|
3714
|
-
logger.log(
|
|
3661
|
+
const failed = tests.filter((t) => t.meta?.typecheck && t.result?.errors?.length);
|
|
3662
|
+
this.log(
|
|
3715
3663
|
padTitle("Type Errors"),
|
|
3716
3664
|
failed.length ? c.bold(c.red(`${failed.length} failed`)) : c.dim("no errors")
|
|
3717
3665
|
);
|
|
3718
3666
|
}
|
|
3719
3667
|
if (errors.length) {
|
|
3720
|
-
|
|
3668
|
+
this.log(
|
|
3721
3669
|
padTitle("Errors"),
|
|
3722
3670
|
c.bold(c.red(`${errors.length} error${errors.length > 1 ? "s" : ""}`))
|
|
3723
3671
|
);
|
|
3724
3672
|
}
|
|
3725
|
-
|
|
3673
|
+
this.log(padTitle("Start at"), this._timeStart);
|
|
3674
|
+
const collectTime = sum(files, (file) => file.collectDuration);
|
|
3675
|
+
const testsTime = sum(files, (file) => file.result?.duration);
|
|
3676
|
+
const setupTime = sum(files, (file) => file.setupDuration);
|
|
3726
3677
|
if (this.watchFilters) {
|
|
3727
|
-
|
|
3678
|
+
this.log(padTitle("Duration"), time(collectTime + testsTime + setupTime));
|
|
3728
3679
|
} else {
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
const
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
);
|
|
3680
|
+
const executionTime = this.end - this.start;
|
|
3681
|
+
const environmentTime = sum(files, (file) => file.environmentLoad);
|
|
3682
|
+
const prepareTime = sum(files, (file) => file.prepareDuration);
|
|
3683
|
+
const transformTime = sum(this.ctx.projects, (project) => project.vitenode.getTotalDuration());
|
|
3684
|
+
const typecheck = sum(this.ctx.projects, (project) => project.typechecker?.getResult().time);
|
|
3685
|
+
const timers = [
|
|
3686
|
+
`transform ${time(transformTime)}`,
|
|
3687
|
+
`setup ${time(setupTime)}`,
|
|
3688
|
+
`collect ${time(collectTime)}`,
|
|
3689
|
+
`tests ${time(testsTime)}`,
|
|
3690
|
+
`environment ${time(environmentTime)}`,
|
|
3691
|
+
`prepare ${time(prepareTime)}`,
|
|
3692
|
+
typecheck && `typecheck ${time(typecheck)}`
|
|
3693
|
+
].filter(Boolean).join(", ");
|
|
3694
|
+
this.log(padTitle("Duration"), time(executionTime) + c.dim(` (${timers})`));
|
|
3745
3695
|
}
|
|
3746
|
-
|
|
3696
|
+
this.log();
|
|
3747
3697
|
}
|
|
3748
3698
|
printErrorsSummary(files, errors) {
|
|
3749
|
-
const logger = this.ctx.logger;
|
|
3750
3699
|
const suites = getSuites(files);
|
|
3751
3700
|
const tests = getTests(files);
|
|
3752
3701
|
const failedSuites = suites.filter((i) => i.result?.errors);
|
|
3753
3702
|
const failedTests = tests.filter((i) => i.result?.state === "fail");
|
|
3754
3703
|
const failedTotal = countTestErrors(failedSuites) + countTestErrors(failedTests);
|
|
3755
3704
|
let current = 1;
|
|
3756
|
-
const errorDivider = () =>
|
|
3757
|
-
|
|
3758
|
-
c.dim(divider(`[${current++}/${failedTotal}]`, void 0, 1))
|
|
3759
|
-
)}
|
|
3760
|
-
`
|
|
3761
|
-
);
|
|
3705
|
+
const errorDivider = () => this.error(`${c.red(c.dim(divider(`[${current++}/${failedTotal}]`, void 0, 1)))}
|
|
3706
|
+
`);
|
|
3762
3707
|
if (failedSuites.length) {
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
divider(c.bold(c.inverse(` Failed Suites ${failedSuites.length} `)))
|
|
3766
|
-
)
|
|
3767
|
-
);
|
|
3768
|
-
logger.error();
|
|
3708
|
+
this.error(`${errorBanner(`Failed Suites ${failedSuites.length}`)}
|
|
3709
|
+
`);
|
|
3769
3710
|
this.printTaskErrors(failedSuites, errorDivider);
|
|
3770
3711
|
}
|
|
3771
3712
|
if (failedTests.length) {
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
divider(c.bold(c.inverse(` Failed Tests ${failedTests.length} `)))
|
|
3775
|
-
)
|
|
3776
|
-
);
|
|
3777
|
-
logger.error();
|
|
3713
|
+
this.error(`${errorBanner(`Failed Tests ${failedTests.length}`)}
|
|
3714
|
+
`);
|
|
3778
3715
|
this.printTaskErrors(failedTests, errorDivider);
|
|
3779
3716
|
}
|
|
3780
3717
|
if (errors.length) {
|
|
3781
|
-
logger.printUnhandledErrors(errors);
|
|
3782
|
-
|
|
3718
|
+
this.ctx.logger.printUnhandledErrors(errors);
|
|
3719
|
+
this.error();
|
|
3783
3720
|
}
|
|
3784
|
-
return tests;
|
|
3785
3721
|
}
|
|
3786
3722
|
reportBenchmarkSummary(files) {
|
|
3787
|
-
const logger = this.ctx.logger;
|
|
3788
3723
|
const benches = getTests(files);
|
|
3789
3724
|
const topBenches = benches.filter((i) => i.result?.benchmark?.rank === 1);
|
|
3790
|
-
|
|
3791
|
-
`
|
|
3792
|
-
${c.cyan(c.inverse(c.bold(" BENCH ")))} ${c.cyan("Summary")}
|
|
3793
|
-
`
|
|
3794
|
-
);
|
|
3725
|
+
this.log(withLabel("cyan", "BENCH", "Summary\n"));
|
|
3795
3726
|
for (const bench of topBenches) {
|
|
3796
3727
|
const group = bench.suite || bench.file;
|
|
3797
3728
|
if (!group) {
|
|
3798
3729
|
continue;
|
|
3799
3730
|
}
|
|
3800
3731
|
const groupName = getFullName(group, c.dim(" > "));
|
|
3801
|
-
|
|
3732
|
+
this.log(` ${bench.name}${c.dim(` - ${groupName}`)}`);
|
|
3802
3733
|
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);
|
|
3803
|
-
if (siblings.length === 0) {
|
|
3804
|
-
logger.log("");
|
|
3805
|
-
continue;
|
|
3806
|
-
}
|
|
3807
3734
|
for (const sibling of siblings) {
|
|
3808
|
-
const number =
|
|
3809
|
-
|
|
3810
|
-
` ${c.green(number)} ${c.gray("faster than")} ${sibling.name}`
|
|
3811
|
-
);
|
|
3735
|
+
const number = (sibling.result.benchmark.mean / bench.result.benchmark.mean).toFixed(2);
|
|
3736
|
+
this.log(c.green(` ${number}x `) + c.gray("faster than ") + sibling.name);
|
|
3812
3737
|
}
|
|
3813
|
-
|
|
3738
|
+
this.log("");
|
|
3814
3739
|
}
|
|
3815
3740
|
}
|
|
3816
3741
|
printTaskErrors(tasks, errorDivider) {
|
|
3817
3742
|
const errorsQueue = [];
|
|
3818
3743
|
for (const task of tasks) {
|
|
3819
3744
|
task.result?.errors?.forEach((error) => {
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3745
|
+
let previous;
|
|
3746
|
+
if (error?.stackStr) {
|
|
3747
|
+
previous = errorsQueue.find((i) => {
|
|
3748
|
+
if (i[0]?.stackStr !== error.stackStr) {
|
|
3749
|
+
return false;
|
|
3750
|
+
}
|
|
3751
|
+
const currentProjectName = task?.projectName || task.file?.projectName || "";
|
|
3752
|
+
const projectName = i[1][0]?.projectName || i[1][0].file?.projectName || "";
|
|
3753
|
+
return projectName === currentProjectName;
|
|
3754
|
+
});
|
|
3755
|
+
}
|
|
3756
|
+
if (previous) {
|
|
3757
|
+
previous[1].push(task);
|
|
3831
3758
|
} else {
|
|
3832
3759
|
errorsQueue.push([error, [task]]);
|
|
3833
3760
|
}
|
|
@@ -3839,40 +3766,25 @@ ${c.cyan(c.inverse(c.bold(" BENCH ")))} ${c.cyan("Summary")}
|
|
|
3839
3766
|
const projectName = task?.projectName || task.file?.projectName || "";
|
|
3840
3767
|
let name = getFullName(task, c.dim(" > "));
|
|
3841
3768
|
if (filepath) {
|
|
3842
|
-
name
|
|
3769
|
+
name += c.dim(` [ ${this.relative(filepath)} ]`);
|
|
3843
3770
|
}
|
|
3844
3771
|
this.ctx.logger.error(
|
|
3845
|
-
`${c.red(c.bold(c.inverse(" FAIL ")))}
|
|
3846
|
-
projectName
|
|
3847
|
-
)}${name}`
|
|
3772
|
+
`${c.red(c.bold(c.inverse(" FAIL ")))}${formatProjectName(projectName)} ${name}`
|
|
3848
3773
|
);
|
|
3849
3774
|
}
|
|
3850
|
-
const
|
|
3851
|
-
const project = this.ctx.getProjectByTaskId(tasks2[0].id);
|
|
3775
|
+
const screenshotPaths = tasks2.map((t) => t.meta?.failScreenshotPath).filter((screenshot) => screenshot != null);
|
|
3852
3776
|
this.ctx.logger.printError(error, {
|
|
3853
|
-
project,
|
|
3777
|
+
project: this.ctx.getProjectByTaskId(tasks2[0].id),
|
|
3854
3778
|
verbose: this.verbose,
|
|
3855
|
-
screenshotPaths
|
|
3779
|
+
screenshotPaths,
|
|
3856
3780
|
task: tasks2[0]
|
|
3857
3781
|
});
|
|
3858
3782
|
errorDivider();
|
|
3859
3783
|
}
|
|
3860
3784
|
}
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
this.ctx.logger.printError(err, {
|
|
3865
|
-
fullStack: true,
|
|
3866
|
-
type: "Unhandled Rejection"
|
|
3867
|
-
});
|
|
3868
|
-
this.ctx.logger.error("\n\n");
|
|
3869
|
-
process.exit();
|
|
3870
|
-
};
|
|
3871
|
-
process.on("unhandledRejection", onUnhandledRejection);
|
|
3872
|
-
this._offUnhandledRejection = () => {
|
|
3873
|
-
process.off("unhandledRejection", onUnhandledRejection);
|
|
3874
|
-
};
|
|
3875
|
-
}
|
|
3785
|
+
}
|
|
3786
|
+
function errorBanner(message) {
|
|
3787
|
+
return c.red(divider(c.bold(c.inverse(` ${message} `))));
|
|
3876
3788
|
}
|
|
3877
3789
|
function padTitle(str) {
|
|
3878
3790
|
return c.dim(`${str.padStart(11)} `);
|
|
@@ -3883,6 +3795,11 @@ function time(time2) {
|
|
|
3883
3795
|
}
|
|
3884
3796
|
return `${Math.round(time2)}ms`;
|
|
3885
3797
|
}
|
|
3798
|
+
function sum(items, cb) {
|
|
3799
|
+
return items.reduce((total, next) => {
|
|
3800
|
+
return total + Math.max(cb(next) || 0, 0);
|
|
3801
|
+
}, 0);
|
|
3802
|
+
}
|
|
3886
3803
|
|
|
3887
3804
|
class BasicReporter extends BaseReporter {
|
|
3888
3805
|
constructor() {
|
|
@@ -3973,7 +3890,8 @@ function renderTree$1(tasks, options, level = 0, maxRows) {
|
|
|
3973
3890
|
suffix += c.dim(` (${tests.length})`);
|
|
3974
3891
|
}
|
|
3975
3892
|
if (task.mode === "skip" || task.mode === "todo") {
|
|
3976
|
-
|
|
3893
|
+
const note = task.result?.note || "skipped";
|
|
3894
|
+
suffix += ` ${c.dim(c.gray(`[${note}]`))}`;
|
|
3977
3895
|
}
|
|
3978
3896
|
if (task.type === "test" && task.result?.repeatCount && task.result.repeatCount > 0) {
|
|
3979
3897
|
suffix += c.yellow(` (repeat x${task.result.repeatCount})`);
|
|
@@ -4135,7 +4053,7 @@ class DefaultReporter extends BaseReporter {
|
|
|
4135
4053
|
this.rendererOptions.logger = this.ctx.logger;
|
|
4136
4054
|
this.rendererOptions.showHeap = this.ctx.config.logHeapUsage;
|
|
4137
4055
|
this.rendererOptions.slowTestThreshold = this.ctx.config.slowTestThreshold;
|
|
4138
|
-
this.rendererOptions.mode = this.mode;
|
|
4056
|
+
this.rendererOptions.mode = this.ctx.config.mode;
|
|
4139
4057
|
const files = this.ctx.state.getFiles(this.watchFilters);
|
|
4140
4058
|
if (!this.renderer) {
|
|
4141
4059
|
this.renderer = createListRenderer(files, this.rendererOptions).start();
|
|
@@ -4409,7 +4327,7 @@ class JsonReporter {
|
|
|
4409
4327
|
this.ctx = ctx;
|
|
4410
4328
|
this.start = Date.now();
|
|
4411
4329
|
}
|
|
4412
|
-
async logTasks(files) {
|
|
4330
|
+
async logTasks(files, coverageMap) {
|
|
4413
4331
|
const suites = getSuites(files);
|
|
4414
4332
|
const numTotalTestSuites = suites.length;
|
|
4415
4333
|
const tests = getTests(files);
|
|
@@ -4492,12 +4410,13 @@ class JsonReporter {
|
|
|
4492
4410
|
snapshot: this.ctx.snapshot.summary,
|
|
4493
4411
|
startTime: this.start,
|
|
4494
4412
|
success,
|
|
4495
|
-
testResults
|
|
4413
|
+
testResults,
|
|
4414
|
+
coverageMap
|
|
4496
4415
|
};
|
|
4497
4416
|
await this.writeReport(JSON.stringify(result));
|
|
4498
4417
|
}
|
|
4499
|
-
async onFinished(files = this.ctx.state.getFiles()) {
|
|
4500
|
-
await this.logTasks(files);
|
|
4418
|
+
async onFinished(files = this.ctx.state.getFiles(), _errors = [], coverageMap) {
|
|
4419
|
+
await this.logTasks(files, coverageMap);
|
|
4501
4420
|
}
|
|
4502
4421
|
/**
|
|
4503
4422
|
* Writes the report to an output file if specified in the config,
|
|
@@ -4927,6 +4846,9 @@ class VerboseReporter extends DefaultReporter {
|
|
|
4927
4846
|
` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`
|
|
4928
4847
|
);
|
|
4929
4848
|
}
|
|
4849
|
+
if (task.result?.note) {
|
|
4850
|
+
title += c.dim(c.gray(` [${task.result.note}]`));
|
|
4851
|
+
}
|
|
4930
4852
|
this.ctx.logger.log(title);
|
|
4931
4853
|
if (task.result.state === "fail") {
|
|
4932
4854
|
task.result.errors?.forEach((error) => {
|