vitest 2.2.0-beta.2 → 3.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +75 -0
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +1 -1
- package/dist/chunks/{RandomSequencer.BPedXEug.js → RandomSequencer.gisBJ77r.js} +11 -4
- package/dist/chunks/{base.BS0HhLXd.js → base.CkcgFVQd.js} +8 -3
- package/dist/chunks/{cac.Cs06pOqp.js → cac.CWCZimpS.js} +7 -7
- package/dist/chunks/{cli-api.CB-jIbYQ.js → cli-api.BKUOv0Nc.js} +186 -83
- package/dist/chunks/{config.CPguQ7J1.d.ts → config.BTPBhmK5.d.ts} +1 -1
- package/dist/chunks/{creator.IIqd8RWT.js → creator.DcAcUhMD.js} +1 -4
- package/dist/chunks/{globals.BCGEw6ON.js → globals.DJTzb7B3.js} +2 -2
- package/dist/chunks/{index.DD5eTY2y.js → index.BqHViJW9.js} +1 -1
- package/dist/chunks/{index.BjjsHdBb.js → index.CkOJwybT.js} +1 -1
- package/dist/chunks/{index.bzFpKeaq.js → index.DKe7vK-G.js} +530 -144
- package/dist/chunks/{index.CqYx2Nsr.js → index.DQboAxJm.js} +23 -14
- package/dist/chunks/{inspector.70d6emsh.js → inspector.DKLceBVD.js} +1 -1
- package/dist/chunks/{reporters.F9D2idOT.d.ts → reporters.BZbwTvrM.d.ts} +249 -258
- package/dist/chunks/{resolveConfig.CLnvCvEs.js → resolveConfig.3rGGWga5.js} +81 -49
- package/dist/chunks/{runBaseTests.B7hcVT-s.js → runBaseTests.C6huCAng.js} +6 -6
- package/dist/chunks/{setup-common.BfGt8K-K.js → setup-common.B5ClyS48.js} +1 -1
- package/dist/chunks/{utils.DJONn5B5.js → utils.CMUTX-p8.js} +5 -2
- package/dist/chunks/{vi.BlPttogV.js → vi.CZKezqeD.js} +18 -13
- package/dist/chunks/{vite.DonA4fvH.d.ts → vite.DIfmneq0.d.ts} +1 -1
- package/dist/chunks/{vm.Zr4qWzDJ.js → vm.DGhTouO3.js} +10 -1
- package/dist/chunks/{worker.9VY11NZs.d.ts → worker.CmzGeuVD.d.ts} +3 -3
- package/dist/chunks/{worker.Qz1UB4Fv.d.ts → worker.umPNbBNk.d.ts} +1 -1
- package/dist/cli.js +1 -1
- package/dist/config.cjs +1 -10
- package/dist/config.d.ts +4 -5
- package/dist/config.js +1 -10
- package/dist/coverage.d.ts +2 -2
- package/dist/coverage.js +4 -4
- package/dist/execute.d.ts +3 -3
- package/dist/index.d.ts +21 -13
- package/dist/index.js +2 -2
- package/dist/node.d.ts +9 -22
- package/dist/node.js +9 -9
- package/dist/reporters.d.ts +2 -2
- package/dist/reporters.js +5 -4
- package/dist/runners.d.ts +1 -2
- package/dist/runners.js +9 -14
- package/dist/worker.js +1 -1
- package/dist/workers/forks.js +1 -1
- package/dist/workers/runVmTests.js +6 -6
- 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 +3 -3
- package/dist/workers.js +3 -3
- package/package.json +21 -22
|
@@ -3,19 +3,20 @@ 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, 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.
|
|
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.CMUTX-p8.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 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.gisBJ77r.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';
|
|
15
14
|
import { Writable } from 'node:stream';
|
|
16
15
|
import { Console } from 'node:console';
|
|
17
16
|
import process$1 from 'node:process';
|
|
18
|
-
import { g as getDefaultExportFromCjs } from './_commonjsHelpers.BFTU3MAI.js';
|
|
17
|
+
import { g as getDefaultExportFromCjs, c as commonjsGlobal } from './_commonjsHelpers.BFTU3MAI.js';
|
|
18
|
+
import require$$0 from 'assert';
|
|
19
|
+
import require$$0$1 from 'events';
|
|
19
20
|
import { createRequire } from 'node:module';
|
|
20
21
|
import { hostname } from 'node:os';
|
|
21
22
|
|
|
@@ -626,6 +627,370 @@ ansiEscapes.iTerm = {
|
|
|
626
627
|
}
|
|
627
628
|
};
|
|
628
629
|
|
|
630
|
+
var onetime$1 = {exports: {}};
|
|
631
|
+
|
|
632
|
+
var mimicFn = {exports: {}};
|
|
633
|
+
|
|
634
|
+
var hasRequiredMimicFn;
|
|
635
|
+
|
|
636
|
+
function requireMimicFn () {
|
|
637
|
+
if (hasRequiredMimicFn) return mimicFn.exports;
|
|
638
|
+
hasRequiredMimicFn = 1;
|
|
639
|
+
|
|
640
|
+
const mimicFn$1 = (to, from) => {
|
|
641
|
+
for (const prop of Reflect.ownKeys(from)) {
|
|
642
|
+
Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop));
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
return to;
|
|
646
|
+
};
|
|
647
|
+
|
|
648
|
+
mimicFn.exports = mimicFn$1;
|
|
649
|
+
// TODO: Remove this for the next major release
|
|
650
|
+
mimicFn.exports.default = mimicFn$1;
|
|
651
|
+
return mimicFn.exports;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
var hasRequiredOnetime;
|
|
655
|
+
|
|
656
|
+
function requireOnetime () {
|
|
657
|
+
if (hasRequiredOnetime) return onetime$1.exports;
|
|
658
|
+
hasRequiredOnetime = 1;
|
|
659
|
+
const mimicFn = requireMimicFn();
|
|
660
|
+
|
|
661
|
+
const calledFunctions = new WeakMap();
|
|
662
|
+
|
|
663
|
+
const onetime = (function_, options = {}) => {
|
|
664
|
+
if (typeof function_ !== 'function') {
|
|
665
|
+
throw new TypeError('Expected a function');
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
let returnValue;
|
|
669
|
+
let callCount = 0;
|
|
670
|
+
const functionName = function_.displayName || function_.name || '<anonymous>';
|
|
671
|
+
|
|
672
|
+
const onetime = function (...arguments_) {
|
|
673
|
+
calledFunctions.set(onetime, ++callCount);
|
|
674
|
+
|
|
675
|
+
if (callCount === 1) {
|
|
676
|
+
returnValue = function_.apply(this, arguments_);
|
|
677
|
+
function_ = null;
|
|
678
|
+
} else if (options.throw === true) {
|
|
679
|
+
throw new Error(`Function \`${functionName}\` can only be called once`);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
return returnValue;
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
mimicFn(onetime, function_);
|
|
686
|
+
calledFunctions.set(onetime, callCount);
|
|
687
|
+
|
|
688
|
+
return onetime;
|
|
689
|
+
};
|
|
690
|
+
|
|
691
|
+
onetime$1.exports = onetime;
|
|
692
|
+
// TODO: Remove this for the next major release
|
|
693
|
+
onetime$1.exports.default = onetime;
|
|
694
|
+
|
|
695
|
+
onetime$1.exports.callCount = function_ => {
|
|
696
|
+
if (!calledFunctions.has(function_)) {
|
|
697
|
+
throw new Error(`The given function \`${function_.name}\` is not wrapped by the \`onetime\` package`);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
return calledFunctions.get(function_);
|
|
701
|
+
};
|
|
702
|
+
return onetime$1.exports;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
var onetimeExports = requireOnetime();
|
|
706
|
+
var onetime = /*@__PURE__*/getDefaultExportFromCjs(onetimeExports);
|
|
707
|
+
|
|
708
|
+
var signalExit$1 = {exports: {}};
|
|
709
|
+
|
|
710
|
+
var signals = {exports: {}};
|
|
711
|
+
|
|
712
|
+
var hasRequiredSignals;
|
|
713
|
+
|
|
714
|
+
function requireSignals () {
|
|
715
|
+
if (hasRequiredSignals) return signals.exports;
|
|
716
|
+
hasRequiredSignals = 1;
|
|
717
|
+
(function (module) {
|
|
718
|
+
// This is not the set of all possible signals.
|
|
719
|
+
//
|
|
720
|
+
// It IS, however, the set of all signals that trigger
|
|
721
|
+
// an exit on either Linux or BSD systems. Linux is a
|
|
722
|
+
// superset of the signal names supported on BSD, and
|
|
723
|
+
// the unknown signals just fail to register, so we can
|
|
724
|
+
// catch that easily enough.
|
|
725
|
+
//
|
|
726
|
+
// Don't bother with SIGKILL. It's uncatchable, which
|
|
727
|
+
// means that we can't fire any callbacks anyway.
|
|
728
|
+
//
|
|
729
|
+
// If a user does happen to register a handler on a non-
|
|
730
|
+
// fatal signal like SIGWINCH or something, and then
|
|
731
|
+
// exit, it'll end up firing `process.emit('exit')`, so
|
|
732
|
+
// the handler will be fired anyway.
|
|
733
|
+
//
|
|
734
|
+
// SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised
|
|
735
|
+
// artificially, inherently leave the process in a
|
|
736
|
+
// state from which it is not safe to try and enter JS
|
|
737
|
+
// listeners.
|
|
738
|
+
module.exports = [
|
|
739
|
+
'SIGABRT',
|
|
740
|
+
'SIGALRM',
|
|
741
|
+
'SIGHUP',
|
|
742
|
+
'SIGINT',
|
|
743
|
+
'SIGTERM'
|
|
744
|
+
];
|
|
745
|
+
|
|
746
|
+
if (process.platform !== 'win32') {
|
|
747
|
+
module.exports.push(
|
|
748
|
+
'SIGVTALRM',
|
|
749
|
+
'SIGXCPU',
|
|
750
|
+
'SIGXFSZ',
|
|
751
|
+
'SIGUSR2',
|
|
752
|
+
'SIGTRAP',
|
|
753
|
+
'SIGSYS',
|
|
754
|
+
'SIGQUIT',
|
|
755
|
+
'SIGIOT'
|
|
756
|
+
// should detect profiler and enable/disable accordingly.
|
|
757
|
+
// see #21
|
|
758
|
+
// 'SIGPROF'
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
if (process.platform === 'linux') {
|
|
763
|
+
module.exports.push(
|
|
764
|
+
'SIGIO',
|
|
765
|
+
'SIGPOLL',
|
|
766
|
+
'SIGPWR',
|
|
767
|
+
'SIGSTKFLT',
|
|
768
|
+
'SIGUNUSED'
|
|
769
|
+
);
|
|
770
|
+
}
|
|
771
|
+
} (signals));
|
|
772
|
+
return signals.exports;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
var hasRequiredSignalExit;
|
|
776
|
+
|
|
777
|
+
function requireSignalExit () {
|
|
778
|
+
if (hasRequiredSignalExit) return signalExit$1.exports;
|
|
779
|
+
hasRequiredSignalExit = 1;
|
|
780
|
+
// Note: since nyc uses this module to output coverage, any lines
|
|
781
|
+
// that are in the direct sync flow of nyc's outputCoverage are
|
|
782
|
+
// ignored, since we can never get coverage for them.
|
|
783
|
+
// grab a reference to node's real process object right away
|
|
784
|
+
var process = commonjsGlobal.process;
|
|
785
|
+
|
|
786
|
+
const processOk = function (process) {
|
|
787
|
+
return process &&
|
|
788
|
+
typeof process === 'object' &&
|
|
789
|
+
typeof process.removeListener === 'function' &&
|
|
790
|
+
typeof process.emit === 'function' &&
|
|
791
|
+
typeof process.reallyExit === 'function' &&
|
|
792
|
+
typeof process.listeners === 'function' &&
|
|
793
|
+
typeof process.kill === 'function' &&
|
|
794
|
+
typeof process.pid === 'number' &&
|
|
795
|
+
typeof process.on === 'function'
|
|
796
|
+
};
|
|
797
|
+
|
|
798
|
+
// some kind of non-node environment, just no-op
|
|
799
|
+
/* istanbul ignore if */
|
|
800
|
+
if (!processOk(process)) {
|
|
801
|
+
signalExit$1.exports = function () {
|
|
802
|
+
return function () {}
|
|
803
|
+
};
|
|
804
|
+
} else {
|
|
805
|
+
var assert = require$$0;
|
|
806
|
+
var signals = requireSignals();
|
|
807
|
+
var isWin = /^win/i.test(process.platform);
|
|
808
|
+
|
|
809
|
+
var EE = require$$0$1;
|
|
810
|
+
/* istanbul ignore if */
|
|
811
|
+
if (typeof EE !== 'function') {
|
|
812
|
+
EE = EE.EventEmitter;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
var emitter;
|
|
816
|
+
if (process.__signal_exit_emitter__) {
|
|
817
|
+
emitter = process.__signal_exit_emitter__;
|
|
818
|
+
} else {
|
|
819
|
+
emitter = process.__signal_exit_emitter__ = new EE();
|
|
820
|
+
emitter.count = 0;
|
|
821
|
+
emitter.emitted = {};
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// Because this emitter is a global, we have to check to see if a
|
|
825
|
+
// previous version of this library failed to enable infinite listeners.
|
|
826
|
+
// I know what you're about to say. But literally everything about
|
|
827
|
+
// signal-exit is a compromise with evil. Get used to it.
|
|
828
|
+
if (!emitter.infinite) {
|
|
829
|
+
emitter.setMaxListeners(Infinity);
|
|
830
|
+
emitter.infinite = true;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
signalExit$1.exports = function (cb, opts) {
|
|
834
|
+
/* istanbul ignore if */
|
|
835
|
+
if (!processOk(commonjsGlobal.process)) {
|
|
836
|
+
return function () {}
|
|
837
|
+
}
|
|
838
|
+
assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler');
|
|
839
|
+
|
|
840
|
+
if (loaded === false) {
|
|
841
|
+
load();
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
var ev = 'exit';
|
|
845
|
+
if (opts && opts.alwaysLast) {
|
|
846
|
+
ev = 'afterexit';
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
var remove = function () {
|
|
850
|
+
emitter.removeListener(ev, cb);
|
|
851
|
+
if (emitter.listeners('exit').length === 0 &&
|
|
852
|
+
emitter.listeners('afterexit').length === 0) {
|
|
853
|
+
unload();
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
emitter.on(ev, cb);
|
|
857
|
+
|
|
858
|
+
return remove
|
|
859
|
+
};
|
|
860
|
+
|
|
861
|
+
var unload = function unload () {
|
|
862
|
+
if (!loaded || !processOk(commonjsGlobal.process)) {
|
|
863
|
+
return
|
|
864
|
+
}
|
|
865
|
+
loaded = false;
|
|
866
|
+
|
|
867
|
+
signals.forEach(function (sig) {
|
|
868
|
+
try {
|
|
869
|
+
process.removeListener(sig, sigListeners[sig]);
|
|
870
|
+
} catch (er) {}
|
|
871
|
+
});
|
|
872
|
+
process.emit = originalProcessEmit;
|
|
873
|
+
process.reallyExit = originalProcessReallyExit;
|
|
874
|
+
emitter.count -= 1;
|
|
875
|
+
};
|
|
876
|
+
signalExit$1.exports.unload = unload;
|
|
877
|
+
|
|
878
|
+
var emit = function emit (event, code, signal) {
|
|
879
|
+
/* istanbul ignore if */
|
|
880
|
+
if (emitter.emitted[event]) {
|
|
881
|
+
return
|
|
882
|
+
}
|
|
883
|
+
emitter.emitted[event] = true;
|
|
884
|
+
emitter.emit(event, code, signal);
|
|
885
|
+
};
|
|
886
|
+
|
|
887
|
+
// { <signal>: <listener fn>, ... }
|
|
888
|
+
var sigListeners = {};
|
|
889
|
+
signals.forEach(function (sig) {
|
|
890
|
+
sigListeners[sig] = function listener () {
|
|
891
|
+
/* istanbul ignore if */
|
|
892
|
+
if (!processOk(commonjsGlobal.process)) {
|
|
893
|
+
return
|
|
894
|
+
}
|
|
895
|
+
// If there are no other listeners, an exit is coming!
|
|
896
|
+
// Simplest way: remove us and then re-send the signal.
|
|
897
|
+
// We know that this will kill the process, so we can
|
|
898
|
+
// safely emit now.
|
|
899
|
+
var listeners = process.listeners(sig);
|
|
900
|
+
if (listeners.length === emitter.count) {
|
|
901
|
+
unload();
|
|
902
|
+
emit('exit', null, sig);
|
|
903
|
+
/* istanbul ignore next */
|
|
904
|
+
emit('afterexit', null, sig);
|
|
905
|
+
/* istanbul ignore next */
|
|
906
|
+
if (isWin && sig === 'SIGHUP') {
|
|
907
|
+
// "SIGHUP" throws an `ENOSYS` error on Windows,
|
|
908
|
+
// so use a supported signal instead
|
|
909
|
+
sig = 'SIGINT';
|
|
910
|
+
}
|
|
911
|
+
/* istanbul ignore next */
|
|
912
|
+
process.kill(process.pid, sig);
|
|
913
|
+
}
|
|
914
|
+
};
|
|
915
|
+
});
|
|
916
|
+
|
|
917
|
+
signalExit$1.exports.signals = function () {
|
|
918
|
+
return signals
|
|
919
|
+
};
|
|
920
|
+
|
|
921
|
+
var loaded = false;
|
|
922
|
+
|
|
923
|
+
var load = function load () {
|
|
924
|
+
if (loaded || !processOk(commonjsGlobal.process)) {
|
|
925
|
+
return
|
|
926
|
+
}
|
|
927
|
+
loaded = true;
|
|
928
|
+
|
|
929
|
+
// This is the number of onSignalExit's that are in play.
|
|
930
|
+
// It's important so that we can count the correct number of
|
|
931
|
+
// listeners on signals, and don't wait for the other one to
|
|
932
|
+
// handle it instead of us.
|
|
933
|
+
emitter.count += 1;
|
|
934
|
+
|
|
935
|
+
signals = signals.filter(function (sig) {
|
|
936
|
+
try {
|
|
937
|
+
process.on(sig, sigListeners[sig]);
|
|
938
|
+
return true
|
|
939
|
+
} catch (er) {
|
|
940
|
+
return false
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
process.emit = processEmit;
|
|
945
|
+
process.reallyExit = processReallyExit;
|
|
946
|
+
};
|
|
947
|
+
signalExit$1.exports.load = load;
|
|
948
|
+
|
|
949
|
+
var originalProcessReallyExit = process.reallyExit;
|
|
950
|
+
var processReallyExit = function processReallyExit (code) {
|
|
951
|
+
/* istanbul ignore if */
|
|
952
|
+
if (!processOk(commonjsGlobal.process)) {
|
|
953
|
+
return
|
|
954
|
+
}
|
|
955
|
+
process.exitCode = code || /* istanbul ignore next */ 0;
|
|
956
|
+
emit('exit', process.exitCode, null);
|
|
957
|
+
/* istanbul ignore next */
|
|
958
|
+
emit('afterexit', process.exitCode, null);
|
|
959
|
+
/* istanbul ignore next */
|
|
960
|
+
originalProcessReallyExit.call(process, process.exitCode);
|
|
961
|
+
};
|
|
962
|
+
|
|
963
|
+
var originalProcessEmit = process.emit;
|
|
964
|
+
var processEmit = function processEmit (ev, arg) {
|
|
965
|
+
if (ev === 'exit' && processOk(commonjsGlobal.process)) {
|
|
966
|
+
/* istanbul ignore else */
|
|
967
|
+
if (arg !== undefined) {
|
|
968
|
+
process.exitCode = arg;
|
|
969
|
+
}
|
|
970
|
+
var ret = originalProcessEmit.apply(this, arguments);
|
|
971
|
+
/* istanbul ignore next */
|
|
972
|
+
emit('exit', process.exitCode, null);
|
|
973
|
+
/* istanbul ignore next */
|
|
974
|
+
emit('afterexit', process.exitCode, null);
|
|
975
|
+
/* istanbul ignore next */
|
|
976
|
+
return ret
|
|
977
|
+
} else {
|
|
978
|
+
return originalProcessEmit.apply(this, arguments)
|
|
979
|
+
}
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
return signalExit$1.exports;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
var signalExitExports = requireSignalExit();
|
|
986
|
+
var signalExit = /*@__PURE__*/getDefaultExportFromCjs(signalExitExports);
|
|
987
|
+
|
|
988
|
+
const restoreCursor = onetime(() => {
|
|
989
|
+
signalExit(() => {
|
|
990
|
+
process$1.stderr.write('\u001B[?25h');
|
|
991
|
+
}, {alwaysLast: true});
|
|
992
|
+
});
|
|
993
|
+
|
|
629
994
|
let isHidden = false;
|
|
630
995
|
|
|
631
996
|
const cliCursor = {};
|
|
@@ -2804,15 +3169,15 @@ Vitest caught ${errors.length} unhandled error${errors.length > 1 ? "s" : ""} du
|
|
|
2804
3169
|
This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.`
|
|
2805
3170
|
)
|
|
2806
3171
|
);
|
|
2807
|
-
this.
|
|
2808
|
-
this.
|
|
3172
|
+
this.error(c.red(divider(c.bold(c.inverse(" Unhandled Errors ")))));
|
|
3173
|
+
this.error(errorMessage);
|
|
2809
3174
|
errors.forEach((err) => {
|
|
2810
3175
|
this.printError(err, {
|
|
2811
3176
|
fullStack: true,
|
|
2812
3177
|
type: err.type || "Unhandled Error"
|
|
2813
3178
|
});
|
|
2814
3179
|
});
|
|
2815
|
-
this.
|
|
3180
|
+
this.error(c.red(divider()));
|
|
2816
3181
|
}
|
|
2817
3182
|
printSourceTypeErrors(errors) {
|
|
2818
3183
|
const errorMessage = c.red(
|
|
@@ -2866,7 +3231,7 @@ class BlobReporter {
|
|
|
2866
3231
|
const modules = this.ctx.projects.map(
|
|
2867
3232
|
(project) => {
|
|
2868
3233
|
return [
|
|
2869
|
-
project.
|
|
3234
|
+
project.name,
|
|
2870
3235
|
[...project.vite.moduleGraph.idToModuleMap.entries()].map((mod) => {
|
|
2871
3236
|
if (!mod[1].file) {
|
|
2872
3237
|
return null;
|
|
@@ -2934,7 +3299,7 @@ ${blobs.map((b) => `- "${b.file}" uses v${b.version}`).join("\n")}`
|
|
|
2934
3299
|
);
|
|
2935
3300
|
}
|
|
2936
3301
|
const projects = Object.fromEntries(
|
|
2937
|
-
projectsArray.map((p) => [p.
|
|
3302
|
+
projectsArray.map((p) => [p.name, p])
|
|
2938
3303
|
);
|
|
2939
3304
|
blobs.forEach((blob) => {
|
|
2940
3305
|
blob.moduleKeys.forEach(([projectName, moduleIds]) => {
|
|
@@ -3041,21 +3406,27 @@ class BaseReporter {
|
|
|
3041
3406
|
this.log(` ${title} ${task.name} ${suffix}`);
|
|
3042
3407
|
const anyFailed = tests.some((test) => test.result?.state === "fail");
|
|
3043
3408
|
for (const test of tests) {
|
|
3044
|
-
const duration = test.result
|
|
3409
|
+
const { duration, retryCount, repeatCount } = test.result || {};
|
|
3410
|
+
let suffix2 = "";
|
|
3411
|
+
if (retryCount != null && retryCount > 0) {
|
|
3412
|
+
suffix2 += c.yellow(` (retry x${retryCount})`);
|
|
3413
|
+
}
|
|
3414
|
+
if (repeatCount != null && repeatCount > 0) {
|
|
3415
|
+
suffix2 += c.yellow(` (repeat x${repeatCount})`);
|
|
3416
|
+
}
|
|
3045
3417
|
if (test.result?.state === "fail") {
|
|
3046
|
-
|
|
3047
|
-
this.log(c.red(` ${taskFail} ${getTestName(test, c.dim(" > "))}${suffix2}`));
|
|
3418
|
+
this.log(c.red(` ${taskFail} ${getTestName(test, c.dim(" > "))}${this.getDurationPrefix(test)}`) + suffix2);
|
|
3048
3419
|
test.result?.errors?.forEach((e) => {
|
|
3049
3420
|
this.log(c.red(` ${F_RIGHT} ${e?.message}`));
|
|
3050
3421
|
});
|
|
3051
3422
|
} else if (duration && duration > this.ctx.config.slowTestThreshold) {
|
|
3052
3423
|
this.log(
|
|
3053
|
-
` ${c.yellow(c.dim(F_CHECK))} ${getTestName(test, c.dim(" > "))} ${c.yellow(Math.round(duration) + c.dim("ms"))}`
|
|
3424
|
+
` ${c.yellow(c.dim(F_CHECK))} ${getTestName(test, c.dim(" > "))} ${c.yellow(Math.round(duration) + c.dim("ms"))}${suffix2}`
|
|
3054
3425
|
);
|
|
3055
|
-
} else if (test.result?.state === "skip" && test.result.note) {
|
|
3426
|
+
} else if (this.ctx.config.hideSkippedTests && (test.mode === "skip" || test.result?.state === "skip")) ; else if (test.result?.state === "skip" && test.result.note) {
|
|
3056
3427
|
this.log(` ${getStateSymbol(test)} ${getTestName(test)}${c.dim(c.gray(` [${test.result.note}]`))}`);
|
|
3057
3428
|
} else if (this.renderSucceed || anyFailed) {
|
|
3058
|
-
this.log(` ${c.
|
|
3429
|
+
this.log(` ${c.dim(getStateSymbol(test))} ${getTestName(test, c.dim(" > "))}${suffix2}`);
|
|
3059
3430
|
}
|
|
3060
3431
|
}
|
|
3061
3432
|
}
|
|
@@ -3245,12 +3616,14 @@ class BaseReporter {
|
|
|
3245
3616
|
const errorDivider = () => this.error(`${c.red(c.dim(divider(`[${current++}/${failedTotal}]`, void 0, 1)))}
|
|
3246
3617
|
`);
|
|
3247
3618
|
if (failedSuites.length) {
|
|
3248
|
-
this.error(
|
|
3619
|
+
this.error(`
|
|
3620
|
+
${errorBanner(`Failed Suites ${failedSuites.length}`)}
|
|
3249
3621
|
`);
|
|
3250
3622
|
this.printTaskErrors(failedSuites, errorDivider);
|
|
3251
3623
|
}
|
|
3252
3624
|
if (failedTests.length) {
|
|
3253
|
-
this.error(
|
|
3625
|
+
this.error(`
|
|
3626
|
+
${errorBanner(`Failed Tests ${failedTests.length}`)}
|
|
3254
3627
|
`);
|
|
3255
3628
|
this.printTaskErrors(failedTests, errorDivider);
|
|
3256
3629
|
}
|
|
@@ -3309,7 +3682,7 @@ class BaseReporter {
|
|
|
3309
3682
|
name += c.dim(` [ ${this.relative(filepath)} ]`);
|
|
3310
3683
|
}
|
|
3311
3684
|
this.ctx.logger.error(
|
|
3312
|
-
`${c.red(c.bold(c.inverse(" FAIL ")))}${formatProjectName(projectName)}
|
|
3685
|
+
`${c.red(c.bold(c.inverse(" FAIL ")))} ${formatProjectName(projectName)}${name}`
|
|
3313
3686
|
);
|
|
3314
3687
|
}
|
|
3315
3688
|
const screenshotPaths = tasks2.map((t) => t.meta?.failScreenshotPath).filter((screenshot) => screenshot != null);
|
|
@@ -3378,9 +3751,9 @@ class WindowRenderer {
|
|
|
3378
3751
|
};
|
|
3379
3752
|
this.cleanups.push(
|
|
3380
3753
|
this.interceptStream(process.stdout, "output"),
|
|
3381
|
-
this.interceptStream(process.stderr, "error")
|
|
3754
|
+
this.interceptStream(process.stderr, "error"),
|
|
3755
|
+
this.addProcessExitListeners()
|
|
3382
3756
|
);
|
|
3383
|
-
restoreCursor();
|
|
3384
3757
|
this.write(HIDE_CURSOR, "output");
|
|
3385
3758
|
this.start();
|
|
3386
3759
|
}
|
|
@@ -3402,6 +3775,9 @@ class WindowRenderer {
|
|
|
3402
3775
|
this.flushBuffer();
|
|
3403
3776
|
clearInterval(this.renderInterval);
|
|
3404
3777
|
}
|
|
3778
|
+
getColumns() {
|
|
3779
|
+
return "columns" in this.options.logger.outputStream ? this.options.logger.outputStream.columns : 80;
|
|
3780
|
+
}
|
|
3405
3781
|
flushBuffer() {
|
|
3406
3782
|
if (this.buffer.length === 0) {
|
|
3407
3783
|
return this.render();
|
|
@@ -3429,10 +3805,10 @@ class WindowRenderer {
|
|
|
3429
3805
|
return this.write(message || "", type);
|
|
3430
3806
|
}
|
|
3431
3807
|
const windowContent = this.options.getWindow();
|
|
3432
|
-
const rowCount = getRenderedRowCount(windowContent, this.
|
|
3808
|
+
const rowCount = getRenderedRowCount(windowContent, this.getColumns());
|
|
3433
3809
|
let padding = this.windowHeight - rowCount;
|
|
3434
3810
|
if (padding > 0 && message) {
|
|
3435
|
-
padding -= getRenderedRowCount([message], this.
|
|
3811
|
+
padding -= getRenderedRowCount([message], this.getColumns());
|
|
3436
3812
|
}
|
|
3437
3813
|
this.write(SYNC_START);
|
|
3438
3814
|
this.clearWindow();
|
|
@@ -3475,10 +3851,27 @@ class WindowRenderer {
|
|
|
3475
3851
|
write(message, type = "output") {
|
|
3476
3852
|
this.streams[type](message);
|
|
3477
3853
|
}
|
|
3854
|
+
addProcessExitListeners() {
|
|
3855
|
+
const onExit = (signal, exitCode) => {
|
|
3856
|
+
this.flushBuffer();
|
|
3857
|
+
this.stop();
|
|
3858
|
+
if (process.exitCode === void 0) {
|
|
3859
|
+
process.exitCode = exitCode !== void 0 ? 128 + exitCode : Number(signal);
|
|
3860
|
+
}
|
|
3861
|
+
process.exit();
|
|
3862
|
+
};
|
|
3863
|
+
process.once("SIGINT", onExit);
|
|
3864
|
+
process.once("SIGTERM", onExit);
|
|
3865
|
+
process.once("exit", onExit);
|
|
3866
|
+
return function cleanup() {
|
|
3867
|
+
process.off("SIGINT", onExit);
|
|
3868
|
+
process.off("SIGTERM", onExit);
|
|
3869
|
+
process.off("exit", onExit);
|
|
3870
|
+
};
|
|
3871
|
+
}
|
|
3478
3872
|
}
|
|
3479
|
-
function getRenderedRowCount(rows,
|
|
3873
|
+
function getRenderedRowCount(rows, columns) {
|
|
3480
3874
|
let count = 0;
|
|
3481
|
-
const columns = "columns" in stream ? stream.columns : 80;
|
|
3482
3875
|
for (const row of rows) {
|
|
3483
3876
|
const text = stripVTControlCharacters(row);
|
|
3484
3877
|
count += Math.max(1, Math.ceil(text.length / columns));
|
|
@@ -3524,7 +3917,7 @@ class TaskParser {
|
|
|
3524
3917
|
finishedTestFiles.push(task.file);
|
|
3525
3918
|
}
|
|
3526
3919
|
}
|
|
3527
|
-
if (task?.type === "test"
|
|
3920
|
+
if (task?.type === "test") {
|
|
3528
3921
|
if (task.result?.state === "run") {
|
|
3529
3922
|
startingTests.push(task);
|
|
3530
3923
|
} else if (task.result?.hooks?.afterEach !== "run") {
|
|
@@ -3855,139 +4248,131 @@ class DefaultReporter extends BaseReporter {
|
|
|
3855
4248
|
}
|
|
3856
4249
|
}
|
|
3857
4250
|
|
|
3858
|
-
|
|
3859
|
-
|
|
4251
|
+
class DotReporter extends BaseReporter {
|
|
4252
|
+
summary;
|
|
4253
|
+
onInit(ctx) {
|
|
4254
|
+
super.onInit(ctx);
|
|
4255
|
+
if (this.isTTY) {
|
|
4256
|
+
this.summary = new DotSummary();
|
|
4257
|
+
this.summary.onInit(ctx);
|
|
4258
|
+
}
|
|
4259
|
+
}
|
|
4260
|
+
onTaskUpdate(packs) {
|
|
4261
|
+
this.summary?.onTaskUpdate(packs);
|
|
4262
|
+
if (!this.isTTY) {
|
|
4263
|
+
super.onTaskUpdate(packs);
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
onWatcherRerun(files, trigger) {
|
|
4267
|
+
this.summary?.onWatcherRerun();
|
|
4268
|
+
super.onWatcherRerun(files, trigger);
|
|
4269
|
+
}
|
|
4270
|
+
onFinished(files, errors) {
|
|
4271
|
+
this.summary?.onFinished();
|
|
4272
|
+
super.onFinished(files, errors);
|
|
4273
|
+
}
|
|
4274
|
+
}
|
|
4275
|
+
class DotSummary extends TaskParser {
|
|
4276
|
+
renderer;
|
|
4277
|
+
tests = /* @__PURE__ */ new Map();
|
|
4278
|
+
finishedTests = /* @__PURE__ */ new Set();
|
|
4279
|
+
onInit(ctx) {
|
|
4280
|
+
this.ctx = ctx;
|
|
4281
|
+
this.renderer = new WindowRenderer({
|
|
4282
|
+
logger: ctx.logger,
|
|
4283
|
+
getWindow: () => this.createSummary()
|
|
4284
|
+
});
|
|
4285
|
+
this.ctx.onClose(() => this.renderer.stop());
|
|
4286
|
+
}
|
|
4287
|
+
onWatcherRerun() {
|
|
4288
|
+
this.tests.clear();
|
|
4289
|
+
this.renderer.start();
|
|
4290
|
+
}
|
|
4291
|
+
onFinished() {
|
|
4292
|
+
const finalLog = formatTests(Array.from(this.tests.values()));
|
|
4293
|
+
this.ctx.logger.log(finalLog);
|
|
4294
|
+
this.tests.clear();
|
|
4295
|
+
this.renderer.finish();
|
|
4296
|
+
}
|
|
4297
|
+
onTestFilePrepare(file) {
|
|
4298
|
+
for (const test of getTests(file)) {
|
|
4299
|
+
this.onTestStart(test);
|
|
4300
|
+
}
|
|
4301
|
+
}
|
|
4302
|
+
onTestStart(test) {
|
|
4303
|
+
if (this.finishedTests.has(test.id)) {
|
|
4304
|
+
return;
|
|
4305
|
+
}
|
|
4306
|
+
this.tests.set(test.id, test.mode || "run");
|
|
4307
|
+
}
|
|
4308
|
+
onTestFinished(test) {
|
|
4309
|
+
if (this.finishedTests.has(test.id)) {
|
|
4310
|
+
return;
|
|
4311
|
+
}
|
|
4312
|
+
this.finishedTests.add(test.id);
|
|
4313
|
+
this.tests.set(test.id, test.result?.state || "skip");
|
|
4314
|
+
}
|
|
4315
|
+
onTestFileFinished() {
|
|
4316
|
+
const columns = this.renderer.getColumns();
|
|
4317
|
+
if (this.tests.size < columns) {
|
|
4318
|
+
return;
|
|
4319
|
+
}
|
|
4320
|
+
const finishedTests = Array.from(this.tests).filter((entry) => entry[1] !== "run");
|
|
4321
|
+
if (finishedTests.length < columns) {
|
|
4322
|
+
return;
|
|
4323
|
+
}
|
|
4324
|
+
const states = [];
|
|
4325
|
+
let count = 0;
|
|
4326
|
+
for (const [id, state] of finishedTests) {
|
|
4327
|
+
if (count++ >= columns) {
|
|
4328
|
+
break;
|
|
4329
|
+
}
|
|
4330
|
+
this.tests.delete(id);
|
|
4331
|
+
states.push(state);
|
|
4332
|
+
}
|
|
4333
|
+
this.ctx.logger.log(formatTests(states));
|
|
4334
|
+
}
|
|
4335
|
+
createSummary() {
|
|
4336
|
+
return [
|
|
4337
|
+
formatTests(Array.from(this.tests.values())),
|
|
4338
|
+
""
|
|
4339
|
+
];
|
|
4340
|
+
}
|
|
4341
|
+
}
|
|
4342
|
+
const pass = { char: "\xB7", color: c.green };
|
|
4343
|
+
const fail = { char: "x", color: c.red };
|
|
3860
4344
|
const pending = { char: "*", color: c.yellow };
|
|
3861
4345
|
const skip = { char: "-", color: (char) => c.dim(c.gray(char)) };
|
|
3862
|
-
function getIcon(
|
|
3863
|
-
|
|
3864
|
-
return skip;
|
|
3865
|
-
}
|
|
3866
|
-
switch (task.result?.state) {
|
|
4346
|
+
function getIcon(state) {
|
|
4347
|
+
switch (state) {
|
|
3867
4348
|
case "pass":
|
|
3868
|
-
return
|
|
4349
|
+
return pass;
|
|
3869
4350
|
case "fail":
|
|
3870
|
-
return
|
|
4351
|
+
return fail;
|
|
4352
|
+
case "skip":
|
|
4353
|
+
case "todo":
|
|
4354
|
+
return skip;
|
|
3871
4355
|
default:
|
|
3872
4356
|
return pending;
|
|
3873
4357
|
}
|
|
3874
4358
|
}
|
|
3875
|
-
function
|
|
3876
|
-
const all = getTests(tasks);
|
|
4359
|
+
function formatTests(states) {
|
|
3877
4360
|
let currentIcon = pending;
|
|
3878
|
-
let
|
|
3879
|
-
let previousLineWidth = 0;
|
|
4361
|
+
let count = 0;
|
|
3880
4362
|
let output = "";
|
|
3881
|
-
const
|
|
3882
|
-
const
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
output += color(char.repeat(currentTasks));
|
|
3886
|
-
previousLineWidth += currentTasks;
|
|
3887
|
-
} else {
|
|
3888
|
-
let buf = `${char.repeat(availableWidth)}
|
|
3889
|
-
`;
|
|
3890
|
-
const remaining = currentTasks - availableWidth;
|
|
3891
|
-
const fullRows = Math.floor(remaining / width);
|
|
3892
|
-
buf += `${char.repeat(width)}
|
|
3893
|
-
`.repeat(fullRows);
|
|
3894
|
-
const partialRow = remaining % width;
|
|
3895
|
-
if (partialRow > 0) {
|
|
3896
|
-
buf += char.repeat(partialRow);
|
|
3897
|
-
previousLineWidth = partialRow;
|
|
3898
|
-
} else {
|
|
3899
|
-
previousLineWidth = 0;
|
|
3900
|
-
}
|
|
3901
|
-
output += color(buf);
|
|
3902
|
-
}
|
|
3903
|
-
};
|
|
3904
|
-
for (const task of all) {
|
|
3905
|
-
const icon = getIcon(task);
|
|
3906
|
-
if (icon === currentIcon) {
|
|
3907
|
-
currentTasks++;
|
|
4363
|
+
for (const state of states) {
|
|
4364
|
+
const icon = getIcon(state);
|
|
4365
|
+
if (currentIcon === icon) {
|
|
4366
|
+
count++;
|
|
3908
4367
|
continue;
|
|
3909
4368
|
}
|
|
3910
|
-
|
|
3911
|
-
|
|
4369
|
+
output += currentIcon.color(currentIcon.char.repeat(count));
|
|
4370
|
+
count = 1;
|
|
3912
4371
|
currentIcon = icon;
|
|
3913
4372
|
}
|
|
3914
|
-
|
|
4373
|
+
output += currentIcon.color(currentIcon.char.repeat(count));
|
|
3915
4374
|
return output;
|
|
3916
4375
|
}
|
|
3917
|
-
function createDotRenderer(_tasks, options) {
|
|
3918
|
-
let tasks = _tasks;
|
|
3919
|
-
let timer;
|
|
3920
|
-
const { logUpdate: log, outputStream } = options.logger;
|
|
3921
|
-
const columns = "columns" in outputStream ? outputStream.columns : 80;
|
|
3922
|
-
function update() {
|
|
3923
|
-
log(render(tasks, columns));
|
|
3924
|
-
}
|
|
3925
|
-
return {
|
|
3926
|
-
start() {
|
|
3927
|
-
if (timer) {
|
|
3928
|
-
return this;
|
|
3929
|
-
}
|
|
3930
|
-
timer = setInterval(update, 16);
|
|
3931
|
-
return this;
|
|
3932
|
-
},
|
|
3933
|
-
update(_tasks2) {
|
|
3934
|
-
tasks = _tasks2;
|
|
3935
|
-
return this;
|
|
3936
|
-
},
|
|
3937
|
-
async stop() {
|
|
3938
|
-
if (timer) {
|
|
3939
|
-
clearInterval(timer);
|
|
3940
|
-
timer = void 0;
|
|
3941
|
-
}
|
|
3942
|
-
log.clear();
|
|
3943
|
-
options.logger.log(render(tasks, columns));
|
|
3944
|
-
return this;
|
|
3945
|
-
},
|
|
3946
|
-
clear() {
|
|
3947
|
-
log.clear();
|
|
3948
|
-
}
|
|
3949
|
-
};
|
|
3950
|
-
}
|
|
3951
|
-
|
|
3952
|
-
class DotReporter extends BaseReporter {
|
|
3953
|
-
renderer;
|
|
3954
|
-
onTaskUpdate() {
|
|
3955
|
-
}
|
|
3956
|
-
onCollected() {
|
|
3957
|
-
if (this.isTTY) {
|
|
3958
|
-
const files = this.ctx.state.getFiles(this.watchFilters);
|
|
3959
|
-
if (!this.renderer) {
|
|
3960
|
-
this.renderer = createDotRenderer(files, {
|
|
3961
|
-
logger: this.ctx.logger
|
|
3962
|
-
}).start();
|
|
3963
|
-
} else {
|
|
3964
|
-
this.renderer.update(files);
|
|
3965
|
-
}
|
|
3966
|
-
}
|
|
3967
|
-
}
|
|
3968
|
-
async onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
|
|
3969
|
-
await this.stopListRender();
|
|
3970
|
-
this.ctx.logger.log();
|
|
3971
|
-
super.onFinished(files, errors);
|
|
3972
|
-
}
|
|
3973
|
-
async onWatcherStart() {
|
|
3974
|
-
await this.stopListRender();
|
|
3975
|
-
super.onWatcherStart();
|
|
3976
|
-
}
|
|
3977
|
-
async stopListRender() {
|
|
3978
|
-
this.renderer?.stop();
|
|
3979
|
-
this.renderer = void 0;
|
|
3980
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
3981
|
-
}
|
|
3982
|
-
async onWatcherRerun(files, trigger) {
|
|
3983
|
-
await this.stopListRender();
|
|
3984
|
-
super.onWatcherRerun(files, trigger);
|
|
3985
|
-
}
|
|
3986
|
-
onUserConsoleLog(log) {
|
|
3987
|
-
this.renderer?.clear();
|
|
3988
|
-
super.onUserConsoleLog(log);
|
|
3989
|
-
}
|
|
3990
|
-
}
|
|
3991
4376
|
|
|
3992
4377
|
class GithubActionsReporter {
|
|
3993
4378
|
ctx = void 0;
|
|
@@ -4443,6 +4828,7 @@ class JUnitReporter {
|
|
|
4443
4828
|
(stats2, file) => {
|
|
4444
4829
|
stats2.tests += file.tasks.length;
|
|
4445
4830
|
stats2.failures += file.stats.failures;
|
|
4831
|
+
stats2.time += file.result?.duration || 0;
|
|
4446
4832
|
return stats2;
|
|
4447
4833
|
},
|
|
4448
4834
|
{
|
|
@@ -4451,10 +4837,10 @@ class JUnitReporter {
|
|
|
4451
4837
|
failures: 0,
|
|
4452
4838
|
errors: 0,
|
|
4453
4839
|
// we cannot detect those
|
|
4454
|
-
time:
|
|
4840
|
+
time: 0
|
|
4455
4841
|
}
|
|
4456
4842
|
);
|
|
4457
|
-
await this.writeElement("testsuites", stats, async () => {
|
|
4843
|
+
await this.writeElement("testsuites", { ...stats, time: executionTime(stats.time) }, async () => {
|
|
4458
4844
|
for (const file of transformed) {
|
|
4459
4845
|
const filename = relative(this.ctx.config.root, file.filepath);
|
|
4460
4846
|
await this.writeElement(
|