vitest 2.2.0-beta.1 → 2.2.0-beta.2
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 +0 -75
- package/dist/browser.d.ts +6 -6
- package/dist/chunks/{RandomSequencer.CMRlh2v4.js → RandomSequencer.BPedXEug.js} +1 -0
- package/dist/chunks/{benchmark.geERunq4.d.ts → benchmark.CFFwLv-O.d.ts} +2 -2
- package/dist/chunks/{cac.Z91LBqmg.js → cac.Cs06pOqp.js} +5 -5
- package/dist/chunks/{cli-api.DVJJMJHj.js → cli-api.CB-jIbYQ.js} +570 -406
- package/dist/chunks/{index.DLRzErGF.js → index.bzFpKeaq.js} +568 -794
- package/dist/chunks/{reporters.B_9uUTGW.d.ts → reporters.F9D2idOT.d.ts} +1231 -1204
- package/dist/chunks/{resolveConfig.CQIc6fe7.js → resolveConfig.CLnvCvEs.js} +8 -8
- package/dist/chunks/{suite.B2jumIFP.d.ts → suite.BJU7kdY9.d.ts} +4 -4
- package/dist/chunks/{utils.DNoFbBUZ.js → utils.DJONn5B5.js} +15 -21
- package/dist/chunks/{vite.Bvms8Xir.d.ts → vite.DonA4fvH.d.ts} +1 -1
- package/dist/cli.js +1 -1
- package/dist/config.d.ts +10 -9
- package/dist/coverage.d.ts +6 -6
- package/dist/coverage.js +2 -2
- package/dist/index.d.ts +7 -6
- package/dist/node.d.ts +19 -10
- package/dist/node.js +9 -9
- package/dist/reporters.d.ts +6 -6
- package/dist/reporters.js +4 -5
- package/dist/runners.d.ts +2 -2
- package/dist/suite.d.ts +2 -2
- package/package.json +13 -12
|
@@ -3,85 +3,22 @@ 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, 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
|
|
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, p as padSummaryTitle, e as getStateString$1, h as formatTime, i as countTestErrors, j as F_TREE_NODE_END, k as F_TREE_NODE_MIDDLE, l as getCols } from './utils.DJONn5B5.js';
|
|
7
7
|
import { stripVTControlCharacters } from 'node:util';
|
|
8
8
|
import { highlight, isPrimitive, inspect, positionToOffset, lineSplitRE, toArray, notNullish } from '@vitest/utils';
|
|
9
|
-
import { performance } from 'node:perf_hooks';
|
|
9
|
+
import { performance as performance$1 } from 'node:perf_hooks';
|
|
10
10
|
import { parseErrorStacktrace, parseStacktrace } from '@vitest/utils/source-map';
|
|
11
|
-
import { a as TypeCheckError, R as RandomSequencer, g as getOutputFile, b as isNode, c as isDeno } from './RandomSequencer.
|
|
11
|
+
import { a as TypeCheckError, R as RandomSequencer, g as getOutputFile, b as isNode, c as isDeno } from './RandomSequencer.BPedXEug.js';
|
|
12
12
|
import { isCI } from 'std-env';
|
|
13
13
|
import { mkdir, writeFile, readdir, stat, readFile } from 'node:fs/promises';
|
|
14
|
+
import restoreCursor from 'restore-cursor';
|
|
14
15
|
import { Writable } from 'node:stream';
|
|
15
16
|
import { Console } from 'node:console';
|
|
16
17
|
import process$1 from 'node:process';
|
|
17
|
-
import { g as getDefaultExportFromCjs
|
|
18
|
-
import require$$0 from 'assert';
|
|
19
|
-
import require$$0$1 from 'events';
|
|
18
|
+
import { g as getDefaultExportFromCjs } from './_commonjsHelpers.BFTU3MAI.js';
|
|
20
19
|
import { createRequire } from 'node:module';
|
|
21
20
|
import { hostname } from 'node:os';
|
|
22
21
|
|
|
23
|
-
class TestProject {
|
|
24
|
-
/**
|
|
25
|
-
* The global vitest instance.
|
|
26
|
-
* @experimental The public Vitest API is experimental and does not follow semver.
|
|
27
|
-
*/
|
|
28
|
-
vitest;
|
|
29
|
-
/**
|
|
30
|
-
* The workspace project this test project is associated with.
|
|
31
|
-
* @experimental The public Vitest API is experimental and does not follow semver.
|
|
32
|
-
*/
|
|
33
|
-
workspaceProject;
|
|
34
|
-
/**
|
|
35
|
-
* Vite's dev server instance. Every workspace project has its own server.
|
|
36
|
-
*/
|
|
37
|
-
vite;
|
|
38
|
-
/**
|
|
39
|
-
* Resolved project configuration.
|
|
40
|
-
*/
|
|
41
|
-
config;
|
|
42
|
-
/**
|
|
43
|
-
* Resolved global configuration. If there are no workspace projects, this will be the same as `config`.
|
|
44
|
-
*/
|
|
45
|
-
globalConfig;
|
|
46
|
-
/**
|
|
47
|
-
* The name of the project or an empty string if not set.
|
|
48
|
-
*/
|
|
49
|
-
name;
|
|
50
|
-
constructor(workspaceProject) {
|
|
51
|
-
this.workspaceProject = workspaceProject;
|
|
52
|
-
this.vitest = workspaceProject.ctx;
|
|
53
|
-
this.vite = workspaceProject.server;
|
|
54
|
-
this.globalConfig = workspaceProject.ctx.config;
|
|
55
|
-
this.config = workspaceProject.config;
|
|
56
|
-
this.name = workspaceProject.getName();
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Serialized project configuration. This is the config that tests receive.
|
|
60
|
-
*/
|
|
61
|
-
get serializedConfig() {
|
|
62
|
-
return this.workspaceProject.getSerializableConfig();
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Custom context provided to the project.
|
|
66
|
-
*/
|
|
67
|
-
context() {
|
|
68
|
-
return this.workspaceProject.getProvidedContext();
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Provide a custom serializable context to the project. This context will be available for tests once they run.
|
|
72
|
-
*/
|
|
73
|
-
provide(key, value) {
|
|
74
|
-
this.workspaceProject.provide(key, value);
|
|
75
|
-
}
|
|
76
|
-
toJSON() {
|
|
77
|
-
return {
|
|
78
|
-
name: this.name,
|
|
79
|
-
serializedConfig: this.serializedConfig,
|
|
80
|
-
context: this.context()
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
22
|
class ReportedTaskImplementation {
|
|
86
23
|
/**
|
|
87
24
|
* Task instance.
|
|
@@ -104,7 +41,7 @@ class ReportedTaskImplementation {
|
|
|
104
41
|
location;
|
|
105
42
|
constructor(task, project) {
|
|
106
43
|
this.task = task;
|
|
107
|
-
this.project = project
|
|
44
|
+
this.project = project;
|
|
108
45
|
this.id = task.id;
|
|
109
46
|
this.location = task.location;
|
|
110
47
|
}
|
|
@@ -415,10 +352,10 @@ function getTestState(test) {
|
|
|
415
352
|
return result ? result.state : "running";
|
|
416
353
|
}
|
|
417
354
|
function storeTask(project, runnerTask, reportedTask) {
|
|
418
|
-
project.
|
|
355
|
+
project.vitest.state.reportedTasksMap.set(runnerTask, reportedTask);
|
|
419
356
|
}
|
|
420
357
|
function getReportedTask(project, runnerTask) {
|
|
421
|
-
const reportedTask = project.
|
|
358
|
+
const reportedTask = project.vitest.state.getReportedEntity(runnerTask);
|
|
422
359
|
if (!reportedTask) {
|
|
423
360
|
throw new Error(
|
|
424
361
|
`Task instance was not found for ${runnerTask.type} "${runnerTask.name}"`
|
|
@@ -534,7 +471,7 @@ const stringify = (value, replacer, space) => {
|
|
|
534
471
|
}
|
|
535
472
|
};
|
|
536
473
|
|
|
537
|
-
const ESC$
|
|
474
|
+
const ESC$2 = '\u001B[';
|
|
538
475
|
const OSC = '\u001B]';
|
|
539
476
|
const BEL = '\u0007';
|
|
540
477
|
const SEP = ';';
|
|
@@ -548,10 +485,10 @@ ansiEscapes.cursorTo = (x, y) => {
|
|
|
548
485
|
}
|
|
549
486
|
|
|
550
487
|
if (typeof y !== 'number') {
|
|
551
|
-
return ESC$
|
|
488
|
+
return ESC$2 + (x + 1) + 'G';
|
|
552
489
|
}
|
|
553
490
|
|
|
554
|
-
return ESC$
|
|
491
|
+
return ESC$2 + (y + 1) + ';' + (x + 1) + 'H';
|
|
555
492
|
};
|
|
556
493
|
|
|
557
494
|
ansiEscapes.cursorMove = (x, y) => {
|
|
@@ -562,33 +499,33 @@ ansiEscapes.cursorMove = (x, y) => {
|
|
|
562
499
|
let returnValue = '';
|
|
563
500
|
|
|
564
501
|
if (x < 0) {
|
|
565
|
-
returnValue += ESC$
|
|
502
|
+
returnValue += ESC$2 + (-x) + 'D';
|
|
566
503
|
} else if (x > 0) {
|
|
567
|
-
returnValue += ESC$
|
|
504
|
+
returnValue += ESC$2 + x + 'C';
|
|
568
505
|
}
|
|
569
506
|
|
|
570
507
|
if (y < 0) {
|
|
571
|
-
returnValue += ESC$
|
|
508
|
+
returnValue += ESC$2 + (-y) + 'A';
|
|
572
509
|
} else if (y > 0) {
|
|
573
|
-
returnValue += ESC$
|
|
510
|
+
returnValue += ESC$2 + y + 'B';
|
|
574
511
|
}
|
|
575
512
|
|
|
576
513
|
return returnValue;
|
|
577
514
|
};
|
|
578
515
|
|
|
579
|
-
ansiEscapes.cursorUp = (count = 1) => ESC$
|
|
580
|
-
ansiEscapes.cursorDown = (count = 1) => ESC$
|
|
581
|
-
ansiEscapes.cursorForward = (count = 1) => ESC$
|
|
582
|
-
ansiEscapes.cursorBackward = (count = 1) => ESC$
|
|
516
|
+
ansiEscapes.cursorUp = (count = 1) => ESC$2 + count + 'A';
|
|
517
|
+
ansiEscapes.cursorDown = (count = 1) => ESC$2 + count + 'B';
|
|
518
|
+
ansiEscapes.cursorForward = (count = 1) => ESC$2 + count + 'C';
|
|
519
|
+
ansiEscapes.cursorBackward = (count = 1) => ESC$2 + count + 'D';
|
|
583
520
|
|
|
584
|
-
ansiEscapes.cursorLeft = ESC$
|
|
585
|
-
ansiEscapes.cursorSavePosition = isTerminalApp ? '\u001B7' : ESC$
|
|
586
|
-
ansiEscapes.cursorRestorePosition = isTerminalApp ? '\u001B8' : ESC$
|
|
587
|
-
ansiEscapes.cursorGetPosition = ESC$
|
|
588
|
-
ansiEscapes.cursorNextLine = ESC$
|
|
589
|
-
ansiEscapes.cursorPrevLine = ESC$
|
|
590
|
-
ansiEscapes.cursorHide = ESC$
|
|
591
|
-
ansiEscapes.cursorShow = ESC$
|
|
521
|
+
ansiEscapes.cursorLeft = ESC$2 + 'G';
|
|
522
|
+
ansiEscapes.cursorSavePosition = isTerminalApp ? '\u001B7' : ESC$2 + 's';
|
|
523
|
+
ansiEscapes.cursorRestorePosition = isTerminalApp ? '\u001B8' : ESC$2 + 'u';
|
|
524
|
+
ansiEscapes.cursorGetPosition = ESC$2 + '6n';
|
|
525
|
+
ansiEscapes.cursorNextLine = ESC$2 + 'E';
|
|
526
|
+
ansiEscapes.cursorPrevLine = ESC$2 + 'F';
|
|
527
|
+
ansiEscapes.cursorHide = ESC$2 + '?25l';
|
|
528
|
+
ansiEscapes.cursorShow = ESC$2 + '?25h';
|
|
592
529
|
|
|
593
530
|
ansiEscapes.eraseLines = count => {
|
|
594
531
|
let clear = '';
|
|
@@ -604,24 +541,24 @@ ansiEscapes.eraseLines = count => {
|
|
|
604
541
|
return clear;
|
|
605
542
|
};
|
|
606
543
|
|
|
607
|
-
ansiEscapes.eraseEndLine = ESC$
|
|
608
|
-
ansiEscapes.eraseStartLine = ESC$
|
|
609
|
-
ansiEscapes.eraseLine = ESC$
|
|
610
|
-
ansiEscapes.eraseDown = ESC$
|
|
611
|
-
ansiEscapes.eraseUp = ESC$
|
|
612
|
-
ansiEscapes.eraseScreen = ESC$
|
|
613
|
-
ansiEscapes.scrollUp = ESC$
|
|
614
|
-
ansiEscapes.scrollDown = ESC$
|
|
544
|
+
ansiEscapes.eraseEndLine = ESC$2 + 'K';
|
|
545
|
+
ansiEscapes.eraseStartLine = ESC$2 + '1K';
|
|
546
|
+
ansiEscapes.eraseLine = ESC$2 + '2K';
|
|
547
|
+
ansiEscapes.eraseDown = ESC$2 + 'J';
|
|
548
|
+
ansiEscapes.eraseUp = ESC$2 + '1J';
|
|
549
|
+
ansiEscapes.eraseScreen = ESC$2 + '2J';
|
|
550
|
+
ansiEscapes.scrollUp = ESC$2 + 'S';
|
|
551
|
+
ansiEscapes.scrollDown = ESC$2 + 'T';
|
|
615
552
|
|
|
616
553
|
ansiEscapes.clearScreen = '\u001Bc';
|
|
617
554
|
|
|
618
555
|
ansiEscapes.clearTerminal = process.platform === 'win32' ?
|
|
619
|
-
`${ansiEscapes.eraseScreen}${ESC$
|
|
556
|
+
`${ansiEscapes.eraseScreen}${ESC$2}0f` :
|
|
620
557
|
// 1. Erases the screen (Only done in case `2` is not supported)
|
|
621
558
|
// 2. Erases the whole screen including scrollback buffer
|
|
622
559
|
// 3. Moves cursor to the top-left position
|
|
623
560
|
// More info: https://www.real-world-systems.com/docs/ANSIcode.html
|
|
624
|
-
`${ansiEscapes.eraseScreen}${ESC$
|
|
561
|
+
`${ansiEscapes.eraseScreen}${ESC$2}3J${ESC$2}H`;
|
|
625
562
|
|
|
626
563
|
ansiEscapes.beep = BEL;
|
|
627
564
|
|
|
@@ -689,370 +626,6 @@ ansiEscapes.iTerm = {
|
|
|
689
626
|
}
|
|
690
627
|
};
|
|
691
628
|
|
|
692
|
-
var onetime$1 = {exports: {}};
|
|
693
|
-
|
|
694
|
-
var mimicFn = {exports: {}};
|
|
695
|
-
|
|
696
|
-
var hasRequiredMimicFn;
|
|
697
|
-
|
|
698
|
-
function requireMimicFn () {
|
|
699
|
-
if (hasRequiredMimicFn) return mimicFn.exports;
|
|
700
|
-
hasRequiredMimicFn = 1;
|
|
701
|
-
|
|
702
|
-
const mimicFn$1 = (to, from) => {
|
|
703
|
-
for (const prop of Reflect.ownKeys(from)) {
|
|
704
|
-
Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop));
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
return to;
|
|
708
|
-
};
|
|
709
|
-
|
|
710
|
-
mimicFn.exports = mimicFn$1;
|
|
711
|
-
// TODO: Remove this for the next major release
|
|
712
|
-
mimicFn.exports.default = mimicFn$1;
|
|
713
|
-
return mimicFn.exports;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
var hasRequiredOnetime;
|
|
717
|
-
|
|
718
|
-
function requireOnetime () {
|
|
719
|
-
if (hasRequiredOnetime) return onetime$1.exports;
|
|
720
|
-
hasRequiredOnetime = 1;
|
|
721
|
-
const mimicFn = requireMimicFn();
|
|
722
|
-
|
|
723
|
-
const calledFunctions = new WeakMap();
|
|
724
|
-
|
|
725
|
-
const onetime = (function_, options = {}) => {
|
|
726
|
-
if (typeof function_ !== 'function') {
|
|
727
|
-
throw new TypeError('Expected a function');
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
let returnValue;
|
|
731
|
-
let callCount = 0;
|
|
732
|
-
const functionName = function_.displayName || function_.name || '<anonymous>';
|
|
733
|
-
|
|
734
|
-
const onetime = function (...arguments_) {
|
|
735
|
-
calledFunctions.set(onetime, ++callCount);
|
|
736
|
-
|
|
737
|
-
if (callCount === 1) {
|
|
738
|
-
returnValue = function_.apply(this, arguments_);
|
|
739
|
-
function_ = null;
|
|
740
|
-
} else if (options.throw === true) {
|
|
741
|
-
throw new Error(`Function \`${functionName}\` can only be called once`);
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
return returnValue;
|
|
745
|
-
};
|
|
746
|
-
|
|
747
|
-
mimicFn(onetime, function_);
|
|
748
|
-
calledFunctions.set(onetime, callCount);
|
|
749
|
-
|
|
750
|
-
return onetime;
|
|
751
|
-
};
|
|
752
|
-
|
|
753
|
-
onetime$1.exports = onetime;
|
|
754
|
-
// TODO: Remove this for the next major release
|
|
755
|
-
onetime$1.exports.default = onetime;
|
|
756
|
-
|
|
757
|
-
onetime$1.exports.callCount = function_ => {
|
|
758
|
-
if (!calledFunctions.has(function_)) {
|
|
759
|
-
throw new Error(`The given function \`${function_.name}\` is not wrapped by the \`onetime\` package`);
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
return calledFunctions.get(function_);
|
|
763
|
-
};
|
|
764
|
-
return onetime$1.exports;
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
var onetimeExports = requireOnetime();
|
|
768
|
-
var onetime = /*@__PURE__*/getDefaultExportFromCjs(onetimeExports);
|
|
769
|
-
|
|
770
|
-
var signalExit$1 = {exports: {}};
|
|
771
|
-
|
|
772
|
-
var signals = {exports: {}};
|
|
773
|
-
|
|
774
|
-
var hasRequiredSignals;
|
|
775
|
-
|
|
776
|
-
function requireSignals () {
|
|
777
|
-
if (hasRequiredSignals) return signals.exports;
|
|
778
|
-
hasRequiredSignals = 1;
|
|
779
|
-
(function (module) {
|
|
780
|
-
// This is not the set of all possible signals.
|
|
781
|
-
//
|
|
782
|
-
// It IS, however, the set of all signals that trigger
|
|
783
|
-
// an exit on either Linux or BSD systems. Linux is a
|
|
784
|
-
// superset of the signal names supported on BSD, and
|
|
785
|
-
// the unknown signals just fail to register, so we can
|
|
786
|
-
// catch that easily enough.
|
|
787
|
-
//
|
|
788
|
-
// Don't bother with SIGKILL. It's uncatchable, which
|
|
789
|
-
// means that we can't fire any callbacks anyway.
|
|
790
|
-
//
|
|
791
|
-
// If a user does happen to register a handler on a non-
|
|
792
|
-
// fatal signal like SIGWINCH or something, and then
|
|
793
|
-
// exit, it'll end up firing `process.emit('exit')`, so
|
|
794
|
-
// the handler will be fired anyway.
|
|
795
|
-
//
|
|
796
|
-
// SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised
|
|
797
|
-
// artificially, inherently leave the process in a
|
|
798
|
-
// state from which it is not safe to try and enter JS
|
|
799
|
-
// listeners.
|
|
800
|
-
module.exports = [
|
|
801
|
-
'SIGABRT',
|
|
802
|
-
'SIGALRM',
|
|
803
|
-
'SIGHUP',
|
|
804
|
-
'SIGINT',
|
|
805
|
-
'SIGTERM'
|
|
806
|
-
];
|
|
807
|
-
|
|
808
|
-
if (process.platform !== 'win32') {
|
|
809
|
-
module.exports.push(
|
|
810
|
-
'SIGVTALRM',
|
|
811
|
-
'SIGXCPU',
|
|
812
|
-
'SIGXFSZ',
|
|
813
|
-
'SIGUSR2',
|
|
814
|
-
'SIGTRAP',
|
|
815
|
-
'SIGSYS',
|
|
816
|
-
'SIGQUIT',
|
|
817
|
-
'SIGIOT'
|
|
818
|
-
// should detect profiler and enable/disable accordingly.
|
|
819
|
-
// see #21
|
|
820
|
-
// 'SIGPROF'
|
|
821
|
-
);
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
if (process.platform === 'linux') {
|
|
825
|
-
module.exports.push(
|
|
826
|
-
'SIGIO',
|
|
827
|
-
'SIGPOLL',
|
|
828
|
-
'SIGPWR',
|
|
829
|
-
'SIGSTKFLT',
|
|
830
|
-
'SIGUNUSED'
|
|
831
|
-
);
|
|
832
|
-
}
|
|
833
|
-
} (signals));
|
|
834
|
-
return signals.exports;
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
var hasRequiredSignalExit;
|
|
838
|
-
|
|
839
|
-
function requireSignalExit () {
|
|
840
|
-
if (hasRequiredSignalExit) return signalExit$1.exports;
|
|
841
|
-
hasRequiredSignalExit = 1;
|
|
842
|
-
// Note: since nyc uses this module to output coverage, any lines
|
|
843
|
-
// that are in the direct sync flow of nyc's outputCoverage are
|
|
844
|
-
// ignored, since we can never get coverage for them.
|
|
845
|
-
// grab a reference to node's real process object right away
|
|
846
|
-
var process = commonjsGlobal.process;
|
|
847
|
-
|
|
848
|
-
const processOk = function (process) {
|
|
849
|
-
return process &&
|
|
850
|
-
typeof process === 'object' &&
|
|
851
|
-
typeof process.removeListener === 'function' &&
|
|
852
|
-
typeof process.emit === 'function' &&
|
|
853
|
-
typeof process.reallyExit === 'function' &&
|
|
854
|
-
typeof process.listeners === 'function' &&
|
|
855
|
-
typeof process.kill === 'function' &&
|
|
856
|
-
typeof process.pid === 'number' &&
|
|
857
|
-
typeof process.on === 'function'
|
|
858
|
-
};
|
|
859
|
-
|
|
860
|
-
// some kind of non-node environment, just no-op
|
|
861
|
-
/* istanbul ignore if */
|
|
862
|
-
if (!processOk(process)) {
|
|
863
|
-
signalExit$1.exports = function () {
|
|
864
|
-
return function () {}
|
|
865
|
-
};
|
|
866
|
-
} else {
|
|
867
|
-
var assert = require$$0;
|
|
868
|
-
var signals = requireSignals();
|
|
869
|
-
var isWin = /^win/i.test(process.platform);
|
|
870
|
-
|
|
871
|
-
var EE = require$$0$1;
|
|
872
|
-
/* istanbul ignore if */
|
|
873
|
-
if (typeof EE !== 'function') {
|
|
874
|
-
EE = EE.EventEmitter;
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
var emitter;
|
|
878
|
-
if (process.__signal_exit_emitter__) {
|
|
879
|
-
emitter = process.__signal_exit_emitter__;
|
|
880
|
-
} else {
|
|
881
|
-
emitter = process.__signal_exit_emitter__ = new EE();
|
|
882
|
-
emitter.count = 0;
|
|
883
|
-
emitter.emitted = {};
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
// Because this emitter is a global, we have to check to see if a
|
|
887
|
-
// previous version of this library failed to enable infinite listeners.
|
|
888
|
-
// I know what you're about to say. But literally everything about
|
|
889
|
-
// signal-exit is a compromise with evil. Get used to it.
|
|
890
|
-
if (!emitter.infinite) {
|
|
891
|
-
emitter.setMaxListeners(Infinity);
|
|
892
|
-
emitter.infinite = true;
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
signalExit$1.exports = function (cb, opts) {
|
|
896
|
-
/* istanbul ignore if */
|
|
897
|
-
if (!processOk(commonjsGlobal.process)) {
|
|
898
|
-
return function () {}
|
|
899
|
-
}
|
|
900
|
-
assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler');
|
|
901
|
-
|
|
902
|
-
if (loaded === false) {
|
|
903
|
-
load();
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
var ev = 'exit';
|
|
907
|
-
if (opts && opts.alwaysLast) {
|
|
908
|
-
ev = 'afterexit';
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
var remove = function () {
|
|
912
|
-
emitter.removeListener(ev, cb);
|
|
913
|
-
if (emitter.listeners('exit').length === 0 &&
|
|
914
|
-
emitter.listeners('afterexit').length === 0) {
|
|
915
|
-
unload();
|
|
916
|
-
}
|
|
917
|
-
};
|
|
918
|
-
emitter.on(ev, cb);
|
|
919
|
-
|
|
920
|
-
return remove
|
|
921
|
-
};
|
|
922
|
-
|
|
923
|
-
var unload = function unload () {
|
|
924
|
-
if (!loaded || !processOk(commonjsGlobal.process)) {
|
|
925
|
-
return
|
|
926
|
-
}
|
|
927
|
-
loaded = false;
|
|
928
|
-
|
|
929
|
-
signals.forEach(function (sig) {
|
|
930
|
-
try {
|
|
931
|
-
process.removeListener(sig, sigListeners[sig]);
|
|
932
|
-
} catch (er) {}
|
|
933
|
-
});
|
|
934
|
-
process.emit = originalProcessEmit;
|
|
935
|
-
process.reallyExit = originalProcessReallyExit;
|
|
936
|
-
emitter.count -= 1;
|
|
937
|
-
};
|
|
938
|
-
signalExit$1.exports.unload = unload;
|
|
939
|
-
|
|
940
|
-
var emit = function emit (event, code, signal) {
|
|
941
|
-
/* istanbul ignore if */
|
|
942
|
-
if (emitter.emitted[event]) {
|
|
943
|
-
return
|
|
944
|
-
}
|
|
945
|
-
emitter.emitted[event] = true;
|
|
946
|
-
emitter.emit(event, code, signal);
|
|
947
|
-
};
|
|
948
|
-
|
|
949
|
-
// { <signal>: <listener fn>, ... }
|
|
950
|
-
var sigListeners = {};
|
|
951
|
-
signals.forEach(function (sig) {
|
|
952
|
-
sigListeners[sig] = function listener () {
|
|
953
|
-
/* istanbul ignore if */
|
|
954
|
-
if (!processOk(commonjsGlobal.process)) {
|
|
955
|
-
return
|
|
956
|
-
}
|
|
957
|
-
// If there are no other listeners, an exit is coming!
|
|
958
|
-
// Simplest way: remove us and then re-send the signal.
|
|
959
|
-
// We know that this will kill the process, so we can
|
|
960
|
-
// safely emit now.
|
|
961
|
-
var listeners = process.listeners(sig);
|
|
962
|
-
if (listeners.length === emitter.count) {
|
|
963
|
-
unload();
|
|
964
|
-
emit('exit', null, sig);
|
|
965
|
-
/* istanbul ignore next */
|
|
966
|
-
emit('afterexit', null, sig);
|
|
967
|
-
/* istanbul ignore next */
|
|
968
|
-
if (isWin && sig === 'SIGHUP') {
|
|
969
|
-
// "SIGHUP" throws an `ENOSYS` error on Windows,
|
|
970
|
-
// so use a supported signal instead
|
|
971
|
-
sig = 'SIGINT';
|
|
972
|
-
}
|
|
973
|
-
/* istanbul ignore next */
|
|
974
|
-
process.kill(process.pid, sig);
|
|
975
|
-
}
|
|
976
|
-
};
|
|
977
|
-
});
|
|
978
|
-
|
|
979
|
-
signalExit$1.exports.signals = function () {
|
|
980
|
-
return signals
|
|
981
|
-
};
|
|
982
|
-
|
|
983
|
-
var loaded = false;
|
|
984
|
-
|
|
985
|
-
var load = function load () {
|
|
986
|
-
if (loaded || !processOk(commonjsGlobal.process)) {
|
|
987
|
-
return
|
|
988
|
-
}
|
|
989
|
-
loaded = true;
|
|
990
|
-
|
|
991
|
-
// This is the number of onSignalExit's that are in play.
|
|
992
|
-
// It's important so that we can count the correct number of
|
|
993
|
-
// listeners on signals, and don't wait for the other one to
|
|
994
|
-
// handle it instead of us.
|
|
995
|
-
emitter.count += 1;
|
|
996
|
-
|
|
997
|
-
signals = signals.filter(function (sig) {
|
|
998
|
-
try {
|
|
999
|
-
process.on(sig, sigListeners[sig]);
|
|
1000
|
-
return true
|
|
1001
|
-
} catch (er) {
|
|
1002
|
-
return false
|
|
1003
|
-
}
|
|
1004
|
-
});
|
|
1005
|
-
|
|
1006
|
-
process.emit = processEmit;
|
|
1007
|
-
process.reallyExit = processReallyExit;
|
|
1008
|
-
};
|
|
1009
|
-
signalExit$1.exports.load = load;
|
|
1010
|
-
|
|
1011
|
-
var originalProcessReallyExit = process.reallyExit;
|
|
1012
|
-
var processReallyExit = function processReallyExit (code) {
|
|
1013
|
-
/* istanbul ignore if */
|
|
1014
|
-
if (!processOk(commonjsGlobal.process)) {
|
|
1015
|
-
return
|
|
1016
|
-
}
|
|
1017
|
-
process.exitCode = code || /* istanbul ignore next */ 0;
|
|
1018
|
-
emit('exit', process.exitCode, null);
|
|
1019
|
-
/* istanbul ignore next */
|
|
1020
|
-
emit('afterexit', process.exitCode, null);
|
|
1021
|
-
/* istanbul ignore next */
|
|
1022
|
-
originalProcessReallyExit.call(process, process.exitCode);
|
|
1023
|
-
};
|
|
1024
|
-
|
|
1025
|
-
var originalProcessEmit = process.emit;
|
|
1026
|
-
var processEmit = function processEmit (ev, arg) {
|
|
1027
|
-
if (ev === 'exit' && processOk(commonjsGlobal.process)) {
|
|
1028
|
-
/* istanbul ignore else */
|
|
1029
|
-
if (arg !== undefined) {
|
|
1030
|
-
process.exitCode = arg;
|
|
1031
|
-
}
|
|
1032
|
-
var ret = originalProcessEmit.apply(this, arguments);
|
|
1033
|
-
/* istanbul ignore next */
|
|
1034
|
-
emit('exit', process.exitCode, null);
|
|
1035
|
-
/* istanbul ignore next */
|
|
1036
|
-
emit('afterexit', process.exitCode, null);
|
|
1037
|
-
/* istanbul ignore next */
|
|
1038
|
-
return ret
|
|
1039
|
-
} else {
|
|
1040
|
-
return originalProcessEmit.apply(this, arguments)
|
|
1041
|
-
}
|
|
1042
|
-
};
|
|
1043
|
-
}
|
|
1044
|
-
return signalExit$1.exports;
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
var signalExitExports = requireSignalExit();
|
|
1048
|
-
var signalExit = /*@__PURE__*/getDefaultExportFromCjs(signalExitExports);
|
|
1049
|
-
|
|
1050
|
-
const restoreCursor = onetime(() => {
|
|
1051
|
-
signalExit(() => {
|
|
1052
|
-
process$1.stderr.write('\u001B[?25h');
|
|
1053
|
-
}, {alwaysLast: true});
|
|
1054
|
-
});
|
|
1055
|
-
|
|
1056
629
|
let isHidden = false;
|
|
1057
630
|
|
|
1058
631
|
const cliCursor = {};
|
|
@@ -3026,10 +2599,10 @@ function lineNo(no = "") {
|
|
|
3026
2599
|
}
|
|
3027
2600
|
|
|
3028
2601
|
const PAD = " ";
|
|
3029
|
-
const ESC = "\x1B[";
|
|
3030
|
-
const ERASE_DOWN = `${ESC}J`;
|
|
3031
|
-
const ERASE_SCROLLBACK = `${ESC}3J`;
|
|
3032
|
-
const CURSOR_TO_START = `${ESC}1;1H`;
|
|
2602
|
+
const ESC$1 = "\x1B[";
|
|
2603
|
+
const ERASE_DOWN = `${ESC$1}J`;
|
|
2604
|
+
const ERASE_SCROLLBACK = `${ESC$1}3J`;
|
|
2605
|
+
const CURSOR_TO_START = `${ESC$1}1;1H`;
|
|
3033
2606
|
const CLEAR_SCREEN = "\x1Bc";
|
|
3034
2607
|
class Logger {
|
|
3035
2608
|
constructor(ctx, outputStream = process.stdout, errorStream = process.stderr) {
|
|
@@ -3088,7 +2661,7 @@ class Logger {
|
|
|
3088
2661
|
}
|
|
3089
2662
|
printError(err, options = {}) {
|
|
3090
2663
|
const { fullStack = false, type } = options;
|
|
3091
|
-
const project = options.project ?? this.ctx.
|
|
2664
|
+
const project = options.project ?? this.ctx.coreWorkspaceProject ?? this.ctx.projects[0];
|
|
3092
2665
|
return printError(err, project, {
|
|
3093
2666
|
type,
|
|
3094
2667
|
showCodeFrame: options.showCodeFrame ?? true,
|
|
@@ -3137,8 +2710,7 @@ class Logger {
|
|
|
3137
2710
|
}
|
|
3138
2711
|
this.ctx.projects.forEach((project) => {
|
|
3139
2712
|
const config2 = project.config;
|
|
3140
|
-
const
|
|
3141
|
-
const output = project.isCore() || !name ? "" : `[${name}]`;
|
|
2713
|
+
const output = project.isRootProject() || !project.name ? "" : `[${project.name}]`;
|
|
3142
2714
|
if (output) {
|
|
3143
2715
|
this.console.error(c.bgCyan(`${output} Config`));
|
|
3144
2716
|
}
|
|
@@ -3214,8 +2786,7 @@ Vitest is running in standalone mode. Edit a test file to rerun tests.`));
|
|
|
3214
2786
|
if (!origin) {
|
|
3215
2787
|
return;
|
|
3216
2788
|
}
|
|
3217
|
-
const
|
|
3218
|
-
const output = project.isCore() ? "" : formatProjectName(name);
|
|
2789
|
+
const output = project.isRootProject() ? "" : formatProjectName(project.name);
|
|
3219
2790
|
const provider = project.browser.provider.name;
|
|
3220
2791
|
const providerString = provider === "preview" ? "" : ` by ${c.reset(c.bold(provider))}`;
|
|
3221
2792
|
this.log(
|
|
@@ -3296,7 +2867,7 @@ class BlobReporter {
|
|
|
3296
2867
|
(project) => {
|
|
3297
2868
|
return [
|
|
3298
2869
|
project.getName(),
|
|
3299
|
-
[...project.
|
|
2870
|
+
[...project.vite.moduleGraph.idToModuleMap.entries()].map((mod) => {
|
|
3300
2871
|
if (!mod[1].file) {
|
|
3301
2872
|
return null;
|
|
3302
2873
|
}
|
|
@@ -3372,10 +2943,10 @@ ${blobs.map((b) => `- "${b.file}" uses v${b.version}`).join("\n")}`
|
|
|
3372
2943
|
return;
|
|
3373
2944
|
}
|
|
3374
2945
|
moduleIds.forEach(([moduleId, file, url]) => {
|
|
3375
|
-
const moduleNode = project.
|
|
2946
|
+
const moduleNode = project.vite.moduleGraph.createFileOnlyEntry(file);
|
|
3376
2947
|
moduleNode.url = url;
|
|
3377
2948
|
moduleNode.id = moduleId;
|
|
3378
|
-
project.
|
|
2949
|
+
project.vite.moduleGraph.idToModuleMap.set(moduleId, moduleNode);
|
|
3379
2950
|
});
|
|
3380
2951
|
});
|
|
3381
2952
|
});
|
|
@@ -3402,7 +2973,6 @@ function hasFailedSnapshot(suite) {
|
|
|
3402
2973
|
}
|
|
3403
2974
|
|
|
3404
2975
|
const BADGE_PADDING = " ";
|
|
3405
|
-
const LAST_RUN_LOG_TIMEOUT = 1500;
|
|
3406
2976
|
class BaseReporter {
|
|
3407
2977
|
start = 0;
|
|
3408
2978
|
end = 0;
|
|
@@ -3410,19 +2980,17 @@ class BaseReporter {
|
|
|
3410
2980
|
failedUnwatchedFiles = [];
|
|
3411
2981
|
isTTY;
|
|
3412
2982
|
ctx = void 0;
|
|
2983
|
+
renderSucceed = false;
|
|
3413
2984
|
verbose = false;
|
|
3414
2985
|
_filesInWatchMode = /* @__PURE__ */ new Map();
|
|
3415
2986
|
_timeStart = formatTimeString(/* @__PURE__ */ new Date());
|
|
3416
|
-
_lastRunTimeout = 0;
|
|
3417
|
-
_lastRunTimer;
|
|
3418
|
-
_lastRunCount = 0;
|
|
3419
2987
|
constructor(options = {}) {
|
|
3420
2988
|
this.isTTY = options.isTTY ?? ((isNode || isDeno) && process.stdout?.isTTY && !isCI);
|
|
3421
2989
|
}
|
|
3422
2990
|
onInit(ctx) {
|
|
3423
2991
|
this.ctx = ctx;
|
|
3424
2992
|
this.ctx.logger.printBanner();
|
|
3425
|
-
this.start = performance.now();
|
|
2993
|
+
this.start = performance$1.now();
|
|
3426
2994
|
}
|
|
3427
2995
|
log(...messages) {
|
|
3428
2996
|
this.ctx.logger.log(...messages);
|
|
@@ -3434,13 +3002,10 @@ class BaseReporter {
|
|
|
3434
3002
|
return relative(this.ctx.config.root, path);
|
|
3435
3003
|
}
|
|
3436
3004
|
onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
|
|
3437
|
-
this.end = performance.now();
|
|
3005
|
+
this.end = performance$1.now();
|
|
3438
3006
|
this.reportSummary(files, errors);
|
|
3439
3007
|
}
|
|
3440
3008
|
onTaskUpdate(packs) {
|
|
3441
|
-
if (this.isTTY) {
|
|
3442
|
-
return;
|
|
3443
|
-
}
|
|
3444
3009
|
for (const pack of packs) {
|
|
3445
3010
|
const task = this.ctx.state.idMap.get(pack[0]);
|
|
3446
3011
|
if (task) {
|
|
@@ -3474,6 +3039,7 @@ class BaseReporter {
|
|
|
3474
3039
|
title += ` ${formatProjectName(task.projectName, "")}`;
|
|
3475
3040
|
}
|
|
3476
3041
|
this.log(` ${title} ${task.name} ${suffix}`);
|
|
3042
|
+
const anyFailed = tests.some((test) => test.result?.state === "fail");
|
|
3477
3043
|
for (const test of tests) {
|
|
3478
3044
|
const duration = test.result?.duration;
|
|
3479
3045
|
if (test.result?.state === "fail") {
|
|
@@ -3486,6 +3052,10 @@ class BaseReporter {
|
|
|
3486
3052
|
this.log(
|
|
3487
3053
|
` ${c.yellow(c.dim(F_CHECK))} ${getTestName(test, c.dim(" > "))} ${c.yellow(Math.round(duration) + c.dim("ms"))}`
|
|
3488
3054
|
);
|
|
3055
|
+
} else if (test.result?.state === "skip" && test.result.note) {
|
|
3056
|
+
this.log(` ${getStateSymbol(test)} ${getTestName(test)}${c.dim(c.gray(` [${test.result.note}]`))}`);
|
|
3057
|
+
} else if (this.renderSucceed || anyFailed) {
|
|
3058
|
+
this.log(` ${c.green(c.dim(F_CHECK))} ${getTestName(test, c.dim(" > "))}`);
|
|
3489
3059
|
}
|
|
3490
3060
|
}
|
|
3491
3061
|
}
|
|
@@ -3497,7 +3067,6 @@ class BaseReporter {
|
|
|
3497
3067
|
return color(` ${Math.round(task.result.duration)}${c.dim("ms")}`);
|
|
3498
3068
|
}
|
|
3499
3069
|
onWatcherStart(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
|
|
3500
|
-
this.resetLastRunLog();
|
|
3501
3070
|
const failed = errors.length > 0 || hasFailed(files);
|
|
3502
3071
|
if (failed) {
|
|
3503
3072
|
this.log(withLabel("red", "FAIL", "Tests failed. Watching for file changes..."));
|
|
@@ -3513,34 +3082,8 @@ class BaseReporter {
|
|
|
3513
3082
|
hints.push(c.dim("press ") + c.bold("q") + c.dim(" to quit"));
|
|
3514
3083
|
}
|
|
3515
3084
|
this.log(BADGE_PADDING + hints.join(c.dim(", ")));
|
|
3516
|
-
if (this._lastRunCount) {
|
|
3517
|
-
const LAST_RUN_TEXT = `rerun x${this._lastRunCount}`;
|
|
3518
|
-
const LAST_RUN_TEXTS = [
|
|
3519
|
-
c.blue(LAST_RUN_TEXT),
|
|
3520
|
-
c.gray(LAST_RUN_TEXT),
|
|
3521
|
-
c.dim(c.gray(LAST_RUN_TEXT))
|
|
3522
|
-
];
|
|
3523
|
-
this.ctx.logger.logUpdate(BADGE_PADDING + LAST_RUN_TEXTS[0]);
|
|
3524
|
-
this._lastRunTimeout = 0;
|
|
3525
|
-
this._lastRunTimer = setInterval(() => {
|
|
3526
|
-
this._lastRunTimeout += 1;
|
|
3527
|
-
if (this._lastRunTimeout >= LAST_RUN_TEXTS.length) {
|
|
3528
|
-
this.resetLastRunLog();
|
|
3529
|
-
} else {
|
|
3530
|
-
this.ctx.logger.logUpdate(
|
|
3531
|
-
BADGE_PADDING + LAST_RUN_TEXTS[this._lastRunTimeout]
|
|
3532
|
-
);
|
|
3533
|
-
}
|
|
3534
|
-
}, LAST_RUN_LOG_TIMEOUT / LAST_RUN_TEXTS.length);
|
|
3535
|
-
}
|
|
3536
|
-
}
|
|
3537
|
-
resetLastRunLog() {
|
|
3538
|
-
clearInterval(this._lastRunTimer);
|
|
3539
|
-
this._lastRunTimer = void 0;
|
|
3540
|
-
this.ctx.logger.logUpdate.clear();
|
|
3541
3085
|
}
|
|
3542
3086
|
onWatcherRerun(files, trigger) {
|
|
3543
|
-
this.resetLastRunLog();
|
|
3544
3087
|
this.watchFilters = files;
|
|
3545
3088
|
this.failedUnwatchedFiles = this.ctx.state.getFiles().filter(
|
|
3546
3089
|
(file) => !files.includes(file.filepath) && hasFailed(file)
|
|
@@ -3550,9 +3093,7 @@ class BaseReporter {
|
|
|
3550
3093
|
this._filesInWatchMode.set(filepath, ++reruns);
|
|
3551
3094
|
});
|
|
3552
3095
|
let banner = trigger ? c.dim(`${this.relative(trigger)} `) : "";
|
|
3553
|
-
if (files.length
|
|
3554
|
-
this._lastRunCount = 0;
|
|
3555
|
-
} else if (files.length === 1) {
|
|
3096
|
+
if (files.length === 1) {
|
|
3556
3097
|
const rerun = this._filesInWatchMode.get(files[0]) ?? 1;
|
|
3557
3098
|
banner += c.blue(`x${rerun} `);
|
|
3558
3099
|
}
|
|
@@ -3568,13 +3109,11 @@ class BaseReporter {
|
|
|
3568
3109
|
this.log(BADGE_PADDING + c.dim(" Test name pattern: ") + c.blue(String(this.ctx.configOverride.testNamePattern)));
|
|
3569
3110
|
}
|
|
3570
3111
|
this.log("");
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
this.printTask(task);
|
|
3574
|
-
}
|
|
3112
|
+
for (const task of this.failedUnwatchedFiles) {
|
|
3113
|
+
this.printTask(task);
|
|
3575
3114
|
}
|
|
3576
3115
|
this._timeStart = formatTimeString(/* @__PURE__ */ new Date());
|
|
3577
|
-
this.start = performance.now();
|
|
3116
|
+
this.start = performance$1.now();
|
|
3578
3117
|
}
|
|
3579
3118
|
onUserConsoleLog(log) {
|
|
3580
3119
|
if (!this.shouldLog(log)) {
|
|
@@ -3595,7 +3134,7 @@ class BaseReporter {
|
|
|
3595
3134
|
if (log.browser) {
|
|
3596
3135
|
write("\n");
|
|
3597
3136
|
}
|
|
3598
|
-
const project = log.taskId ? this.ctx.getProjectByTaskId(log.taskId) : this.ctx.
|
|
3137
|
+
const project = log.taskId ? this.ctx.getProjectByTaskId(log.taskId) : this.ctx.getRootTestProject();
|
|
3599
3138
|
const stack = log.browser ? project.browser?.parseStacktrace(log.origin) || [] : parseStacktrace(log.origin);
|
|
3600
3139
|
const highlight = task && stack.find((i) => i.file === task.file.filepath);
|
|
3601
3140
|
for (const frame of stack) {
|
|
@@ -3639,6 +3178,7 @@ class BaseReporter {
|
|
|
3639
3178
|
}
|
|
3640
3179
|
}
|
|
3641
3180
|
reportTestSummary(files, errors) {
|
|
3181
|
+
this.log();
|
|
3642
3182
|
const affectedFiles = [
|
|
3643
3183
|
...this.failedUnwatchedFiles,
|
|
3644
3184
|
...files
|
|
@@ -3650,32 +3190,32 @@ class BaseReporter {
|
|
|
3650
3190
|
);
|
|
3651
3191
|
for (const [index, snapshot] of snapshotOutput.entries()) {
|
|
3652
3192
|
const title = index === 0 ? "Snapshots" : "";
|
|
3653
|
-
this.log(`${
|
|
3193
|
+
this.log(`${padSummaryTitle(title)} ${snapshot}`);
|
|
3654
3194
|
}
|
|
3655
3195
|
if (snapshotOutput.length > 1) {
|
|
3656
3196
|
this.log();
|
|
3657
3197
|
}
|
|
3658
|
-
this.log(
|
|
3659
|
-
this.log(
|
|
3198
|
+
this.log(padSummaryTitle("Test Files"), getStateString$1(affectedFiles));
|
|
3199
|
+
this.log(padSummaryTitle("Tests"), getStateString$1(tests));
|
|
3660
3200
|
if (this.ctx.projects.some((c2) => c2.config.typecheck.enabled)) {
|
|
3661
3201
|
const failed = tests.filter((t) => t.meta?.typecheck && t.result?.errors?.length);
|
|
3662
3202
|
this.log(
|
|
3663
|
-
|
|
3203
|
+
padSummaryTitle("Type Errors"),
|
|
3664
3204
|
failed.length ? c.bold(c.red(`${failed.length} failed`)) : c.dim("no errors")
|
|
3665
3205
|
);
|
|
3666
3206
|
}
|
|
3667
3207
|
if (errors.length) {
|
|
3668
3208
|
this.log(
|
|
3669
|
-
|
|
3209
|
+
padSummaryTitle("Errors"),
|
|
3670
3210
|
c.bold(c.red(`${errors.length} error${errors.length > 1 ? "s" : ""}`))
|
|
3671
3211
|
);
|
|
3672
3212
|
}
|
|
3673
|
-
this.log(
|
|
3213
|
+
this.log(padSummaryTitle("Start at"), this._timeStart);
|
|
3674
3214
|
const collectTime = sum(files, (file) => file.collectDuration);
|
|
3675
3215
|
const testsTime = sum(files, (file) => file.result?.duration);
|
|
3676
3216
|
const setupTime = sum(files, (file) => file.setupDuration);
|
|
3677
3217
|
if (this.watchFilters) {
|
|
3678
|
-
this.log(
|
|
3218
|
+
this.log(padSummaryTitle("Duration"), formatTime(collectTime + testsTime + setupTime));
|
|
3679
3219
|
} else {
|
|
3680
3220
|
const executionTime = this.end - this.start;
|
|
3681
3221
|
const environmentTime = sum(files, (file) => file.environmentLoad);
|
|
@@ -3683,15 +3223,15 @@ class BaseReporter {
|
|
|
3683
3223
|
const transformTime = sum(this.ctx.projects, (project) => project.vitenode.getTotalDuration());
|
|
3684
3224
|
const typecheck = sum(this.ctx.projects, (project) => project.typechecker?.getResult().time);
|
|
3685
3225
|
const timers = [
|
|
3686
|
-
`transform ${
|
|
3687
|
-
`setup ${
|
|
3688
|
-
`collect ${
|
|
3689
|
-
`tests ${
|
|
3690
|
-
`environment ${
|
|
3691
|
-
`prepare ${
|
|
3692
|
-
typecheck && `typecheck ${
|
|
3226
|
+
`transform ${formatTime(transformTime)}`,
|
|
3227
|
+
`setup ${formatTime(setupTime)}`,
|
|
3228
|
+
`collect ${formatTime(collectTime)}`,
|
|
3229
|
+
`tests ${formatTime(testsTime)}`,
|
|
3230
|
+
`environment ${formatTime(environmentTime)}`,
|
|
3231
|
+
`prepare ${formatTime(prepareTime)}`,
|
|
3232
|
+
typecheck && `typecheck ${formatTime(typecheck)}`
|
|
3693
3233
|
].filter(Boolean).join(", ");
|
|
3694
|
-
this.log(
|
|
3234
|
+
this.log(padSummaryTitle("Duration"), formatTime(executionTime) + c.dim(` (${timers})`));
|
|
3695
3235
|
}
|
|
3696
3236
|
this.log();
|
|
3697
3237
|
}
|
|
@@ -3786,15 +3326,6 @@ class BaseReporter {
|
|
|
3786
3326
|
function errorBanner(message) {
|
|
3787
3327
|
return c.red(divider(c.bold(c.inverse(` ${message} `))));
|
|
3788
3328
|
}
|
|
3789
|
-
function padTitle(str) {
|
|
3790
|
-
return c.dim(`${str.padStart(11)} `);
|
|
3791
|
-
}
|
|
3792
|
-
function time(time2) {
|
|
3793
|
-
if (time2 > 1e3) {
|
|
3794
|
-
return `${(time2 / 1e3).toFixed(2)}s`;
|
|
3795
|
-
}
|
|
3796
|
-
return `${Math.round(time2)}ms`;
|
|
3797
|
-
}
|
|
3798
3329
|
function sum(items, cb) {
|
|
3799
3330
|
return items.reduce((total, next) => {
|
|
3800
3331
|
return total + Math.max(cb(next) || 0, 0);
|
|
@@ -3806,289 +3337,521 @@ class BasicReporter extends BaseReporter {
|
|
|
3806
3337
|
super();
|
|
3807
3338
|
this.isTTY = false;
|
|
3808
3339
|
}
|
|
3340
|
+
onInit(ctx) {
|
|
3341
|
+
super.onInit(ctx);
|
|
3342
|
+
ctx.logger.log(c.inverse(c.bold(c.yellow(" DEPRECATED "))), c.yellow(
|
|
3343
|
+
`'basic' reporter is deprecated and will be removed in Vitest v3.
|
|
3344
|
+
Remove 'basic' from 'reporters' option. To match 'basic' reporter 100%, use configuration:
|
|
3345
|
+
${JSON.stringify({ test: { reporters: [["default", { summary: false }]] } }, null, 2)}`
|
|
3346
|
+
));
|
|
3347
|
+
}
|
|
3809
3348
|
reportSummary(files, errors) {
|
|
3810
3349
|
this.ctx.logger.log();
|
|
3811
3350
|
return super.reportSummary(files, errors);
|
|
3812
3351
|
}
|
|
3813
3352
|
}
|
|
3814
3353
|
|
|
3815
|
-
const
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3354
|
+
const DEFAULT_RENDER_INTERVAL = 16;
|
|
3355
|
+
const ESC = "\x1B[";
|
|
3356
|
+
const CLEAR_LINE = `${ESC}K`;
|
|
3357
|
+
const MOVE_CURSOR_ONE_ROW_UP = `${ESC}1A`;
|
|
3358
|
+
const HIDE_CURSOR = `${ESC}?25l`;
|
|
3359
|
+
const SHOW_CURSOR = `${ESC}?25h`;
|
|
3360
|
+
const SYNC_START = `${ESC}?2026h`;
|
|
3361
|
+
const SYNC_END = `${ESC}?2026l`;
|
|
3362
|
+
class WindowRenderer {
|
|
3363
|
+
options;
|
|
3364
|
+
streams;
|
|
3365
|
+
buffer = [];
|
|
3366
|
+
renderInterval = void 0;
|
|
3367
|
+
windowHeight = 0;
|
|
3368
|
+
finished = false;
|
|
3369
|
+
cleanups = [];
|
|
3370
|
+
constructor(options) {
|
|
3371
|
+
this.options = {
|
|
3372
|
+
interval: DEFAULT_RENDER_INTERVAL,
|
|
3373
|
+
...options
|
|
3374
|
+
};
|
|
3375
|
+
this.streams = {
|
|
3376
|
+
output: options.logger.outputStream.write.bind(options.logger.outputStream),
|
|
3377
|
+
error: options.logger.errorStream.write.bind(options.logger.errorStream)
|
|
3378
|
+
};
|
|
3379
|
+
this.cleanups.push(
|
|
3380
|
+
this.interceptStream(process.stdout, "output"),
|
|
3381
|
+
this.interceptStream(process.stderr, "error")
|
|
3382
|
+
);
|
|
3383
|
+
restoreCursor();
|
|
3384
|
+
this.write(HIDE_CURSOR, "output");
|
|
3385
|
+
this.start();
|
|
3822
3386
|
}
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
const width = Math.max(...allItems.map((i2) => i2[idx].length));
|
|
3858
|
-
return idx ? i.padStart(width, " ") : i.padEnd(width, " ");
|
|
3859
|
-
});
|
|
3860
|
-
return [
|
|
3861
|
-
padded[0],
|
|
3862
|
-
// name
|
|
3863
|
-
c.dim(" "),
|
|
3864
|
-
c.blue(padded[1]),
|
|
3865
|
-
c.dim(" ops/sec "),
|
|
3866
|
-
c.cyan(padded[3]),
|
|
3867
|
-
c.dim(` (${padded[4]} samples)`),
|
|
3868
|
-
result.rank === 1 ? c.bold(c.green(" fastest")) : result.rank === benches.length && benches.length > 2 ? c.bold(c.gray(" slowest")) : ""
|
|
3869
|
-
].join("");
|
|
3870
|
-
}
|
|
3871
|
-
function renderTree$1(tasks, options, level = 0, maxRows) {
|
|
3872
|
-
const output = [];
|
|
3873
|
-
let currentRowCount = 0;
|
|
3874
|
-
for (const task of [...tasks].reverse()) {
|
|
3875
|
-
const taskOutput = [];
|
|
3876
|
-
let suffix = "";
|
|
3877
|
-
let prefix = ` ${getStateSymbol(task)} `;
|
|
3878
|
-
if (level === 0 && task.type === "suite" && "projectName" in task) {
|
|
3879
|
-
prefix += formatProjectName(task.projectName);
|
|
3880
|
-
}
|
|
3881
|
-
if (level === 0 && task.type === "suite" && task.meta.typecheck) {
|
|
3882
|
-
prefix += c.bgBlue(c.bold(" TS "));
|
|
3883
|
-
prefix += " ";
|
|
3387
|
+
start() {
|
|
3388
|
+
this.finished = false;
|
|
3389
|
+
this.renderInterval = setInterval(() => this.flushBuffer(), this.options.interval);
|
|
3390
|
+
}
|
|
3391
|
+
stop() {
|
|
3392
|
+
this.write(SHOW_CURSOR, "output");
|
|
3393
|
+
this.cleanups.splice(0).map((fn) => fn());
|
|
3394
|
+
clearInterval(this.renderInterval);
|
|
3395
|
+
}
|
|
3396
|
+
/**
|
|
3397
|
+
* Write all buffered output and stop buffering.
|
|
3398
|
+
* All intercepted writes are forwarded to actual write after this.
|
|
3399
|
+
*/
|
|
3400
|
+
finish() {
|
|
3401
|
+
this.finished = true;
|
|
3402
|
+
this.flushBuffer();
|
|
3403
|
+
clearInterval(this.renderInterval);
|
|
3404
|
+
}
|
|
3405
|
+
flushBuffer() {
|
|
3406
|
+
if (this.buffer.length === 0) {
|
|
3407
|
+
return this.render();
|
|
3408
|
+
}
|
|
3409
|
+
let current;
|
|
3410
|
+
for (const next of this.buffer.splice(0)) {
|
|
3411
|
+
if (!current) {
|
|
3412
|
+
current = next;
|
|
3413
|
+
continue;
|
|
3414
|
+
}
|
|
3415
|
+
if (current.type !== next.type) {
|
|
3416
|
+
this.render(current.message, current.type);
|
|
3417
|
+
current = next;
|
|
3418
|
+
continue;
|
|
3419
|
+
}
|
|
3420
|
+
current.message += next.message;
|
|
3884
3421
|
}
|
|
3885
|
-
if (
|
|
3886
|
-
|
|
3422
|
+
if (current) {
|
|
3423
|
+
this.render(current?.message, current?.type);
|
|
3887
3424
|
}
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3425
|
+
}
|
|
3426
|
+
render(message, type = "output") {
|
|
3427
|
+
if (this.finished) {
|
|
3428
|
+
this.clearWindow();
|
|
3429
|
+
return this.write(message || "", type);
|
|
3891
3430
|
}
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3431
|
+
const windowContent = this.options.getWindow();
|
|
3432
|
+
const rowCount = getRenderedRowCount(windowContent, this.options.logger.outputStream);
|
|
3433
|
+
let padding = this.windowHeight - rowCount;
|
|
3434
|
+
if (padding > 0 && message) {
|
|
3435
|
+
padding -= getRenderedRowCount([message], this.options.logger.outputStream);
|
|
3895
3436
|
}
|
|
3896
|
-
|
|
3897
|
-
|
|
3437
|
+
this.write(SYNC_START);
|
|
3438
|
+
this.clearWindow();
|
|
3439
|
+
if (message) {
|
|
3440
|
+
this.write(message, type);
|
|
3898
3441
|
}
|
|
3899
|
-
if (
|
|
3900
|
-
|
|
3901
|
-
suffix += c.yellow(
|
|
3902
|
-
` ${Math.round(task.result.duration)}${c.dim("ms")}`
|
|
3903
|
-
);
|
|
3904
|
-
}
|
|
3442
|
+
if (padding > 0) {
|
|
3443
|
+
this.write("\n".repeat(padding));
|
|
3905
3444
|
}
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3445
|
+
this.write(windowContent.join("\n"));
|
|
3446
|
+
this.write(SYNC_END);
|
|
3447
|
+
this.windowHeight = rowCount + Math.max(0, padding);
|
|
3448
|
+
}
|
|
3449
|
+
clearWindow() {
|
|
3450
|
+
if (this.windowHeight === 0) {
|
|
3451
|
+
return;
|
|
3910
3452
|
}
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3453
|
+
this.write(CLEAR_LINE);
|
|
3454
|
+
for (let i = 1; i < this.windowHeight; i++) {
|
|
3455
|
+
this.write(`${MOVE_CURSOR_ONE_ROW_UP}${CLEAR_LINE}`);
|
|
3914
3456
|
}
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
if (
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3457
|
+
this.windowHeight = 0;
|
|
3458
|
+
}
|
|
3459
|
+
interceptStream(stream, type) {
|
|
3460
|
+
const original = stream.write;
|
|
3461
|
+
stream.write = (chunk, _, callback) => {
|
|
3462
|
+
if (chunk) {
|
|
3463
|
+
if (this.finished) {
|
|
3464
|
+
this.write(chunk.toString(), type);
|
|
3465
|
+
} else {
|
|
3466
|
+
this.buffer.push({ type, message: chunk.toString() });
|
|
3924
3467
|
}
|
|
3925
3468
|
}
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
}
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3469
|
+
callback?.();
|
|
3470
|
+
};
|
|
3471
|
+
return function restore() {
|
|
3472
|
+
stream.write = original;
|
|
3473
|
+
};
|
|
3474
|
+
}
|
|
3475
|
+
write(message, type = "output") {
|
|
3476
|
+
this.streams[type](message);
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
function getRenderedRowCount(rows, stream) {
|
|
3480
|
+
let count = 0;
|
|
3481
|
+
const columns = "columns" in stream ? stream.columns : 80;
|
|
3482
|
+
for (const row of rows) {
|
|
3483
|
+
const text = stripVTControlCharacters(row);
|
|
3484
|
+
count += Math.max(1, Math.ceil(text.length / columns));
|
|
3485
|
+
}
|
|
3486
|
+
return count;
|
|
3487
|
+
}
|
|
3488
|
+
|
|
3489
|
+
class TaskParser {
|
|
3490
|
+
ctx;
|
|
3491
|
+
onInit(ctx) {
|
|
3492
|
+
this.ctx = ctx;
|
|
3493
|
+
}
|
|
3494
|
+
onHookStart(_options) {
|
|
3495
|
+
}
|
|
3496
|
+
onHookEnd(_options) {
|
|
3497
|
+
}
|
|
3498
|
+
onTestStart(_test) {
|
|
3499
|
+
}
|
|
3500
|
+
onTestFinished(_test) {
|
|
3501
|
+
}
|
|
3502
|
+
onTestFilePrepare(_file) {
|
|
3503
|
+
}
|
|
3504
|
+
onTestFileFinished(_file) {
|
|
3505
|
+
}
|
|
3506
|
+
onTaskUpdate(packs) {
|
|
3507
|
+
const startingTestFiles = [];
|
|
3508
|
+
const finishedTestFiles = [];
|
|
3509
|
+
const startingTests = [];
|
|
3510
|
+
const finishedTests = [];
|
|
3511
|
+
const startingHooks = [];
|
|
3512
|
+
const endingHooks = [];
|
|
3513
|
+
for (const pack of packs) {
|
|
3514
|
+
const task = this.ctx.state.idMap.get(pack[0]);
|
|
3515
|
+
if (task?.type === "suite" && "filepath" in task && task.result?.state) {
|
|
3516
|
+
if (task?.result?.state === "run") {
|
|
3517
|
+
startingTestFiles.push(task);
|
|
3942
3518
|
} else {
|
|
3943
|
-
|
|
3519
|
+
for (const test of getTests(task)) {
|
|
3520
|
+
if (!test.result || test.result?.state === "skip") {
|
|
3521
|
+
finishedTests.push(test);
|
|
3522
|
+
}
|
|
3523
|
+
}
|
|
3524
|
+
finishedTestFiles.push(task.file);
|
|
3525
|
+
}
|
|
3526
|
+
}
|
|
3527
|
+
if (task?.type === "test" || task?.type === "custom") {
|
|
3528
|
+
if (task.result?.state === "run") {
|
|
3529
|
+
startingTests.push(task);
|
|
3530
|
+
} else if (task.result?.hooks?.afterEach !== "run") {
|
|
3531
|
+
finishedTests.push(task);
|
|
3532
|
+
}
|
|
3533
|
+
}
|
|
3534
|
+
if (task?.result?.hooks) {
|
|
3535
|
+
for (const [hook, state] of Object.entries(task.result.hooks)) {
|
|
3536
|
+
if (state === "run") {
|
|
3537
|
+
startingHooks.push({ name: hook, file: task.file, id: task.id, type: task.type });
|
|
3538
|
+
} else {
|
|
3539
|
+
endingHooks.push({ name: hook, file: task.file, id: task.id, type: task.type });
|
|
3540
|
+
}
|
|
3944
3541
|
}
|
|
3945
3542
|
}
|
|
3946
3543
|
}
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3544
|
+
endingHooks.forEach((hook) => this.onHookEnd(hook));
|
|
3545
|
+
finishedTests.forEach((test) => this.onTestFinished(test));
|
|
3546
|
+
finishedTestFiles.forEach((file) => this.onTestFileFinished(file));
|
|
3547
|
+
startingTestFiles.forEach((file) => this.onTestFilePrepare(file));
|
|
3548
|
+
startingTests.forEach((test) => this.onTestStart(test));
|
|
3549
|
+
startingHooks.forEach(
|
|
3550
|
+
(hook) => this.onHookStart(hook)
|
|
3551
|
+
);
|
|
3955
3552
|
}
|
|
3956
|
-
return output.reverse().join("\n");
|
|
3957
3553
|
}
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3554
|
+
|
|
3555
|
+
const DURATION_UPDATE_INTERVAL_MS = 100;
|
|
3556
|
+
const FINISHED_TEST_CLEANUP_TIME_MS = 1e3;
|
|
3557
|
+
class SummaryReporter extends TaskParser {
|
|
3558
|
+
options;
|
|
3559
|
+
renderer;
|
|
3560
|
+
suites = emptyCounters();
|
|
3561
|
+
tests = emptyCounters();
|
|
3562
|
+
maxParallelTests = 0;
|
|
3563
|
+
/** Currently running tests, may include finished tests too */
|
|
3564
|
+
runningTests = /* @__PURE__ */ new Map();
|
|
3565
|
+
/** ID of finished `this.runningTests` that are currently being shown */
|
|
3566
|
+
finishedTests = /* @__PURE__ */ new Map();
|
|
3567
|
+
/** IDs of all finished tests */
|
|
3568
|
+
allFinishedTests = /* @__PURE__ */ new Set();
|
|
3569
|
+
startTime = "";
|
|
3570
|
+
currentTime = 0;
|
|
3571
|
+
duration = 0;
|
|
3572
|
+
durationInterval = void 0;
|
|
3573
|
+
onInit(ctx, options = {}) {
|
|
3574
|
+
this.ctx = ctx;
|
|
3575
|
+
this.options = {
|
|
3576
|
+
verbose: false,
|
|
3577
|
+
...options
|
|
3578
|
+
};
|
|
3579
|
+
this.renderer = new WindowRenderer({
|
|
3580
|
+
logger: ctx.logger,
|
|
3581
|
+
getWindow: () => this.createSummary()
|
|
3582
|
+
});
|
|
3583
|
+
this.startTimers();
|
|
3584
|
+
this.ctx.onClose(() => {
|
|
3585
|
+
clearInterval(this.durationInterval);
|
|
3586
|
+
this.renderer.stop();
|
|
3587
|
+
});
|
|
3588
|
+
}
|
|
3589
|
+
onPathsCollected(paths) {
|
|
3590
|
+
this.suites.total = (paths || []).length;
|
|
3591
|
+
}
|
|
3592
|
+
onWatcherRerun() {
|
|
3593
|
+
this.runningTests.clear();
|
|
3594
|
+
this.finishedTests.clear();
|
|
3595
|
+
this.allFinishedTests.clear();
|
|
3596
|
+
this.suites = emptyCounters();
|
|
3597
|
+
this.tests = emptyCounters();
|
|
3598
|
+
this.startTimers();
|
|
3599
|
+
this.renderer.start();
|
|
3600
|
+
}
|
|
3601
|
+
onFinished() {
|
|
3602
|
+
this.runningTests.clear();
|
|
3603
|
+
this.finishedTests.clear();
|
|
3604
|
+
this.allFinishedTests.clear();
|
|
3605
|
+
this.renderer.finish();
|
|
3606
|
+
clearInterval(this.durationInterval);
|
|
3607
|
+
}
|
|
3608
|
+
onTestFilePrepare(file) {
|
|
3609
|
+
if (this.allFinishedTests.has(file.id) || this.runningTests.has(file.id)) {
|
|
3610
|
+
return;
|
|
3988
3611
|
}
|
|
3612
|
+
const total = getTests(file).length;
|
|
3613
|
+
this.tests.total += total;
|
|
3614
|
+
if (this.finishedTests.size) {
|
|
3615
|
+
const finished = this.finishedTests.keys().next().value;
|
|
3616
|
+
this.removeTestFile(finished);
|
|
3617
|
+
}
|
|
3618
|
+
this.runningTests.set(file.id, {
|
|
3619
|
+
total,
|
|
3620
|
+
completed: 0,
|
|
3621
|
+
filename: file.name,
|
|
3622
|
+
projectName: file.projectName,
|
|
3623
|
+
tests: /* @__PURE__ */ new Map()
|
|
3624
|
+
});
|
|
3625
|
+
this.maxParallelTests = Math.max(this.maxParallelTests, this.runningTests.size);
|
|
3989
3626
|
}
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3627
|
+
onHookStart(options) {
|
|
3628
|
+
const stats = this.getHookStats(options);
|
|
3629
|
+
if (!stats) {
|
|
3630
|
+
return;
|
|
3631
|
+
}
|
|
3632
|
+
const hook = {
|
|
3633
|
+
name: options.name,
|
|
3634
|
+
visible: false,
|
|
3635
|
+
startTime: performance.now(),
|
|
3636
|
+
onFinish: () => {
|
|
3994
3637
|
}
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
3638
|
+
};
|
|
3639
|
+
stats.hook?.onFinish?.();
|
|
3640
|
+
stats.hook = hook;
|
|
3641
|
+
const timeout = setTimeout(() => {
|
|
3642
|
+
hook.visible = true;
|
|
3643
|
+
}, this.ctx.config.slowTestThreshold).unref();
|
|
3644
|
+
hook.onFinish = () => clearTimeout(timeout);
|
|
3645
|
+
}
|
|
3646
|
+
onHookEnd(options) {
|
|
3647
|
+
const stats = this.getHookStats(options);
|
|
3648
|
+
if (stats?.hook?.name !== options.name) {
|
|
3649
|
+
return;
|
|
3650
|
+
}
|
|
3651
|
+
stats.hook.onFinish();
|
|
3652
|
+
stats.hook.visible = false;
|
|
3653
|
+
}
|
|
3654
|
+
onTestStart(test) {
|
|
3655
|
+
if (!this.options.verbose) {
|
|
3656
|
+
return;
|
|
3657
|
+
}
|
|
3658
|
+
const stats = this.getTestStats(test);
|
|
3659
|
+
if (!stats || stats.tests.has(test.id)) {
|
|
3660
|
+
return;
|
|
3661
|
+
}
|
|
3662
|
+
const slowTest = {
|
|
3663
|
+
name: test.name,
|
|
3664
|
+
visible: false,
|
|
3665
|
+
startTime: performance.now(),
|
|
3666
|
+
onFinish: () => {
|
|
4006
3667
|
}
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
3668
|
+
};
|
|
3669
|
+
const timeout = setTimeout(() => {
|
|
3670
|
+
slowTest.visible = true;
|
|
3671
|
+
}, this.ctx.config.slowTestThreshold).unref();
|
|
3672
|
+
slowTest.onFinish = () => {
|
|
3673
|
+
slowTest.hook?.onFinish();
|
|
3674
|
+
clearTimeout(timeout);
|
|
3675
|
+
};
|
|
3676
|
+
stats.tests.set(test.id, slowTest);
|
|
3677
|
+
}
|
|
3678
|
+
onTestFinished(test) {
|
|
3679
|
+
const stats = this.getTestStats(test);
|
|
3680
|
+
if (!stats) {
|
|
3681
|
+
return;
|
|
3682
|
+
}
|
|
3683
|
+
stats.tests.get(test.id)?.onFinish();
|
|
3684
|
+
stats.tests.delete(test.id);
|
|
3685
|
+
stats.completed++;
|
|
3686
|
+
const result = test.result;
|
|
3687
|
+
if (result?.state === "pass") {
|
|
3688
|
+
this.tests.passed++;
|
|
3689
|
+
} else if (result?.state === "fail") {
|
|
3690
|
+
this.tests.failed++;
|
|
3691
|
+
} else if (!result?.state || result?.state === "skip" || result?.state === "todo") {
|
|
3692
|
+
this.tests.skipped++;
|
|
3693
|
+
}
|
|
3694
|
+
}
|
|
3695
|
+
onTestFileFinished(file) {
|
|
3696
|
+
if (this.allFinishedTests.has(file.id)) {
|
|
3697
|
+
return;
|
|
3698
|
+
}
|
|
3699
|
+
this.allFinishedTests.add(file.id);
|
|
3700
|
+
this.suites.completed++;
|
|
3701
|
+
if (file.result?.state === "pass") {
|
|
3702
|
+
this.suites.passed++;
|
|
3703
|
+
} else if (file.result?.state === "fail") {
|
|
3704
|
+
this.suites.failed++;
|
|
3705
|
+
} else if (file.result?.state === "skip") {
|
|
3706
|
+
this.suites.skipped++;
|
|
3707
|
+
} else if (file.result?.state === "todo") {
|
|
3708
|
+
this.suites.todo++;
|
|
3709
|
+
}
|
|
3710
|
+
const left = this.suites.total - this.suites.completed;
|
|
3711
|
+
if (left > this.maxParallelTests) {
|
|
3712
|
+
this.finishedTests.set(file.id, setTimeout(() => {
|
|
3713
|
+
this.removeTestFile(file.id);
|
|
3714
|
+
}, FINISHED_TEST_CLEANUP_TIME_MS).unref());
|
|
3715
|
+
} else {
|
|
3716
|
+
this.removeTestFile(file.id);
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3719
|
+
getTestStats(test) {
|
|
3720
|
+
const file = test.file;
|
|
3721
|
+
let stats = this.runningTests.get(file.id);
|
|
3722
|
+
if (!stats) {
|
|
3723
|
+
this.onTestFilePrepare(test.file);
|
|
3724
|
+
stats = this.runningTests.get(file.id);
|
|
3725
|
+
if (!stats) {
|
|
3726
|
+
return;
|
|
3727
|
+
}
|
|
3728
|
+
}
|
|
3729
|
+
return stats;
|
|
3730
|
+
}
|
|
3731
|
+
getHookStats({ file, id, type }) {
|
|
3732
|
+
if (!this.options.verbose) {
|
|
3733
|
+
return;
|
|
3734
|
+
}
|
|
3735
|
+
const stats = this.runningTests.get(file.id);
|
|
3736
|
+
if (!stats) {
|
|
3737
|
+
return;
|
|
3738
|
+
}
|
|
3739
|
+
return type === "suite" ? stats : stats?.tests.get(id);
|
|
3740
|
+
}
|
|
3741
|
+
createSummary() {
|
|
3742
|
+
const summary = [""];
|
|
3743
|
+
for (const testFile of Array.from(this.runningTests.values()).sort(sortRunningTests)) {
|
|
3744
|
+
summary.push(
|
|
3745
|
+
c.bold(c.yellow(` ${F_POINTER} `)) + formatProjectName(testFile.projectName) + testFile.filename + c.dim(` ${testFile.completed}/${testFile.total}`)
|
|
3746
|
+
);
|
|
3747
|
+
const slowTasks = [
|
|
3748
|
+
testFile.hook,
|
|
3749
|
+
...Array.from(testFile.tests.values())
|
|
3750
|
+
].filter((t) => t != null && t.visible);
|
|
3751
|
+
for (const [index, task] of slowTasks.entries()) {
|
|
3752
|
+
const elapsed = this.currentTime - task.startTime;
|
|
3753
|
+
const icon = index === slowTasks.length - 1 ? F_TREE_NODE_END : F_TREE_NODE_MIDDLE;
|
|
3754
|
+
summary.push(
|
|
3755
|
+
c.bold(c.yellow(` ${icon} `)) + task.name + c.bold(c.yellow(` ${formatTime(Math.max(0, elapsed))}`))
|
|
4011
3756
|
);
|
|
4012
|
-
|
|
4013
|
-
}
|
|
4014
|
-
|
|
3757
|
+
if (task.hook?.visible) {
|
|
3758
|
+
summary.push(c.bold(c.yellow(` ${F_TREE_NODE_END} `)) + task.hook.name);
|
|
3759
|
+
}
|
|
4015
3760
|
}
|
|
4016
|
-
return this;
|
|
4017
|
-
},
|
|
4018
|
-
clear() {
|
|
4019
|
-
log.clear();
|
|
4020
3761
|
}
|
|
4021
|
-
|
|
3762
|
+
if (this.runningTests.size > 0) {
|
|
3763
|
+
summary.push("");
|
|
3764
|
+
}
|
|
3765
|
+
summary.push(padSummaryTitle("Test Files") + getStateString(this.suites));
|
|
3766
|
+
summary.push(padSummaryTitle("Tests") + getStateString(this.tests));
|
|
3767
|
+
summary.push(padSummaryTitle("Start at") + this.startTime);
|
|
3768
|
+
summary.push(padSummaryTitle("Duration") + formatTime(this.duration));
|
|
3769
|
+
summary.push("");
|
|
3770
|
+
return summary;
|
|
3771
|
+
}
|
|
3772
|
+
startTimers() {
|
|
3773
|
+
const start = performance.now();
|
|
3774
|
+
this.startTime = formatTimeString(/* @__PURE__ */ new Date());
|
|
3775
|
+
this.durationInterval = setInterval(() => {
|
|
3776
|
+
this.currentTime = performance.now();
|
|
3777
|
+
this.duration = this.currentTime - start;
|
|
3778
|
+
}, DURATION_UPDATE_INTERVAL_MS).unref();
|
|
3779
|
+
}
|
|
3780
|
+
removeTestFile(id) {
|
|
3781
|
+
if (!id) {
|
|
3782
|
+
return;
|
|
3783
|
+
}
|
|
3784
|
+
const testFile = this.runningTests.get(id);
|
|
3785
|
+
testFile?.hook?.onFinish();
|
|
3786
|
+
testFile?.tests?.forEach((test) => test.onFinish());
|
|
3787
|
+
this.runningTests.delete(id);
|
|
3788
|
+
clearTimeout(this.finishedTests.get(id));
|
|
3789
|
+
this.finishedTests.delete(id);
|
|
3790
|
+
}
|
|
3791
|
+
}
|
|
3792
|
+
function emptyCounters() {
|
|
3793
|
+
return { completed: 0, passed: 0, failed: 0, skipped: 0, todo: 0, total: 0 };
|
|
3794
|
+
}
|
|
3795
|
+
function getStateString(entry) {
|
|
3796
|
+
return [
|
|
3797
|
+
entry.failed ? c.bold(c.red(`${entry.failed} failed`)) : null,
|
|
3798
|
+
c.bold(c.green(`${entry.passed} passed`)),
|
|
3799
|
+
entry.skipped ? c.yellow(`${entry.skipped} skipped`) : null,
|
|
3800
|
+
entry.todo ? c.gray(`${entry.todo} todo`) : null
|
|
3801
|
+
].filter(Boolean).join(c.dim(" | ")) + c.gray(` (${entry.total})`);
|
|
3802
|
+
}
|
|
3803
|
+
function sortRunningTests(a, b) {
|
|
3804
|
+
if ((a.projectName || "") > (b.projectName || "")) {
|
|
3805
|
+
return 1;
|
|
3806
|
+
}
|
|
3807
|
+
if ((a.projectName || "") < (b.projectName || "")) {
|
|
3808
|
+
return -1;
|
|
3809
|
+
}
|
|
3810
|
+
return a.filename.localeCompare(b.filename);
|
|
4022
3811
|
}
|
|
4023
3812
|
|
|
4024
3813
|
class DefaultReporter extends BaseReporter {
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
3814
|
+
options;
|
|
3815
|
+
summary;
|
|
3816
|
+
constructor(options = {}) {
|
|
3817
|
+
super(options);
|
|
3818
|
+
this.options = {
|
|
3819
|
+
summary: true,
|
|
3820
|
+
...options
|
|
3821
|
+
};
|
|
3822
|
+
if (!this.isTTY) {
|
|
3823
|
+
this.options.summary = false;
|
|
3824
|
+
}
|
|
3825
|
+
if (this.options.summary) {
|
|
3826
|
+
this.summary = new SummaryReporter();
|
|
4036
3827
|
}
|
|
4037
3828
|
}
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
this.ctx.
|
|
4041
|
-
c.yellow("Test removed...") + (trigger ? c.dim(` [ ${this.relative(trigger)} ]
|
|
4042
|
-
`) : ""),
|
|
4043
|
-
true
|
|
4044
|
-
);
|
|
4045
|
-
const files = this.ctx.state.getFiles(this.watchFilters);
|
|
4046
|
-
createListRenderer(files, this.rendererOptions).stop();
|
|
4047
|
-
this.ctx.logger.log();
|
|
4048
|
-
super.reportSummary(files, this.ctx.state.getUnhandledErrors());
|
|
4049
|
-
super.onWatcherStart();
|
|
3829
|
+
onInit(ctx) {
|
|
3830
|
+
super.onInit(ctx);
|
|
3831
|
+
this.summary?.onInit(ctx, { verbose: this.verbose });
|
|
4050
3832
|
}
|
|
4051
|
-
|
|
3833
|
+
onPathsCollected(paths = []) {
|
|
4052
3834
|
if (this.isTTY) {
|
|
4053
|
-
this.
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
this.
|
|
4057
|
-
|
|
4058
|
-
if (!this.renderer) {
|
|
4059
|
-
this.renderer = createListRenderer(files, this.rendererOptions).start();
|
|
4060
|
-
} else {
|
|
4061
|
-
this.renderer.update(files);
|
|
3835
|
+
if (this.renderSucceed === void 0) {
|
|
3836
|
+
this.renderSucceed = !!this.renderSucceed;
|
|
3837
|
+
}
|
|
3838
|
+
if (this.renderSucceed !== true) {
|
|
3839
|
+
this.renderSucceed = paths.length <= 1;
|
|
4062
3840
|
}
|
|
4063
3841
|
}
|
|
3842
|
+
this.summary?.onPathsCollected(paths);
|
|
4064
3843
|
}
|
|
4065
|
-
|
|
4066
|
-
this.
|
|
4067
|
-
|
|
4068
|
-
...files
|
|
4069
|
-
]);
|
|
4070
|
-
this.stopListRender();
|
|
4071
|
-
this.ctx.logger.log();
|
|
4072
|
-
super.onFinished(files, errors);
|
|
4073
|
-
}
|
|
4074
|
-
async onWatcherStart(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
|
|
4075
|
-
this.stopListRender();
|
|
4076
|
-
await super.onWatcherStart(files, errors);
|
|
4077
|
-
}
|
|
4078
|
-
stopListRender() {
|
|
4079
|
-
this.renderer?.stop();
|
|
4080
|
-
this.renderer = void 0;
|
|
3844
|
+
onTaskUpdate(packs) {
|
|
3845
|
+
this.summary?.onTaskUpdate(packs);
|
|
3846
|
+
super.onTaskUpdate(packs);
|
|
4081
3847
|
}
|
|
4082
|
-
|
|
4083
|
-
this.
|
|
4084
|
-
|
|
3848
|
+
onWatcherRerun(files, trigger) {
|
|
3849
|
+
this.summary?.onWatcherRerun();
|
|
3850
|
+
super.onWatcherRerun(files, trigger);
|
|
4085
3851
|
}
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
}
|
|
4090
|
-
this.renderer?.clear();
|
|
4091
|
-
super.onUserConsoleLog(log);
|
|
3852
|
+
onFinished(files, errors) {
|
|
3853
|
+
this.summary?.onFinished();
|
|
3854
|
+
super.onFinished(files, errors);
|
|
4092
3855
|
}
|
|
4093
3856
|
}
|
|
4094
3857
|
|
|
@@ -4188,6 +3951,8 @@ function createDotRenderer(_tasks, options) {
|
|
|
4188
3951
|
|
|
4189
3952
|
class DotReporter extends BaseReporter {
|
|
4190
3953
|
renderer;
|
|
3954
|
+
onTaskUpdate() {
|
|
3955
|
+
}
|
|
4191
3956
|
onCollected() {
|
|
4192
3957
|
if (this.isTTY) {
|
|
4193
3958
|
const files = this.ctx.state.getFiles(this.watchFilters);
|
|
@@ -4233,7 +3998,7 @@ class GithubActionsReporter {
|
|
|
4233
3998
|
const projectErrors = new Array();
|
|
4234
3999
|
for (const error of errors) {
|
|
4235
4000
|
projectErrors.push({
|
|
4236
|
-
project: this.ctx.
|
|
4001
|
+
project: this.ctx.getRootTestProject(),
|
|
4237
4002
|
title: "Unhandled error",
|
|
4238
4003
|
error
|
|
4239
4004
|
});
|
|
@@ -4571,10 +4336,22 @@ class JUnitReporter {
|
|
|
4571
4336
|
}
|
|
4572
4337
|
async writeTasks(tasks, filename) {
|
|
4573
4338
|
for (const task of tasks) {
|
|
4339
|
+
let classname = filename;
|
|
4340
|
+
const templateVars = {
|
|
4341
|
+
filename: task.file.name,
|
|
4342
|
+
filepath: task.file.filepath
|
|
4343
|
+
};
|
|
4344
|
+
if (typeof this.options.classnameTemplate === "function") {
|
|
4345
|
+
classname = this.options.classnameTemplate(templateVars);
|
|
4346
|
+
} else if (typeof this.options.classnameTemplate === "string") {
|
|
4347
|
+
classname = this.options.classnameTemplate.replace(/\{filename\}/g, templateVars.filename).replace(/\{filepath\}/g, templateVars.filepath);
|
|
4348
|
+
} else if (typeof this.options.classname === "string") {
|
|
4349
|
+
classname = this.options.classname;
|
|
4350
|
+
}
|
|
4574
4351
|
await this.writeElement(
|
|
4575
4352
|
"testcase",
|
|
4576
4353
|
{
|
|
4577
|
-
classname
|
|
4354
|
+
classname,
|
|
4578
4355
|
file: this.options.addFileAttribute ? filename : void 0,
|
|
4579
4356
|
name: task.name,
|
|
4580
4357
|
time: getDuration(task)
|
|
@@ -4820,13 +4597,10 @@ class TapFlatReporter extends TapReporter {
|
|
|
4820
4597
|
|
|
4821
4598
|
class VerboseReporter extends DefaultReporter {
|
|
4822
4599
|
verbose = true;
|
|
4823
|
-
|
|
4824
|
-
super();
|
|
4825
|
-
this.rendererOptions.renderSucceed = true;
|
|
4826
|
-
}
|
|
4600
|
+
renderSucceed = true;
|
|
4827
4601
|
onTaskUpdate(packs) {
|
|
4828
4602
|
if (this.isTTY) {
|
|
4829
|
-
return;
|
|
4603
|
+
return super.onTaskUpdate(packs);
|
|
4830
4604
|
}
|
|
4831
4605
|
for (const pack of packs) {
|
|
4832
4606
|
const task = this.ctx.state.idMap.get(pack[0]);
|
|
@@ -5250,4 +5024,4 @@ const ReportersMap = {
|
|
|
5250
5024
|
"github-actions": GithubActionsReporter
|
|
5251
5025
|
};
|
|
5252
5026
|
|
|
5253
|
-
export { BasicReporter as B, DefaultReporter as D, GithubActionsReporter as G, HangingProcessReporter as H, JsonReporter as J, Logger as L, ReportersMap as R, TapFlatReporter as T, VerboseReporter as V, DotReporter as a, JUnitReporter as b, TapReporter as c, TestFile as d, TestCase as e, TestModule as f, TestSuite as g, BenchmarkReportsMap as h,
|
|
5027
|
+
export { BasicReporter as B, DefaultReporter as D, GithubActionsReporter as G, HangingProcessReporter as H, JsonReporter as J, Logger as L, ReportersMap as R, TapFlatReporter as T, VerboseReporter as V, DotReporter as a, JUnitReporter as b, TapReporter as c, TestFile as d, TestCase as e, TestModule as f, TestSuite as g, BenchmarkReportsMap as h, generateCodeFrame as i, BlobReporter as j, parse as p, readBlobs as r, stringify as s };
|