vitest 0.0.76 → 0.0.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import require$$2, { EventEmitter } from 'events';
2
- import { s as stringWidth, a as ansiStyles, b as stripAnsi, c as sliceAnsi, d as c, F as F_POINTER, e as F_DOWN, f as F_LONG_DASH, g as F_DOWN_RIGHT, h as F_DOT, i as F_CHECK, j as F_CROSS, k as cliTruncate, l as F_RIGHT, p as printError } from './error-1df12c37.js';
3
- import { performance } from 'perf_hooks';
2
+ import { s as stringWidth, a as ansiStyles, b as stripAnsi, c as sliceAnsi, d as c, F as F_POINTER, e as F_DOWN, f as F_LONG_DASH, g as F_DOWN_RIGHT, h as F_DOT, i as F_CHECK, j as F_CROSS, k as cliTruncate, l as F_RIGHT, p as printError } from './error-c9295525.js';
4
3
  import path, { isAbsolute, relative, dirname, basename, resolve } from 'path';
5
- import { g as getNames, s as slash, a as getTests, b as getSuites, t as toArray, h as hasFailed } from './utils-9dcc4050.js';
6
4
  import process$2 from 'process';
7
- import require$$0 from 'assert';
8
5
  import { promises } from 'fs';
9
6
  import { createServer } from 'vite';
10
- import { d as defaultIncludes, a as defaultExcludes, b as distDir } from './constants-d4c70610.js';
7
+ import { d as defaultIncludes, a as defaultExcludes, b as defaultPort, c as configFiles, e as distDir } from './constants-9da0006f.js';
8
+ import { performance } from 'perf_hooks';
9
+ import { g as getNames, s as slash, a as getTests, b as getSuites, t as toArray, h as hasFailed } from './utils-9dcc4050.js';
10
+ import require$$0 from 'assert';
11
11
  import { MessageChannel } from 'worker_threads';
12
12
  import { pathToFileURL } from 'url';
13
13
  import Piscina from 'piscina';
@@ -632,1483 +632,1516 @@ const cac = (name = "") => new CAC(name);
632
632
 
633
633
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
634
634
 
635
- var version = "0.0.76";
636
-
637
- const ESC = '\u001B[';
638
- const OSC = '\u001B]';
639
- const BEL = '\u0007';
640
- const SEP = ';';
641
- const isTerminalApp = process.env.TERM_PROGRAM === 'Apple_Terminal';
635
+ var version = "0.0.80";
642
636
 
643
- const ansiEscapes = {};
637
+ /*
638
+ How it works:
639
+ `this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.
640
+ */
644
641
 
645
- ansiEscapes.cursorTo = (x, y) => {
646
- if (typeof x !== 'number') {
647
- throw new TypeError('The `x` argument is required');
648
- }
642
+ class Node {
643
+ value;
644
+ next;
649
645
 
650
- if (typeof y !== 'number') {
651
- return ESC + (x + 1) + 'G';
646
+ constructor(value) {
647
+ this.value = value;
652
648
  }
649
+ }
653
650
 
654
- return ESC + (y + 1) + ';' + (x + 1) + 'H';
655
- };
651
+ class Queue {
652
+ #head;
653
+ #tail;
654
+ #size;
656
655
 
657
- ansiEscapes.cursorMove = (x, y) => {
658
- if (typeof x !== 'number') {
659
- throw new TypeError('The `x` argument is required');
656
+ constructor() {
657
+ this.clear();
660
658
  }
661
659
 
662
- let returnValue = '';
660
+ enqueue(value) {
661
+ const node = new Node(value);
663
662
 
664
- if (x < 0) {
665
- returnValue += ESC + (-x) + 'D';
666
- } else if (x > 0) {
667
- returnValue += ESC + x + 'C';
668
- }
663
+ if (this.#head) {
664
+ this.#tail.next = node;
665
+ this.#tail = node;
666
+ } else {
667
+ this.#head = node;
668
+ this.#tail = node;
669
+ }
669
670
 
670
- if (y < 0) {
671
- returnValue += ESC + (-y) + 'A';
672
- } else if (y > 0) {
673
- returnValue += ESC + y + 'B';
671
+ this.#size++;
674
672
  }
675
673
 
676
- return returnValue;
677
- };
678
-
679
- ansiEscapes.cursorUp = (count = 1) => ESC + count + 'A';
680
- ansiEscapes.cursorDown = (count = 1) => ESC + count + 'B';
681
- ansiEscapes.cursorForward = (count = 1) => ESC + count + 'C';
682
- ansiEscapes.cursorBackward = (count = 1) => ESC + count + 'D';
683
-
684
- ansiEscapes.cursorLeft = ESC + 'G';
685
- ansiEscapes.cursorSavePosition = isTerminalApp ? '\u001B7' : ESC + 's';
686
- ansiEscapes.cursorRestorePosition = isTerminalApp ? '\u001B8' : ESC + 'u';
687
- ansiEscapes.cursorGetPosition = ESC + '6n';
688
- ansiEscapes.cursorNextLine = ESC + 'E';
689
- ansiEscapes.cursorPrevLine = ESC + 'F';
690
- ansiEscapes.cursorHide = ESC + '?25l';
691
- ansiEscapes.cursorShow = ESC + '?25h';
674
+ dequeue() {
675
+ const current = this.#head;
676
+ if (!current) {
677
+ return;
678
+ }
692
679
 
693
- ansiEscapes.eraseLines = count => {
694
- let clear = '';
680
+ this.#head = this.#head.next;
681
+ this.#size--;
682
+ return current.value;
683
+ }
695
684
 
696
- for (let i = 0; i < count; i++) {
697
- clear += ansiEscapes.eraseLine + (i < count - 1 ? ansiEscapes.cursorUp() : '');
685
+ clear() {
686
+ this.#head = undefined;
687
+ this.#tail = undefined;
688
+ this.#size = 0;
698
689
  }
699
690
 
700
- if (count) {
701
- clear += ansiEscapes.cursorLeft;
691
+ get size() {
692
+ return this.#size;
702
693
  }
703
694
 
704
- return clear;
705
- };
695
+ * [Symbol.iterator]() {
696
+ let current = this.#head;
706
697
 
707
- ansiEscapes.eraseEndLine = ESC + 'K';
708
- ansiEscapes.eraseStartLine = ESC + '1K';
709
- ansiEscapes.eraseLine = ESC + '2K';
710
- ansiEscapes.eraseDown = ESC + 'J';
711
- ansiEscapes.eraseUp = ESC + '1J';
712
- ansiEscapes.eraseScreen = ESC + '2J';
713
- ansiEscapes.scrollUp = ESC + 'S';
714
- ansiEscapes.scrollDown = ESC + 'T';
698
+ while (current) {
699
+ yield current.value;
700
+ current = current.next;
701
+ }
702
+ }
703
+ }
715
704
 
716
- ansiEscapes.clearScreen = '\u001Bc';
705
+ function pLimit(concurrency) {
706
+ if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
707
+ throw new TypeError('Expected `concurrency` to be a number from 1 and up');
708
+ }
717
709
 
718
- ansiEscapes.clearTerminal = process.platform === 'win32' ?
719
- `${ansiEscapes.eraseScreen}${ESC}0f` :
720
- // 1. Erases the screen (Only done in case `2` is not supported)
721
- // 2. Erases the whole screen including scrollback buffer
722
- // 3. Moves cursor to the top-left position
723
- // More info: https://www.real-world-systems.com/docs/ANSIcode.html
724
- `${ansiEscapes.eraseScreen}${ESC}3J${ESC}H`;
710
+ const queue = new Queue();
711
+ let activeCount = 0;
725
712
 
726
- ansiEscapes.beep = BEL;
713
+ const next = () => {
714
+ activeCount--;
727
715
 
728
- ansiEscapes.link = (text, url) => {
729
- return [
730
- OSC,
731
- '8',
732
- SEP,
733
- SEP,
734
- url,
735
- BEL,
736
- text,
737
- OSC,
738
- '8',
739
- SEP,
740
- SEP,
741
- BEL
742
- ].join('');
743
- };
716
+ if (queue.size > 0) {
717
+ queue.dequeue()();
718
+ }
719
+ };
744
720
 
745
- ansiEscapes.image = (buffer, options = {}) => {
746
- let returnValue = `${OSC}1337;File=inline=1`;
721
+ const run = async (fn, resolve, args) => {
722
+ activeCount++;
747
723
 
748
- if (options.width) {
749
- returnValue += `;width=${options.width}`;
750
- }
724
+ const result = (async () => fn(...args))();
751
725
 
752
- if (options.height) {
753
- returnValue += `;height=${options.height}`;
754
- }
726
+ resolve(result);
755
727
 
756
- if (options.preserveAspectRatio === false) {
757
- returnValue += ';preserveAspectRatio=0';
758
- }
728
+ try {
729
+ await result;
730
+ } catch {}
759
731
 
760
- return returnValue + ':' + buffer.toString('base64') + BEL;
761
- };
732
+ next();
733
+ };
762
734
 
763
- ansiEscapes.iTerm = {
764
- setCwd: (cwd = process.cwd()) => `${OSC}50;CurrentDir=${cwd}${BEL}`,
735
+ const enqueue = (fn, resolve, args) => {
736
+ queue.enqueue(run.bind(undefined, fn, resolve, args));
765
737
 
766
- annotation: (message, options = {}) => {
767
- let returnValue = `${OSC}1337;`;
738
+ (async () => {
739
+ // This function needs to wait until the next microtask before comparing
740
+ // `activeCount` to `concurrency`, because `activeCount` is updated asynchronously
741
+ // when the run function is dequeued and called. The comparison in the if-statement
742
+ // needs to happen asynchronously as well to get an up-to-date value for `activeCount`.
743
+ await Promise.resolve();
768
744
 
769
- const hasX = typeof options.x !== 'undefined';
770
- const hasY = typeof options.y !== 'undefined';
771
- if ((hasX || hasY) && !(hasX && hasY && typeof options.length !== 'undefined')) {
772
- throw new Error('`x`, `y` and `length` must be defined when `x` or `y` is defined');
773
- }
745
+ if (activeCount < concurrency && queue.size > 0) {
746
+ queue.dequeue()();
747
+ }
748
+ })();
749
+ };
774
750
 
775
- message = message.replace(/\|/g, '');
751
+ const generator = (fn, ...args) => new Promise(resolve => {
752
+ enqueue(fn, resolve, args);
753
+ });
776
754
 
777
- returnValue += options.isHidden ? 'AddHiddenAnnotation=' : 'AddAnnotation=';
755
+ Object.defineProperties(generator, {
756
+ activeCount: {
757
+ get: () => activeCount,
758
+ },
759
+ pendingCount: {
760
+ get: () => queue.size,
761
+ },
762
+ clearQueue: {
763
+ value: () => {
764
+ queue.clear();
765
+ },
766
+ },
767
+ });
778
768
 
779
- if (options.length > 0) {
780
- returnValue +=
781
- (hasX ?
782
- [message, options.length, options.x, options.y] :
783
- [options.length, message]).join('|');
784
- } else {
785
- returnValue += message;
786
- }
769
+ return generator;
770
+ }
787
771
 
788
- return returnValue + BEL;
772
+ class EndError extends Error {
773
+ constructor(value) {
774
+ super();
775
+ this.value = value;
789
776
  }
790
- };
791
-
792
- var onetime$2 = {exports: {}};
777
+ }
793
778
 
794
- var mimicFn$2 = {exports: {}};
779
+ // The input can also be a promise, so we await it.
780
+ const testElement = async (element, tester) => tester(await element);
795
781
 
796
- const mimicFn$1 = (to, from) => {
797
- for (const prop of Reflect.ownKeys(from)) {
798
- Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop));
782
+ // The input can also be a promise, so we `Promise.all()` them both.
783
+ const finder = async element => {
784
+ const values = await Promise.all(element);
785
+ if (values[1] === true) {
786
+ throw new EndError(values[0]);
799
787
  }
800
788
 
801
- return to;
789
+ return false;
802
790
  };
803
791
 
804
- mimicFn$2.exports = mimicFn$1;
805
- // TODO: Remove this for the next major release
806
- mimicFn$2.exports.default = mimicFn$1;
807
-
808
- const mimicFn = mimicFn$2.exports;
809
-
810
- const calledFunctions = new WeakMap();
811
-
812
- const onetime = (function_, options = {}) => {
813
- if (typeof function_ !== 'function') {
814
- throw new TypeError('Expected a function');
815
- }
792
+ async function pLocate(
793
+ iterable,
794
+ tester,
795
+ {
796
+ concurrency = Number.POSITIVE_INFINITY,
797
+ preserveOrder = true,
798
+ } = {},
799
+ ) {
800
+ const limit = pLimit(concurrency);
816
801
 
817
- let returnValue;
818
- let callCount = 0;
819
- const functionName = function_.displayName || function_.name || '<anonymous>';
802
+ // Start all the promises concurrently with optional limit.
803
+ const items = [...iterable].map(element => [element, limit(testElement, element, tester)]);
820
804
 
821
- const onetime = function (...arguments_) {
822
- calledFunctions.set(onetime, ++callCount);
805
+ // Check the promises either serially or concurrently.
806
+ const checkLimit = pLimit(preserveOrder ? 1 : Number.POSITIVE_INFINITY);
823
807
 
824
- if (callCount === 1) {
825
- returnValue = function_.apply(this, arguments_);
826
- function_ = null;
827
- } else if (options.throw === true) {
828
- throw new Error(`Function \`${functionName}\` can only be called once`);
808
+ try {
809
+ await Promise.all(items.map(element => checkLimit(finder, element)));
810
+ } catch (error) {
811
+ if (error instanceof EndError) {
812
+ return error.value;
829
813
  }
830
814
 
831
- return returnValue;
832
- };
833
-
834
- mimicFn(onetime, function_);
835
- calledFunctions.set(onetime, callCount);
836
-
837
- return onetime;
838
- };
839
-
840
- onetime$2.exports = onetime;
841
- // TODO: Remove this for the next major release
842
- onetime$2.exports.default = onetime;
843
-
844
- onetime$2.exports.callCount = function_ => {
845
- if (!calledFunctions.has(function_)) {
846
- throw new Error(`The given function \`${function_.name}\` is not wrapped by the \`onetime\` package`);
815
+ throw error;
847
816
  }
817
+ }
848
818
 
849
- return calledFunctions.get(function_);
819
+ const typeMappings = {
820
+ directory: 'isDirectory',
821
+ file: 'isFile',
850
822
  };
851
823
 
852
- var onetime$1 = onetime$2.exports;
824
+ function checkType(type) {
825
+ if (type in typeMappings) {
826
+ return;
827
+ }
853
828
 
854
- var signalExit$1 = {exports: {}};
829
+ throw new Error(`Invalid type specified: ${type}`);
830
+ }
855
831
 
856
- var signals$1 = {exports: {}};
832
+ const matchType = (type, stat) => type === undefined || stat[typeMappings[type]]();
857
833
 
858
- (function (module) {
859
- // This is not the set of all possible signals.
860
- //
861
- // It IS, however, the set of all signals that trigger
862
- // an exit on either Linux or BSD systems. Linux is a
863
- // superset of the signal names supported on BSD, and
864
- // the unknown signals just fail to register, so we can
865
- // catch that easily enough.
866
- //
867
- // Don't bother with SIGKILL. It's uncatchable, which
868
- // means that we can't fire any callbacks anyway.
869
- //
870
- // If a user does happen to register a handler on a non-
871
- // fatal signal like SIGWINCH or something, and then
872
- // exit, it'll end up firing `process.emit('exit')`, so
873
- // the handler will be fired anyway.
874
- //
875
- // SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised
876
- // artificially, inherently leave the process in a
877
- // state from which it is not safe to try and enter JS
878
- // listeners.
879
- module.exports = [
880
- 'SIGABRT',
881
- 'SIGALRM',
882
- 'SIGHUP',
883
- 'SIGINT',
884
- 'SIGTERM'
885
- ];
834
+ async function locatePath(
835
+ paths,
836
+ {
837
+ cwd = process$2.cwd(),
838
+ type = 'file',
839
+ allowSymlinks = true,
840
+ concurrency,
841
+ preserveOrder,
842
+ } = {},
843
+ ) {
844
+ checkType(type);
886
845
 
887
- if (process.platform !== 'win32') {
888
- module.exports.push(
889
- 'SIGVTALRM',
890
- 'SIGXCPU',
891
- 'SIGXFSZ',
892
- 'SIGUSR2',
893
- 'SIGTRAP',
894
- 'SIGSYS',
895
- 'SIGQUIT',
896
- 'SIGIOT'
897
- // should detect profiler and enable/disable accordingly.
898
- // see #21
899
- // 'SIGPROF'
900
- );
901
- }
846
+ const statFunction = allowSymlinks ? promises.stat : promises.lstat;
902
847
 
903
- if (process.platform === 'linux') {
904
- module.exports.push(
905
- 'SIGIO',
906
- 'SIGPOLL',
907
- 'SIGPWR',
908
- 'SIGSTKFLT',
909
- 'SIGUNUSED'
910
- );
848
+ return pLocate(paths, async path_ => {
849
+ try {
850
+ const stat = await statFunction(path.resolve(cwd, path_));
851
+ return matchType(type, stat);
852
+ } catch {
853
+ return false;
854
+ }
855
+ }, {concurrency, preserveOrder});
911
856
  }
912
- }(signals$1));
913
857
 
914
- // Note: since nyc uses this module to output coverage, any lines
915
- // that are in the direct sync flow of nyc's outputCoverage are
916
- // ignored, since we can never get coverage for them.
917
- // grab a reference to node's real process object right away
918
- var process$1 = commonjsGlobal.process;
858
+ const findUpStop = Symbol('findUpStop');
919
859
 
920
- const processOk = function (process) {
921
- return process &&
922
- typeof process === 'object' &&
923
- typeof process.removeListener === 'function' &&
924
- typeof process.emit === 'function' &&
925
- typeof process.reallyExit === 'function' &&
926
- typeof process.listeners === 'function' &&
927
- typeof process.kill === 'function' &&
928
- typeof process.pid === 'number' &&
929
- typeof process.on === 'function'
930
- };
860
+ async function findUpMultiple(name, options = {}) {
861
+ let directory = path.resolve(options.cwd || '');
862
+ const {root} = path.parse(directory);
863
+ const stopAt = path.resolve(directory, options.stopAt || root);
864
+ const limit = options.limit || Number.POSITIVE_INFINITY;
865
+ const paths = [name].flat();
931
866
 
932
- // some kind of non-node environment, just no-op
933
- /* istanbul ignore if */
934
- if (!processOk(process$1)) {
935
- signalExit$1.exports = function () {};
936
- } else {
937
- var assert = require$$0;
938
- var signals = signals$1.exports;
939
- var isWin = /^win/i.test(process$1.platform);
867
+ const runMatcher = async locateOptions => {
868
+ if (typeof name !== 'function') {
869
+ return locatePath(paths, locateOptions);
870
+ }
940
871
 
941
- var EE = require$$2;
942
- /* istanbul ignore if */
943
- if (typeof EE !== 'function') {
944
- EE = EE.EventEmitter;
945
- }
872
+ const foundPath = await name(locateOptions.cwd);
873
+ if (typeof foundPath === 'string') {
874
+ return locatePath([foundPath], locateOptions);
875
+ }
946
876
 
947
- var emitter;
948
- if (process$1.__signal_exit_emitter__) {
949
- emitter = process$1.__signal_exit_emitter__;
950
- } else {
951
- emitter = process$1.__signal_exit_emitter__ = new EE();
952
- emitter.count = 0;
953
- emitter.emitted = {};
954
- }
877
+ return foundPath;
878
+ };
955
879
 
956
- // Because this emitter is a global, we have to check to see if a
957
- // previous version of this library failed to enable infinite listeners.
958
- // I know what you're about to say. But literally everything about
959
- // signal-exit is a compromise with evil. Get used to it.
960
- if (!emitter.infinite) {
961
- emitter.setMaxListeners(Infinity);
962
- emitter.infinite = true;
963
- }
880
+ const matches = [];
881
+ // eslint-disable-next-line no-constant-condition
882
+ while (true) {
883
+ // eslint-disable-next-line no-await-in-loop
884
+ const foundPath = await runMatcher({...options, cwd: directory});
964
885
 
965
- signalExit$1.exports = function (cb, opts) {
966
- /* istanbul ignore if */
967
- if (!processOk(commonjsGlobal.process)) {
968
- return
969
- }
970
- assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler');
886
+ if (foundPath === findUpStop) {
887
+ break;
888
+ }
971
889
 
972
- if (loaded === false) {
973
- load();
974
- }
890
+ if (foundPath) {
891
+ matches.push(path.resolve(directory, foundPath));
892
+ }
975
893
 
976
- var ev = 'exit';
977
- if (opts && opts.alwaysLast) {
978
- ev = 'afterexit';
979
- }
894
+ if (directory === stopAt || matches.length >= limit) {
895
+ break;
896
+ }
980
897
 
981
- var remove = function () {
982
- emitter.removeListener(ev, cb);
983
- if (emitter.listeners('exit').length === 0 &&
984
- emitter.listeners('afterexit').length === 0) {
985
- unload();
986
- }
987
- };
988
- emitter.on(ev, cb);
898
+ directory = path.dirname(directory);
899
+ }
989
900
 
990
- return remove
991
- };
901
+ return matches;
902
+ }
992
903
 
993
- var unload = function unload () {
994
- if (!loaded || !processOk(commonjsGlobal.process)) {
995
- return
996
- }
997
- loaded = false;
904
+ async function findUp(name, options = {}) {
905
+ const matches = await findUpMultiple(name, {...options, limit: 1});
906
+ return matches[0];
907
+ }
998
908
 
999
- signals.forEach(function (sig) {
1000
- try {
1001
- process$1.removeListener(sig, sigListeners[sig]);
1002
- } catch (er) {}
1003
- });
1004
- process$1.emit = originalProcessEmit;
1005
- process$1.reallyExit = originalProcessReallyExit;
1006
- emitter.count -= 1;
1007
- };
1008
- signalExit$1.exports.unload = unload;
1009
-
1010
- var emit = function emit (event, code, signal) {
1011
- /* istanbul ignore if */
1012
- if (emitter.emitted[event]) {
1013
- return
1014
- }
1015
- emitter.emitted[event] = true;
1016
- emitter.emit(event, code, signal);
1017
- };
1018
-
1019
- // { <signal>: <listener fn>, ... }
1020
- var sigListeners = {};
1021
- signals.forEach(function (sig) {
1022
- sigListeners[sig] = function listener () {
1023
- /* istanbul ignore if */
1024
- if (!processOk(commonjsGlobal.process)) {
1025
- return
1026
- }
1027
- // If there are no other listeners, an exit is coming!
1028
- // Simplest way: remove us and then re-send the signal.
1029
- // We know that this will kill the process, so we can
1030
- // safely emit now.
1031
- var listeners = process$1.listeners(sig);
1032
- if (listeners.length === emitter.count) {
1033
- unload();
1034
- emit('exit', null, sig);
1035
- /* istanbul ignore next */
1036
- emit('afterexit', null, sig);
1037
- /* istanbul ignore next */
1038
- if (isWin && sig === 'SIGHUP') {
1039
- // "SIGHUP" throws an `ENOSYS` error on Windows,
1040
- // so use a supported signal instead
1041
- sig = 'SIGINT';
1042
- }
1043
- /* istanbul ignore next */
1044
- process$1.kill(process$1.pid, sig);
1045
- }
1046
- };
1047
- });
1048
-
1049
- signalExit$1.exports.signals = function () {
1050
- return signals
909
+ class SnapshotManager {
910
+ constructor(config) {
911
+ this.config = config;
912
+ this.summary = void 0;
913
+ this.clear();
914
+ }
915
+ clear() {
916
+ this.summary = emptySummary(this.config.snapshotOptions);
917
+ }
918
+ add(result) {
919
+ addSnapshotResult(this.summary, result);
920
+ }
921
+ }
922
+ function emptySummary(options) {
923
+ const summary = {
924
+ added: 0,
925
+ failure: false,
926
+ filesAdded: 0,
927
+ filesRemoved: 0,
928
+ filesRemovedList: [],
929
+ filesUnmatched: 0,
930
+ filesUpdated: 0,
931
+ matched: 0,
932
+ total: 0,
933
+ unchecked: 0,
934
+ uncheckedKeysByFile: [],
935
+ unmatched: 0,
936
+ updated: 0,
937
+ didUpdate: options.updateSnapshot === "all"
1051
938
  };
1052
-
1053
- var loaded = false;
1054
-
1055
- var load = function load () {
1056
- if (loaded || !processOk(commonjsGlobal.process)) {
1057
- return
1058
- }
1059
- loaded = true;
1060
-
1061
- // This is the number of onSignalExit's that are in play.
1062
- // It's important so that we can count the correct number of
1063
- // listeners on signals, and don't wait for the other one to
1064
- // handle it instead of us.
1065
- emitter.count += 1;
1066
-
1067
- signals = signals.filter(function (sig) {
1068
- try {
1069
- process$1.on(sig, sigListeners[sig]);
1070
- return true
1071
- } catch (er) {
1072
- return false
1073
- }
939
+ return summary;
940
+ }
941
+ function addSnapshotResult(summary, result) {
942
+ if (result.added)
943
+ summary.filesAdded++;
944
+ if (result.fileDeleted)
945
+ summary.filesRemoved++;
946
+ if (result.unmatched)
947
+ summary.filesUnmatched++;
948
+ if (result.updated)
949
+ summary.filesUpdated++;
950
+ summary.added += result.added;
951
+ summary.matched += result.matched;
952
+ summary.unchecked += result.unchecked;
953
+ if (result.uncheckedKeys && result.uncheckedKeys.length > 0) {
954
+ summary.uncheckedKeysByFile.push({
955
+ filePath: result.filepath,
956
+ keys: result.uncheckedKeys
1074
957
  });
1075
-
1076
- process$1.emit = processEmit;
1077
- process$1.reallyExit = processReallyExit;
1078
- };
1079
- signalExit$1.exports.load = load;
1080
-
1081
- var originalProcessReallyExit = process$1.reallyExit;
1082
- var processReallyExit = function processReallyExit (code) {
1083
- /* istanbul ignore if */
1084
- if (!processOk(commonjsGlobal.process)) {
1085
- return
1086
- }
1087
- process$1.exitCode = code || /* istanbul ignore next */ 0;
1088
- emit('exit', process$1.exitCode, null);
1089
- /* istanbul ignore next */
1090
- emit('afterexit', process$1.exitCode, null);
1091
- /* istanbul ignore next */
1092
- originalProcessReallyExit.call(process$1, process$1.exitCode);
1093
- };
1094
-
1095
- var originalProcessEmit = process$1.emit;
1096
- var processEmit = function processEmit (ev, arg) {
1097
- if (ev === 'exit' && processOk(commonjsGlobal.process)) {
1098
- /* istanbul ignore else */
1099
- if (arg !== undefined) {
1100
- process$1.exitCode = arg;
1101
- }
1102
- var ret = originalProcessEmit.apply(this, arguments);
1103
- /* istanbul ignore next */
1104
- emit('exit', process$1.exitCode, null);
1105
- /* istanbul ignore next */
1106
- emit('afterexit', process$1.exitCode, null);
1107
- /* istanbul ignore next */
1108
- return ret
1109
- } else {
1110
- return originalProcessEmit.apply(this, arguments)
1111
- }
1112
- };
958
+ }
959
+ summary.unmatched += result.unmatched;
960
+ summary.updated += result.updated;
961
+ summary.total += result.added + result.matched + result.unmatched + result.updated;
1113
962
  }
1114
963
 
1115
- var signalExit = signalExit$1.exports;
1116
-
1117
- const restoreCursor = onetime$1(() => {
1118
- signalExit(() => {
1119
- process$2.stderr.write('\u001B[?25h');
1120
- }, {alwaysLast: true});
1121
- });
964
+ const ESC = '\u001B[';
965
+ const OSC = '\u001B]';
966
+ const BEL = '\u0007';
967
+ const SEP = ';';
968
+ const isTerminalApp = process.env.TERM_PROGRAM === 'Apple_Terminal';
1122
969
 
1123
- let isHidden = false;
970
+ const ansiEscapes = {};
1124
971
 
1125
- const cliCursor = {};
972
+ ansiEscapes.cursorTo = (x, y) => {
973
+ if (typeof x !== 'number') {
974
+ throw new TypeError('The `x` argument is required');
975
+ }
1126
976
 
1127
- cliCursor.show = (writableStream = process$2.stderr) => {
1128
- if (!writableStream.isTTY) {
1129
- return;
977
+ if (typeof y !== 'number') {
978
+ return ESC + (x + 1) + 'G';
1130
979
  }
1131
980
 
1132
- isHidden = false;
1133
- writableStream.write('\u001B[?25h');
981
+ return ESC + (y + 1) + ';' + (x + 1) + 'H';
1134
982
  };
1135
983
 
1136
- cliCursor.hide = (writableStream = process$2.stderr) => {
1137
- if (!writableStream.isTTY) {
1138
- return;
984
+ ansiEscapes.cursorMove = (x, y) => {
985
+ if (typeof x !== 'number') {
986
+ throw new TypeError('The `x` argument is required');
1139
987
  }
1140
988
 
1141
- restoreCursor();
1142
- isHidden = true;
1143
- writableStream.write('\u001B[?25l');
1144
- };
989
+ let returnValue = '';
1145
990
 
1146
- cliCursor.toggle = (force, writableStream) => {
1147
- if (force !== undefined) {
1148
- isHidden = force;
991
+ if (x < 0) {
992
+ returnValue += ESC + (-x) + 'D';
993
+ } else if (x > 0) {
994
+ returnValue += ESC + x + 'C';
1149
995
  }
1150
996
 
1151
- if (isHidden) {
1152
- cliCursor.show(writableStream);
1153
- } else {
1154
- cliCursor.hide(writableStream);
997
+ if (y < 0) {
998
+ returnValue += ESC + (-y) + 'A';
999
+ } else if (y > 0) {
1000
+ returnValue += ESC + y + 'B';
1155
1001
  }
1156
- };
1157
1002
 
1158
- const ESCAPES = new Set([
1159
- '\u001B',
1160
- '\u009B',
1161
- ]);
1003
+ return returnValue;
1004
+ };
1162
1005
 
1163
- const END_CODE = 39;
1164
- const ANSI_ESCAPE_BELL = '\u0007';
1165
- const ANSI_CSI = '[';
1166
- const ANSI_OSC = ']';
1167
- const ANSI_SGR_TERMINATOR = 'm';
1168
- const ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
1006
+ ansiEscapes.cursorUp = (count = 1) => ESC + count + 'A';
1007
+ ansiEscapes.cursorDown = (count = 1) => ESC + count + 'B';
1008
+ ansiEscapes.cursorForward = (count = 1) => ESC + count + 'C';
1009
+ ansiEscapes.cursorBackward = (count = 1) => ESC + count + 'D';
1169
1010
 
1170
- const wrapAnsiCode = code => `${ESCAPES.values().next().value}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
1171
- const wrapAnsiHyperlink = uri => `${ESCAPES.values().next().value}${ANSI_ESCAPE_LINK}${uri}${ANSI_ESCAPE_BELL}`;
1011
+ ansiEscapes.cursorLeft = ESC + 'G';
1012
+ ansiEscapes.cursorSavePosition = isTerminalApp ? '\u001B7' : ESC + 's';
1013
+ ansiEscapes.cursorRestorePosition = isTerminalApp ? '\u001B8' : ESC + 'u';
1014
+ ansiEscapes.cursorGetPosition = ESC + '6n';
1015
+ ansiEscapes.cursorNextLine = ESC + 'E';
1016
+ ansiEscapes.cursorPrevLine = ESC + 'F';
1017
+ ansiEscapes.cursorHide = ESC + '?25l';
1018
+ ansiEscapes.cursorShow = ESC + '?25h';
1172
1019
 
1173
- // Calculate the length of words split on ' ', ignoring
1174
- // the extra characters added by ansi escape codes
1175
- const wordLengths = string => string.split(' ').map(character => stringWidth(character));
1020
+ ansiEscapes.eraseLines = count => {
1021
+ let clear = '';
1176
1022
 
1177
- // Wrap a long word across multiple rows
1178
- // Ansi escape codes do not count towards length
1179
- const wrapWord = (rows, word, columns) => {
1180
- const characters = [...word];
1023
+ for (let i = 0; i < count; i++) {
1024
+ clear += ansiEscapes.eraseLine + (i < count - 1 ? ansiEscapes.cursorUp() : '');
1025
+ }
1181
1026
 
1182
- let isInsideEscape = false;
1183
- let isInsideLinkEscape = false;
1184
- let visible = stringWidth(stripAnsi(rows[rows.length - 1]));
1027
+ if (count) {
1028
+ clear += ansiEscapes.cursorLeft;
1029
+ }
1185
1030
 
1186
- for (const [index, character] of characters.entries()) {
1187
- const characterLength = stringWidth(character);
1031
+ return clear;
1032
+ };
1188
1033
 
1189
- if (visible + characterLength <= columns) {
1190
- rows[rows.length - 1] += character;
1191
- } else {
1192
- rows.push(character);
1193
- visible = 0;
1194
- }
1195
-
1196
- if (ESCAPES.has(character)) {
1197
- isInsideEscape = true;
1198
- isInsideLinkEscape = characters.slice(index + 1).join('').startsWith(ANSI_ESCAPE_LINK);
1199
- }
1200
-
1201
- if (isInsideEscape) {
1202
- if (isInsideLinkEscape) {
1203
- if (character === ANSI_ESCAPE_BELL) {
1204
- isInsideEscape = false;
1205
- isInsideLinkEscape = false;
1206
- }
1207
- } else if (character === ANSI_SGR_TERMINATOR) {
1208
- isInsideEscape = false;
1209
- }
1034
+ ansiEscapes.eraseEndLine = ESC + 'K';
1035
+ ansiEscapes.eraseStartLine = ESC + '1K';
1036
+ ansiEscapes.eraseLine = ESC + '2K';
1037
+ ansiEscapes.eraseDown = ESC + 'J';
1038
+ ansiEscapes.eraseUp = ESC + '1J';
1039
+ ansiEscapes.eraseScreen = ESC + '2J';
1040
+ ansiEscapes.scrollUp = ESC + 'S';
1041
+ ansiEscapes.scrollDown = ESC + 'T';
1210
1042
 
1211
- continue;
1212
- }
1043
+ ansiEscapes.clearScreen = '\u001Bc';
1213
1044
 
1214
- visible += characterLength;
1045
+ ansiEscapes.clearTerminal = process.platform === 'win32' ?
1046
+ `${ansiEscapes.eraseScreen}${ESC}0f` :
1047
+ // 1. Erases the screen (Only done in case `2` is not supported)
1048
+ // 2. Erases the whole screen including scrollback buffer
1049
+ // 3. Moves cursor to the top-left position
1050
+ // More info: https://www.real-world-systems.com/docs/ANSIcode.html
1051
+ `${ansiEscapes.eraseScreen}${ESC}3J${ESC}H`;
1215
1052
 
1216
- if (visible === columns && index < characters.length - 1) {
1217
- rows.push('');
1218
- visible = 0;
1219
- }
1220
- }
1053
+ ansiEscapes.beep = BEL;
1221
1054
 
1222
- // It's possible that the last row we copy over is only
1223
- // ansi escape characters, handle this edge-case
1224
- if (!visible && rows[rows.length - 1].length > 0 && rows.length > 1) {
1225
- rows[rows.length - 2] += rows.pop();
1226
- }
1055
+ ansiEscapes.link = (text, url) => {
1056
+ return [
1057
+ OSC,
1058
+ '8',
1059
+ SEP,
1060
+ SEP,
1061
+ url,
1062
+ BEL,
1063
+ text,
1064
+ OSC,
1065
+ '8',
1066
+ SEP,
1067
+ SEP,
1068
+ BEL
1069
+ ].join('');
1227
1070
  };
1228
1071
 
1229
- // Trims spaces from a string ignoring invisible sequences
1230
- const stringVisibleTrimSpacesRight = string => {
1231
- const words = string.split(' ');
1232
- let last = words.length;
1072
+ ansiEscapes.image = (buffer, options = {}) => {
1073
+ let returnValue = `${OSC}1337;File=inline=1`;
1233
1074
 
1234
- while (last > 0) {
1235
- if (stringWidth(words[last - 1]) > 0) {
1236
- break;
1237
- }
1075
+ if (options.width) {
1076
+ returnValue += `;width=${options.width}`;
1077
+ }
1238
1078
 
1239
- last--;
1079
+ if (options.height) {
1080
+ returnValue += `;height=${options.height}`;
1240
1081
  }
1241
1082
 
1242
- if (last === words.length) {
1243
- return string;
1083
+ if (options.preserveAspectRatio === false) {
1084
+ returnValue += ';preserveAspectRatio=0';
1244
1085
  }
1245
1086
 
1246
- return words.slice(0, last).join(' ') + words.slice(last).join('');
1087
+ return returnValue + ':' + buffer.toString('base64') + BEL;
1247
1088
  };
1248
1089
 
1249
- // The wrap-ansi module can be invoked in either 'hard' or 'soft' wrap mode
1250
- //
1251
- // 'hard' will never allow a string to take up more than columns characters
1252
- //
1253
- // 'soft' allows long words to expand past the column length
1254
- const exec = (string, columns, options = {}) => {
1255
- if (options.trim !== false && string.trim() === '') {
1256
- return '';
1257
- }
1258
-
1259
- let returnValue = '';
1260
- let escapeCode;
1261
- let escapeUrl;
1090
+ ansiEscapes.iTerm = {
1091
+ setCwd: (cwd = process.cwd()) => `${OSC}50;CurrentDir=${cwd}${BEL}`,
1262
1092
 
1263
- const lengths = wordLengths(string);
1264
- let rows = [''];
1093
+ annotation: (message, options = {}) => {
1094
+ let returnValue = `${OSC}1337;`;
1265
1095
 
1266
- for (const [index, word] of string.split(' ').entries()) {
1267
- if (options.trim !== false) {
1268
- rows[rows.length - 1] = rows[rows.length - 1].trimStart();
1096
+ const hasX = typeof options.x !== 'undefined';
1097
+ const hasY = typeof options.y !== 'undefined';
1098
+ if ((hasX || hasY) && !(hasX && hasY && typeof options.length !== 'undefined')) {
1099
+ throw new Error('`x`, `y` and `length` must be defined when `x` or `y` is defined');
1269
1100
  }
1270
1101
 
1271
- let rowLength = stringWidth(rows[rows.length - 1]);
1272
-
1273
- if (index !== 0) {
1274
- if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
1275
- // If we start with a new word but the current row length equals the length of the columns, add a new row
1276
- rows.push('');
1277
- rowLength = 0;
1278
- }
1279
-
1280
- if (rowLength > 0 || options.trim === false) {
1281
- rows[rows.length - 1] += ' ';
1282
- rowLength++;
1283
- }
1284
- }
1102
+ message = message.replace(/\|/g, '');
1285
1103
 
1286
- // In 'hard' wrap mode, the length of a line is never allowed to extend past 'columns'
1287
- if (options.hard && lengths[index] > columns) {
1288
- const remainingColumns = (columns - rowLength);
1289
- const breaksStartingThisLine = 1 + Math.floor((lengths[index] - remainingColumns - 1) / columns);
1290
- const breaksStartingNextLine = Math.floor((lengths[index] - 1) / columns);
1291
- if (breaksStartingNextLine < breaksStartingThisLine) {
1292
- rows.push('');
1293
- }
1104
+ returnValue += options.isHidden ? 'AddHiddenAnnotation=' : 'AddAnnotation=';
1294
1105
 
1295
- wrapWord(rows, word, columns);
1296
- continue;
1106
+ if (options.length > 0) {
1107
+ returnValue +=
1108
+ (hasX ?
1109
+ [message, options.length, options.x, options.y] :
1110
+ [options.length, message]).join('|');
1111
+ } else {
1112
+ returnValue += message;
1297
1113
  }
1298
1114
 
1299
- if (rowLength + lengths[index] > columns && rowLength > 0 && lengths[index] > 0) {
1300
- if (options.wordWrap === false && rowLength < columns) {
1301
- wrapWord(rows, word, columns);
1302
- continue;
1303
- }
1115
+ return returnValue + BEL;
1116
+ }
1117
+ };
1304
1118
 
1305
- rows.push('');
1306
- }
1119
+ var onetime$2 = {exports: {}};
1307
1120
 
1308
- if (rowLength + lengths[index] > columns && options.wordWrap === false) {
1309
- wrapWord(rows, word, columns);
1310
- continue;
1311
- }
1121
+ var mimicFn$2 = {exports: {}};
1312
1122
 
1313
- rows[rows.length - 1] += word;
1123
+ const mimicFn$1 = (to, from) => {
1124
+ for (const prop of Reflect.ownKeys(from)) {
1125
+ Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop));
1314
1126
  }
1315
1127
 
1316
- if (options.trim !== false) {
1317
- rows = rows.map(row => stringVisibleTrimSpacesRight(row));
1318
- }
1128
+ return to;
1129
+ };
1319
1130
 
1320
- const pre = [...rows.join('\n')];
1131
+ mimicFn$2.exports = mimicFn$1;
1132
+ // TODO: Remove this for the next major release
1133
+ mimicFn$2.exports.default = mimicFn$1;
1321
1134
 
1322
- for (const [index, character] of pre.entries()) {
1323
- returnValue += character;
1135
+ const mimicFn = mimicFn$2.exports;
1324
1136
 
1325
- if (ESCAPES.has(character)) {
1326
- const {groups} = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`).exec(pre.slice(index).join('')) || {groups: {}};
1327
- if (groups.code !== undefined) {
1328
- const code = Number.parseFloat(groups.code);
1329
- escapeCode = code === END_CODE ? undefined : code;
1330
- } else if (groups.uri !== undefined) {
1331
- escapeUrl = groups.uri.length === 0 ? undefined : groups.uri;
1332
- }
1333
- }
1137
+ const calledFunctions = new WeakMap();
1334
1138
 
1335
- const code = ansiStyles.codes.get(Number(escapeCode));
1139
+ const onetime = (function_, options = {}) => {
1140
+ if (typeof function_ !== 'function') {
1141
+ throw new TypeError('Expected a function');
1142
+ }
1336
1143
 
1337
- if (pre[index + 1] === '\n') {
1338
- if (escapeUrl) {
1339
- returnValue += wrapAnsiHyperlink('');
1340
- }
1144
+ let returnValue;
1145
+ let callCount = 0;
1146
+ const functionName = function_.displayName || function_.name || '<anonymous>';
1341
1147
 
1342
- if (escapeCode && code) {
1343
- returnValue += wrapAnsiCode(code);
1344
- }
1345
- } else if (character === '\n') {
1346
- if (escapeCode && code) {
1347
- returnValue += wrapAnsiCode(escapeCode);
1348
- }
1148
+ const onetime = function (...arguments_) {
1149
+ calledFunctions.set(onetime, ++callCount);
1349
1150
 
1350
- if (escapeUrl) {
1351
- returnValue += wrapAnsiHyperlink(escapeUrl);
1352
- }
1151
+ if (callCount === 1) {
1152
+ returnValue = function_.apply(this, arguments_);
1153
+ function_ = null;
1154
+ } else if (options.throw === true) {
1155
+ throw new Error(`Function \`${functionName}\` can only be called once`);
1353
1156
  }
1354
- }
1355
1157
 
1356
- return returnValue;
1357
- };
1158
+ return returnValue;
1159
+ };
1358
1160
 
1359
- // For each newline, invoke the method separately
1360
- function wrapAnsi(string, columns, options) {
1361
- return String(string)
1362
- .normalize()
1363
- .replace(/\r\n/g, '\n')
1364
- .split('\n')
1365
- .map(line => exec(line, columns, options))
1366
- .join('\n');
1367
- }
1161
+ mimicFn(onetime, function_);
1162
+ calledFunctions.set(onetime, callCount);
1368
1163
 
1369
- const defaultTerminalHeight = 24;
1164
+ return onetime;
1165
+ };
1370
1166
 
1371
- const getWidth = stream => {
1372
- const {columns} = stream;
1167
+ onetime$2.exports = onetime;
1168
+ // TODO: Remove this for the next major release
1169
+ onetime$2.exports.default = onetime;
1373
1170
 
1374
- if (!columns) {
1375
- return 80;
1171
+ onetime$2.exports.callCount = function_ => {
1172
+ if (!calledFunctions.has(function_)) {
1173
+ throw new Error(`The given function \`${function_.name}\` is not wrapped by the \`onetime\` package`);
1376
1174
  }
1377
1175
 
1378
- return columns;
1176
+ return calledFunctions.get(function_);
1379
1177
  };
1380
1178
 
1381
- const fitToTerminalHeight = (stream, text) => {
1382
- const terminalHeight = stream.rows || defaultTerminalHeight;
1383
- const lines = text.split('\n');
1179
+ var onetime$1 = onetime$2.exports;
1384
1180
 
1385
- const toRemove = lines.length - terminalHeight;
1386
- if (toRemove <= 0) {
1387
- return text;
1388
- }
1181
+ var signalExit$1 = {exports: {}};
1389
1182
 
1390
- return sliceAnsi(
1391
- text,
1392
- lines.slice(0, toRemove).join('\n').length + 1,
1393
- text.length);
1394
- };
1183
+ var signals$1 = {exports: {}};
1395
1184
 
1396
- function createLogUpdate(stream, {showCursor = false} = {}) {
1397
- let previousLineCount = 0;
1398
- let previousWidth = getWidth(stream);
1399
- let previousOutput = '';
1185
+ (function (module) {
1186
+ // This is not the set of all possible signals.
1187
+ //
1188
+ // It IS, however, the set of all signals that trigger
1189
+ // an exit on either Linux or BSD systems. Linux is a
1190
+ // superset of the signal names supported on BSD, and
1191
+ // the unknown signals just fail to register, so we can
1192
+ // catch that easily enough.
1193
+ //
1194
+ // Don't bother with SIGKILL. It's uncatchable, which
1195
+ // means that we can't fire any callbacks anyway.
1196
+ //
1197
+ // If a user does happen to register a handler on a non-
1198
+ // fatal signal like SIGWINCH or something, and then
1199
+ // exit, it'll end up firing `process.emit('exit')`, so
1200
+ // the handler will be fired anyway.
1201
+ //
1202
+ // SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised
1203
+ // artificially, inherently leave the process in a
1204
+ // state from which it is not safe to try and enter JS
1205
+ // listeners.
1206
+ module.exports = [
1207
+ 'SIGABRT',
1208
+ 'SIGALRM',
1209
+ 'SIGHUP',
1210
+ 'SIGINT',
1211
+ 'SIGTERM'
1212
+ ];
1400
1213
 
1401
- const render = (...arguments_) => {
1402
- if (!showCursor) {
1403
- cliCursor.hide();
1404
- }
1214
+ if (process.platform !== 'win32') {
1215
+ module.exports.push(
1216
+ 'SIGVTALRM',
1217
+ 'SIGXCPU',
1218
+ 'SIGXFSZ',
1219
+ 'SIGUSR2',
1220
+ 'SIGTRAP',
1221
+ 'SIGSYS',
1222
+ 'SIGQUIT',
1223
+ 'SIGIOT'
1224
+ // should detect profiler and enable/disable accordingly.
1225
+ // see #21
1226
+ // 'SIGPROF'
1227
+ );
1228
+ }
1405
1229
 
1406
- let output = arguments_.join(' ') + '\n';
1407
- output = fitToTerminalHeight(stream, output);
1408
- const width = getWidth(stream);
1409
- if (output === previousOutput && previousWidth === width) {
1410
- return;
1411
- }
1230
+ if (process.platform === 'linux') {
1231
+ module.exports.push(
1232
+ 'SIGIO',
1233
+ 'SIGPOLL',
1234
+ 'SIGPWR',
1235
+ 'SIGSTKFLT',
1236
+ 'SIGUNUSED'
1237
+ );
1238
+ }
1239
+ }(signals$1));
1412
1240
 
1413
- previousOutput = output;
1414
- previousWidth = width;
1415
- output = wrapAnsi(output, width, {
1416
- trim: false,
1417
- hard: true,
1418
- wordWrap: false,
1419
- });
1420
- stream.write(ansiEscapes.eraseLines(previousLineCount) + output);
1421
- previousLineCount = output.split('\n').length;
1422
- };
1241
+ // Note: since nyc uses this module to output coverage, any lines
1242
+ // that are in the direct sync flow of nyc's outputCoverage are
1243
+ // ignored, since we can never get coverage for them.
1244
+ // grab a reference to node's real process object right away
1245
+ var process$1 = commonjsGlobal.process;
1423
1246
 
1424
- render.clear = () => {
1425
- stream.write(ansiEscapes.eraseLines(previousLineCount));
1426
- previousOutput = '';
1427
- previousWidth = getWidth(stream);
1428
- previousLineCount = 0;
1429
- };
1247
+ const processOk = function (process) {
1248
+ return process &&
1249
+ typeof process === 'object' &&
1250
+ typeof process.removeListener === 'function' &&
1251
+ typeof process.emit === 'function' &&
1252
+ typeof process.reallyExit === 'function' &&
1253
+ typeof process.listeners === 'function' &&
1254
+ typeof process.kill === 'function' &&
1255
+ typeof process.pid === 'number' &&
1256
+ typeof process.on === 'function'
1257
+ };
1430
1258
 
1431
- render.done = () => {
1432
- previousOutput = '';
1433
- previousWidth = getWidth(stream);
1434
- previousLineCount = 0;
1259
+ // some kind of non-node environment, just no-op
1260
+ /* istanbul ignore if */
1261
+ if (!processOk(process$1)) {
1262
+ signalExit$1.exports = function () {};
1263
+ } else {
1264
+ var assert = require$$0;
1265
+ var signals = signals$1.exports;
1266
+ var isWin = /^win/i.test(process$1.platform);
1435
1267
 
1436
- if (!showCursor) {
1437
- cliCursor.show();
1438
- }
1439
- };
1268
+ var EE = require$$2;
1269
+ /* istanbul ignore if */
1270
+ if (typeof EE !== 'function') {
1271
+ EE = EE.EventEmitter;
1272
+ }
1440
1273
 
1441
- return render;
1442
- }
1274
+ var emitter;
1275
+ if (process$1.__signal_exit_emitter__) {
1276
+ emitter = process$1.__signal_exit_emitter__;
1277
+ } else {
1278
+ emitter = process$1.__signal_exit_emitter__ = new EE();
1279
+ emitter.count = 0;
1280
+ emitter.emitted = {};
1281
+ }
1443
1282
 
1444
- createLogUpdate(process$2.stdout);
1283
+ // Because this emitter is a global, we have to check to see if a
1284
+ // previous version of this library failed to enable infinite listeners.
1285
+ // I know what you're about to say. But literally everything about
1286
+ // signal-exit is a compromise with evil. Get used to it.
1287
+ if (!emitter.infinite) {
1288
+ emitter.setMaxListeners(Infinity);
1289
+ emitter.infinite = true;
1290
+ }
1445
1291
 
1446
- createLogUpdate(process$2.stderr);
1292
+ signalExit$1.exports = function (cb, opts) {
1293
+ /* istanbul ignore if */
1294
+ if (!processOk(commonjsGlobal.process)) {
1295
+ return
1296
+ }
1297
+ assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler');
1447
1298
 
1448
- const DURATION_LONG = 300;
1449
- const MAX_HEIGHT = 20;
1450
- const spinnerMap = new WeakMap();
1451
- const outputMap = new WeakMap();
1452
- const pointer = c.yellow(F_POINTER);
1453
- const skipped = c.yellow(F_DOWN);
1454
- function divider(text, left, right) {
1455
- let length = process.stdout.columns;
1456
- if (!length || isNaN(length))
1457
- length = 10;
1458
- if (text) {
1459
- const textLength = stripAnsi(text).length;
1460
- if (left == null && right != null) {
1461
- left = length - textLength - right;
1462
- } else {
1463
- left = left ?? Math.floor((length - textLength) / 2);
1464
- right = length - textLength - left;
1299
+ if (loaded === false) {
1300
+ load();
1465
1301
  }
1466
- left = Math.max(0, left);
1467
- right = Math.max(0, right);
1468
- return `${F_LONG_DASH.repeat(left)}${text}${F_LONG_DASH.repeat(right)}`;
1469
- }
1470
- return F_LONG_DASH.repeat(length);
1471
- }
1472
- function formatTestPath(root, path) {
1473
- var _a;
1474
- if (isAbsolute(path))
1475
- path = relative(root, path);
1476
- const dir = dirname(path);
1477
- const ext = ((_a = path.match(/(\.(spec|test)\.[cm]?[tj]sx?)$/)) == null ? void 0 : _a[0]) || "";
1478
- const base = basename(path, ext);
1479
- return slash(c.dim(`${dir}/`) + c.bold(base)) + c.dim(ext);
1480
- }
1481
- function renderSnapshotSummary(rootDir, snapshots) {
1482
- const summary = [];
1483
- if (snapshots.added)
1484
- summary.push(c.bold(c.green(`${snapshots.added} written`)));
1485
- if (snapshots.unmatched)
1486
- summary.push(c.bold(c.red(`${snapshots.unmatched} failed`)));
1487
- if (snapshots.updated)
1488
- summary.push(c.bold(c.green(`${snapshots.updated} updated `)));
1489
- if (snapshots.filesRemoved) {
1490
- if (snapshots.didUpdate)
1491
- summary.push(c.bold(c.green(`${snapshots.filesRemoved} files removed `)));
1492
- else
1493
- summary.push(c.bold(c.yellow(`${snapshots.filesRemoved} files obsolete `)));
1494
- }
1495
- if (snapshots.filesRemovedList && snapshots.filesRemovedList.length) {
1496
- const [head, ...tail] = snapshots.filesRemovedList;
1497
- summary.push(`${c.gray(F_DOWN_RIGHT)} ${formatTestPath(rootDir, head)}`);
1498
- tail.forEach((key) => {
1499
- summary.push(` ${c.gray(F_DOT)} ${formatTestPath(rootDir, key)}`);
1500
- });
1501
- }
1502
- if (snapshots.unchecked) {
1503
- if (snapshots.didUpdate)
1504
- summary.push(c.bold(c.green(`${snapshots.unchecked} removed`)));
1505
- else
1506
- summary.push(c.bold(c.yellow(`${snapshots.unchecked} obsolete`)));
1507
- snapshots.uncheckedKeysByFile.forEach((uncheckedFile) => {
1508
- summary.push(`${c.gray(F_DOWN_RIGHT)} ${formatTestPath(rootDir, uncheckedFile.filePath)}`);
1509
- uncheckedFile.keys.forEach((key) => summary.push(` ${c.gray(F_DOT)} ${key}`));
1510
- });
1511
- }
1512
- return summary;
1513
- }
1514
- function getStateString(tasks, name = "tests") {
1515
- if (tasks.length === 0)
1516
- return c.dim(`no ${name}`);
1517
- const passed = tasks.filter((i) => {
1518
- var _a;
1519
- return ((_a = i.result) == null ? void 0 : _a.state) === "pass";
1520
- });
1521
- const failed = tasks.filter((i) => {
1522
- var _a;
1523
- return ((_a = i.result) == null ? void 0 : _a.state) === "fail";
1524
- });
1525
- const skipped2 = tasks.filter((i) => i.mode === "skip");
1526
- const todo = tasks.filter((i) => i.mode === "todo");
1527
- return [
1528
- failed.length ? c.bold(c.red(`${failed.length} failed`)) : null,
1529
- passed.length ? c.bold(c.green(`${passed.length} passed`)) : null,
1530
- skipped2.length ? c.yellow(`${skipped2.length} skipped`) : null,
1531
- todo.length ? c.gray(`${todo.length} todo`) : null
1532
- ].filter(Boolean).join(c.dim(" | ")) + c.gray(` (${tasks.length})`);
1533
- }
1534
- function getStateSymbol(task) {
1535
- if (task.mode === "skip" || task.mode === "todo")
1536
- return skipped;
1537
- if (!task.result)
1538
- return c.gray("\xB7");
1539
- if (task.result.state === "run") {
1540
- if (task.type === "suite")
1541
- return pointer;
1542
- let spinner = spinnerMap.get(task);
1543
- if (!spinner) {
1544
- spinner = elegantSpinner();
1545
- spinnerMap.set(task, spinner);
1302
+
1303
+ var ev = 'exit';
1304
+ if (opts && opts.alwaysLast) {
1305
+ ev = 'afterexit';
1546
1306
  }
1547
- return c.yellow(spinner());
1548
- }
1549
- if (task.result.state === "pass")
1550
- return c.green(F_CHECK);
1551
- if (task.result.state === "fail") {
1552
- return task.type === "suite" ? pointer : c.red(F_CROSS);
1553
- }
1554
- return " ";
1555
- }
1556
- function renderTree(tasks, level = 0) {
1557
- var _a, _b, _c, _d;
1558
- let output = [];
1559
- for (const task of tasks) {
1560
- let delta = 1;
1561
- let suffix = task.mode === "skip" || task.mode === "todo" ? ` ${c.dim("[skipped]")}` : "";
1562
- const prefix = ` ${getStateSymbol(task)} `;
1563
- if (task.type === "suite")
1564
- suffix += c.dim(` (${getTests(task).length})`);
1565
- if ((_a = task.result) == null ? void 0 : _a.end) {
1566
- const duration = task.result.end - task.result.start;
1567
- if (duration > DURATION_LONG)
1568
- suffix += c.yellow(` ${Math.round(duration)}${c.dim("ms")}`);
1569
- }
1570
- if (task.name)
1571
- output.push(" ".repeat(level) + prefix + task.name + suffix);
1572
- else
1573
- delta = 0;
1574
- if (((_b = task.result) == null ? void 0 : _b.state) !== "pass" && outputMap.get(task) != null) {
1575
- let data = outputMap.get(task);
1576
- if (typeof data === "string") {
1577
- data = stripAnsi(data.trim().split("\n").filter(Boolean).pop());
1578
- if (data === "")
1579
- data = void 0;
1580
- }
1581
- if (data != null) {
1582
- const out = `${" ".repeat(level)}${F_RIGHT} ${data}`;
1583
- output.push(` ${c.gray(cliTruncate(out, process.stdout.columns - 3))}`);
1584
- }
1585
- }
1586
- if ((((_c = task.result) == null ? void 0 : _c.state) === "fail" || ((_d = task.result) == null ? void 0 : _d.state) === "run") && task.type === "suite" && task.tasks.length > 0)
1587
- output = output.concat(renderTree(task.tasks, level + delta));
1588
- }
1589
- return output.slice(0, MAX_HEIGHT).join("\n");
1590
- }
1591
- const createRenderer = (_tasks) => {
1592
- let tasks = _tasks;
1593
- let timer;
1594
- const stdout = process.stdout;
1595
- const log = createLogUpdate(stdout);
1596
- function update() {
1597
- log(renderTree(tasks));
1598
- }
1599
- return {
1600
- start() {
1601
- if (timer)
1602
- return this;
1603
- timer = setInterval(update, 200);
1604
- return this;
1605
- },
1606
- update(_tasks2) {
1607
- tasks = _tasks2;
1608
- update();
1609
- return this;
1610
- },
1611
- async stop() {
1612
- if (timer) {
1613
- clearInterval(timer);
1614
- timer = void 0;
1307
+
1308
+ var remove = function () {
1309
+ emitter.removeListener(ev, cb);
1310
+ if (emitter.listeners('exit').length === 0 &&
1311
+ emitter.listeners('afterexit').length === 0) {
1312
+ unload();
1615
1313
  }
1616
- log.clear();
1617
- stdout.write(`${renderTree(tasks)}
1618
- `);
1619
- return this;
1620
- },
1621
- clear() {
1622
- log.clear();
1623
- }
1624
- };
1625
- };
1626
- function getFullName(task) {
1627
- return getNames(task).join(c.dim(" > "));
1628
- }
1629
- const spinnerFrames = process.platform === "win32" ? ["-", "\\", "|", "/"] : ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
1630
- function elegantSpinner() {
1631
- let index = 0;
1632
- return () => {
1633
- index = ++index % spinnerFrames.length;
1634
- return spinnerFrames[index];
1314
+ };
1315
+ emitter.on(ev, cb);
1316
+
1317
+ return remove
1635
1318
  };
1636
- }
1637
1319
 
1638
- const isTTY = process.stdout.isTTY && !process.env.CI;
1639
- class DefaultReporter {
1640
- constructor(ctx) {
1641
- this.ctx = ctx;
1642
- this.start = 0;
1643
- this.end = 0;
1644
- this.console = globalThis.console;
1645
- this.isFirstWatchRun = true;
1646
- const mode = ctx.config.watch ? c.yellow(" DEV ") : c.cyan(" RUN ");
1647
- this.log(`${c.inverse(c.bold(mode))} ${c.gray(this.ctx.config.root)}
1648
- `);
1649
- this.start = performance.now();
1650
- }
1651
- log(...args) {
1652
- if (this.ctx.config.silent)
1653
- return;
1654
- this.console.log(...args);
1655
- }
1656
- error(...args) {
1657
- if (this.ctx.config.silent)
1658
- return;
1659
- this.console.error(...args);
1660
- }
1661
- relative(path) {
1662
- return relative(this.ctx.config.root, path);
1663
- }
1664
- onStart() {
1665
- if (isTTY) {
1666
- const files = this.ctx.state.getFiles(this.watchFilters);
1667
- if (!this.renderer)
1668
- this.renderer = createRenderer(files).start();
1669
- else
1670
- this.renderer.update(files);
1671
- }
1672
- }
1673
- onTaskUpdate(pack) {
1674
- var _a, _b, _c;
1675
- if (isTTY)
1676
- return;
1677
- const task = this.ctx.state.idMap[pack[0]];
1678
- if (task.type === "test" && ((_a = task.result) == null ? void 0 : _a.state) && ((_b = task.result) == null ? void 0 : _b.state) !== "run") {
1679
- this.log(` ${getStateSymbol(task)} ${getFullName(task)}`);
1680
- if (task.result.state === "fail")
1681
- this.log(c.red(` ${F_RIGHT} ${(_c = task.result.error) == null ? void 0 : _c.message}`));
1320
+ var unload = function unload () {
1321
+ if (!loaded || !processOk(commonjsGlobal.process)) {
1322
+ return
1682
1323
  }
1683
- }
1684
- async onFinished(files = this.ctx.state.getFiles()) {
1685
- var _a, _b;
1686
- this.end = performance.now();
1687
- await this.stopListRender();
1688
- this.log();
1689
- const suites = getSuites(files);
1690
- const tests = getTests(files);
1691
- const failedSuites = suites.filter((i) => {
1692
- var _a2;
1693
- return (_a2 = i.result) == null ? void 0 : _a2.error;
1694
- });
1695
- const failedTests = tests.filter((i) => {
1696
- var _a2;
1697
- return ((_a2 = i.result) == null ? void 0 : _a2.state) === "fail";
1324
+ loaded = false;
1325
+
1326
+ signals.forEach(function (sig) {
1327
+ try {
1328
+ process$1.removeListener(sig, sigListeners[sig]);
1329
+ } catch (er) {}
1698
1330
  });
1699
- const failedTotal = failedSuites.length + failedTests.length;
1700
- let current = 1;
1701
- const errorDivider = () => this.error(`${c.red(c.dim(divider(`[${current++}/${failedTotal}]`, void 0, 1)))}
1702
- `);
1703
- if (failedSuites.length) {
1704
- this.error(c.red(divider(c.bold(c.inverse(` Failed Suites ${failedSuites.length} `)))));
1705
- this.error();
1706
- for (const suite of failedSuites) {
1707
- this.error(c.red(`
1708
- - ${getFullName(suite)}`));
1709
- await printError((_a = suite.result) == null ? void 0 : _a.error);
1710
- errorDivider();
1711
- }
1331
+ process$1.emit = originalProcessEmit;
1332
+ process$1.reallyExit = originalProcessReallyExit;
1333
+ emitter.count -= 1;
1334
+ };
1335
+ signalExit$1.exports.unload = unload;
1336
+
1337
+ var emit = function emit (event, code, signal) {
1338
+ /* istanbul ignore if */
1339
+ if (emitter.emitted[event]) {
1340
+ return
1712
1341
  }
1713
- if (failedTests.length) {
1714
- this.error(c.red(divider(c.bold(c.inverse(` Failed Tests ${failedTests.length} `)))));
1715
- this.error();
1716
- for (const test of failedTests) {
1717
- this.error(`${c.red(c.bold(c.inverse(" FAIL ")))} ${getFullName(test)}`);
1718
- await printError((_b = test.result) == null ? void 0 : _b.error);
1719
- errorDivider();
1342
+ emitter.emitted[event] = true;
1343
+ emitter.emit(event, code, signal);
1344
+ };
1345
+
1346
+ // { <signal>: <listener fn>, ... }
1347
+ var sigListeners = {};
1348
+ signals.forEach(function (sig) {
1349
+ sigListeners[sig] = function listener () {
1350
+ /* istanbul ignore if */
1351
+ if (!processOk(commonjsGlobal.process)) {
1352
+ return
1353
+ }
1354
+ // If there are no other listeners, an exit is coming!
1355
+ // Simplest way: remove us and then re-send the signal.
1356
+ // We know that this will kill the process, so we can
1357
+ // safely emit now.
1358
+ var listeners = process$1.listeners(sig);
1359
+ if (listeners.length === emitter.count) {
1360
+ unload();
1361
+ emit('exit', null, sig);
1362
+ /* istanbul ignore next */
1363
+ emit('afterexit', null, sig);
1364
+ /* istanbul ignore next */
1365
+ if (isWin && sig === 'SIGHUP') {
1366
+ // "SIGHUP" throws an `ENOSYS` error on Windows,
1367
+ // so use a supported signal instead
1368
+ sig = 'SIGINT';
1369
+ }
1370
+ /* istanbul ignore next */
1371
+ process$1.kill(process$1.pid, sig);
1720
1372
  }
1721
- }
1722
- const executionTime = this.end - this.start;
1723
- const threadTime = tests.reduce((acc, test) => {
1724
- var _a2;
1725
- return acc + (((_a2 = test.result) == null ? void 0 : _a2.end) ? test.result.end - test.result.start : 0);
1726
- }, 0);
1727
- const padTitle = (str) => c.dim(`${str.padStart(10)} `);
1728
- const time = (time2) => {
1729
- if (time2 > 1e3)
1730
- return `${(time2 / 1e3).toFixed(2)}s`;
1731
- return `${Math.round(time2)}ms`;
1732
1373
  };
1733
- const snapshotOutput = renderSnapshotSummary(this.ctx.config.root, this.ctx.snapshot.summary);
1734
- if (snapshotOutput.length) {
1735
- this.log(snapshotOutput.map((t, i) => i === 0 ? `${padTitle("Snapshots")} ${t}` : `${padTitle("")} ${t}`).join("\n"));
1736
- if (snapshotOutput.length > 1)
1737
- this.log();
1738
- }
1739
- this.log(padTitle("Test Files"), getStateString(files));
1740
- this.log(padTitle("Tests"), getStateString(tests));
1741
- if (this.watchFilters)
1742
- this.log(padTitle("Time"), time(threadTime));
1743
- else
1744
- this.log(padTitle("Time"), time(executionTime) + c.gray(` (in thread ${time(threadTime)}, ${(executionTime / threadTime * 100).toFixed(2)}%)`));
1745
- this.log();
1746
- }
1747
- async onWatcherStart() {
1748
- await this.stopListRender();
1749
- const failed = getTests(this.ctx.state.getFiles()).filter((i) => {
1750
- var _a;
1751
- return ((_a = i.result) == null ? void 0 : _a.state) === "fail";
1374
+ });
1375
+
1376
+ signalExit$1.exports.signals = function () {
1377
+ return signals
1378
+ };
1379
+
1380
+ var loaded = false;
1381
+
1382
+ var load = function load () {
1383
+ if (loaded || !processOk(commonjsGlobal.process)) {
1384
+ return
1385
+ }
1386
+ loaded = true;
1387
+
1388
+ // This is the number of onSignalExit's that are in play.
1389
+ // It's important so that we can count the correct number of
1390
+ // listeners on signals, and don't wait for the other one to
1391
+ // handle it instead of us.
1392
+ emitter.count += 1;
1393
+
1394
+ signals = signals.filter(function (sig) {
1395
+ try {
1396
+ process$1.on(sig, sigListeners[sig]);
1397
+ return true
1398
+ } catch (er) {
1399
+ return false
1400
+ }
1752
1401
  });
1753
- if (failed.length)
1754
- this.log(`
1755
- ${c.bold(c.inverse(c.red(" FAIL ")))}${c.red(` ${failed.length} tests failed. Watching for file changes...`)}`);
1756
- else
1757
- this.log(`
1758
- ${c.bold(c.inverse(c.green(" PASS ")))}${c.green(" Waiting for file changes...")}`);
1759
- if (this.isFirstWatchRun) {
1760
- this.isFirstWatchRun = false;
1761
- this.log(c.gray("press any key to exit..."));
1402
+
1403
+ process$1.emit = processEmit;
1404
+ process$1.reallyExit = processReallyExit;
1405
+ };
1406
+ signalExit$1.exports.load = load;
1407
+
1408
+ var originalProcessReallyExit = process$1.reallyExit;
1409
+ var processReallyExit = function processReallyExit (code) {
1410
+ /* istanbul ignore if */
1411
+ if (!processOk(commonjsGlobal.process)) {
1412
+ return
1762
1413
  }
1763
- }
1764
- async onWatcherRerun(files, trigger) {
1765
- await this.stopListRender();
1766
- this.watchFilters = files;
1767
- this.console.clear();
1768
- this.log(c.blue("Re-running tests...") + c.dim(` [ ${this.relative(trigger)} ]
1769
- `));
1770
- }
1771
- async stopListRender() {
1772
- var _a;
1773
- (_a = this.renderer) == null ? void 0 : _a.stop();
1774
- this.renderer = void 0;
1775
- await new Promise((resolve) => setTimeout(resolve, 10));
1776
- }
1777
- onUserConsoleLog(log) {
1778
- var _a;
1779
- (_a = this.renderer) == null ? void 0 : _a.clear();
1780
- const task = log.taskId ? this.ctx.state.idMap[log.taskId] : void 0;
1781
- this.log(c.gray(log.type + c.dim(` | ${task ? getFullName(task) : "unknown test"}`)));
1782
- process[log.type].write(`${log.content}
1783
- `);
1784
- }
1785
- }
1414
+ process$1.exitCode = code || /* istanbul ignore next */ 0;
1415
+ emit('exit', process$1.exitCode, null);
1416
+ /* istanbul ignore next */
1417
+ emit('afterexit', process$1.exitCode, null);
1418
+ /* istanbul ignore next */
1419
+ originalProcessReallyExit.call(process$1, process$1.exitCode);
1420
+ };
1786
1421
 
1787
- class SnapshotManager {
1788
- constructor(config) {
1789
- this.config = config;
1790
- this.summary = void 0;
1791
- this.clear();
1792
- }
1793
- clear() {
1794
- this.summary = emptySummary(this.config.snapshotOptions);
1795
- }
1796
- add(result) {
1797
- addSnapshotResult(this.summary, result);
1798
- }
1799
- }
1800
- function emptySummary(options) {
1801
- const summary = {
1802
- added: 0,
1803
- failure: false,
1804
- filesAdded: 0,
1805
- filesRemoved: 0,
1806
- filesRemovedList: [],
1807
- filesUnmatched: 0,
1808
- filesUpdated: 0,
1809
- matched: 0,
1810
- total: 0,
1811
- unchecked: 0,
1812
- uncheckedKeysByFile: [],
1813
- unmatched: 0,
1814
- updated: 0,
1815
- didUpdate: options.updateSnapshot === "all"
1422
+ var originalProcessEmit = process$1.emit;
1423
+ var processEmit = function processEmit (ev, arg) {
1424
+ if (ev === 'exit' && processOk(commonjsGlobal.process)) {
1425
+ /* istanbul ignore else */
1426
+ if (arg !== undefined) {
1427
+ process$1.exitCode = arg;
1428
+ }
1429
+ var ret = originalProcessEmit.apply(this, arguments);
1430
+ /* istanbul ignore next */
1431
+ emit('exit', process$1.exitCode, null);
1432
+ /* istanbul ignore next */
1433
+ emit('afterexit', process$1.exitCode, null);
1434
+ /* istanbul ignore next */
1435
+ return ret
1436
+ } else {
1437
+ return originalProcessEmit.apply(this, arguments)
1438
+ }
1816
1439
  };
1817
- return summary;
1818
- }
1819
- function addSnapshotResult(summary, result) {
1820
- if (result.added)
1821
- summary.filesAdded++;
1822
- if (result.fileDeleted)
1823
- summary.filesRemoved++;
1824
- if (result.unmatched)
1825
- summary.filesUnmatched++;
1826
- if (result.updated)
1827
- summary.filesUpdated++;
1828
- summary.added += result.added;
1829
- summary.matched += result.matched;
1830
- summary.unchecked += result.unchecked;
1831
- if (result.uncheckedKeys && result.uncheckedKeys.length > 0) {
1832
- summary.uncheckedKeysByFile.push({
1833
- filePath: result.filepath,
1834
- keys: result.uncheckedKeys
1835
- });
1836
- }
1837
- summary.unmatched += result.unmatched;
1838
- summary.updated += result.updated;
1839
- summary.total += result.added + result.matched + result.unmatched + result.updated;
1840
1440
  }
1841
1441
 
1842
- /*
1843
- How it works:
1844
- `this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.
1845
- */
1442
+ var signalExit = signalExit$1.exports;
1846
1443
 
1847
- class Node {
1848
- value;
1849
- next;
1444
+ const restoreCursor = onetime$1(() => {
1445
+ signalExit(() => {
1446
+ process$2.stderr.write('\u001B[?25h');
1447
+ }, {alwaysLast: true});
1448
+ });
1850
1449
 
1851
- constructor(value) {
1852
- this.value = value;
1450
+ let isHidden = false;
1451
+
1452
+ const cliCursor = {};
1453
+
1454
+ cliCursor.show = (writableStream = process$2.stderr) => {
1455
+ if (!writableStream.isTTY) {
1456
+ return;
1853
1457
  }
1854
- }
1855
1458
 
1856
- class Queue {
1857
- #head;
1858
- #tail;
1859
- #size;
1459
+ isHidden = false;
1460
+ writableStream.write('\u001B[?25h');
1461
+ };
1860
1462
 
1861
- constructor() {
1862
- this.clear();
1463
+ cliCursor.hide = (writableStream = process$2.stderr) => {
1464
+ if (!writableStream.isTTY) {
1465
+ return;
1863
1466
  }
1864
1467
 
1865
- enqueue(value) {
1866
- const node = new Node(value);
1468
+ restoreCursor();
1469
+ isHidden = true;
1470
+ writableStream.write('\u001B[?25l');
1471
+ };
1867
1472
 
1868
- if (this.#head) {
1869
- this.#tail.next = node;
1870
- this.#tail = node;
1473
+ cliCursor.toggle = (force, writableStream) => {
1474
+ if (force !== undefined) {
1475
+ isHidden = force;
1476
+ }
1477
+
1478
+ if (isHidden) {
1479
+ cliCursor.show(writableStream);
1480
+ } else {
1481
+ cliCursor.hide(writableStream);
1482
+ }
1483
+ };
1484
+
1485
+ const ESCAPES = new Set([
1486
+ '\u001B',
1487
+ '\u009B',
1488
+ ]);
1489
+
1490
+ const END_CODE = 39;
1491
+ const ANSI_ESCAPE_BELL = '\u0007';
1492
+ const ANSI_CSI = '[';
1493
+ const ANSI_OSC = ']';
1494
+ const ANSI_SGR_TERMINATOR = 'm';
1495
+ const ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
1496
+
1497
+ const wrapAnsiCode = code => `${ESCAPES.values().next().value}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
1498
+ const wrapAnsiHyperlink = uri => `${ESCAPES.values().next().value}${ANSI_ESCAPE_LINK}${uri}${ANSI_ESCAPE_BELL}`;
1499
+
1500
+ // Calculate the length of words split on ' ', ignoring
1501
+ // the extra characters added by ansi escape codes
1502
+ const wordLengths = string => string.split(' ').map(character => stringWidth(character));
1503
+
1504
+ // Wrap a long word across multiple rows
1505
+ // Ansi escape codes do not count towards length
1506
+ const wrapWord = (rows, word, columns) => {
1507
+ const characters = [...word];
1508
+
1509
+ let isInsideEscape = false;
1510
+ let isInsideLinkEscape = false;
1511
+ let visible = stringWidth(stripAnsi(rows[rows.length - 1]));
1512
+
1513
+ for (const [index, character] of characters.entries()) {
1514
+ const characterLength = stringWidth(character);
1515
+
1516
+ if (visible + characterLength <= columns) {
1517
+ rows[rows.length - 1] += character;
1871
1518
  } else {
1872
- this.#head = node;
1873
- this.#tail = node;
1519
+ rows.push(character);
1520
+ visible = 0;
1874
1521
  }
1875
1522
 
1876
- this.#size++;
1877
- }
1523
+ if (ESCAPES.has(character)) {
1524
+ isInsideEscape = true;
1525
+ isInsideLinkEscape = characters.slice(index + 1).join('').startsWith(ANSI_ESCAPE_LINK);
1526
+ }
1878
1527
 
1879
- dequeue() {
1880
- const current = this.#head;
1881
- if (!current) {
1882
- return;
1528
+ if (isInsideEscape) {
1529
+ if (isInsideLinkEscape) {
1530
+ if (character === ANSI_ESCAPE_BELL) {
1531
+ isInsideEscape = false;
1532
+ isInsideLinkEscape = false;
1533
+ }
1534
+ } else if (character === ANSI_SGR_TERMINATOR) {
1535
+ isInsideEscape = false;
1536
+ }
1537
+
1538
+ continue;
1883
1539
  }
1884
1540
 
1885
- this.#head = this.#head.next;
1886
- this.#size--;
1887
- return current.value;
1888
- }
1541
+ visible += characterLength;
1889
1542
 
1890
- clear() {
1891
- this.#head = undefined;
1892
- this.#tail = undefined;
1893
- this.#size = 0;
1543
+ if (visible === columns && index < characters.length - 1) {
1544
+ rows.push('');
1545
+ visible = 0;
1546
+ }
1894
1547
  }
1895
1548
 
1896
- get size() {
1897
- return this.#size;
1549
+ // It's possible that the last row we copy over is only
1550
+ // ansi escape characters, handle this edge-case
1551
+ if (!visible && rows[rows.length - 1].length > 0 && rows.length > 1) {
1552
+ rows[rows.length - 2] += rows.pop();
1898
1553
  }
1554
+ };
1899
1555
 
1900
- * [Symbol.iterator]() {
1901
- let current = this.#head;
1556
+ // Trims spaces from a string ignoring invisible sequences
1557
+ const stringVisibleTrimSpacesRight = string => {
1558
+ const words = string.split(' ');
1559
+ let last = words.length;
1902
1560
 
1903
- while (current) {
1904
- yield current.value;
1905
- current = current.next;
1561
+ while (last > 0) {
1562
+ if (stringWidth(words[last - 1]) > 0) {
1563
+ break;
1906
1564
  }
1565
+
1566
+ last--;
1907
1567
  }
1908
- }
1909
1568
 
1910
- function pLimit(concurrency) {
1911
- if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
1912
- throw new TypeError('Expected `concurrency` to be a number from 1 and up');
1569
+ if (last === words.length) {
1570
+ return string;
1913
1571
  }
1914
1572
 
1915
- const queue = new Queue();
1916
- let activeCount = 0;
1573
+ return words.slice(0, last).join(' ') + words.slice(last).join('');
1574
+ };
1917
1575
 
1918
- const next = () => {
1919
- activeCount--;
1576
+ // The wrap-ansi module can be invoked in either 'hard' or 'soft' wrap mode
1577
+ //
1578
+ // 'hard' will never allow a string to take up more than columns characters
1579
+ //
1580
+ // 'soft' allows long words to expand past the column length
1581
+ const exec = (string, columns, options = {}) => {
1582
+ if (options.trim !== false && string.trim() === '') {
1583
+ return '';
1584
+ }
1920
1585
 
1921
- if (queue.size > 0) {
1922
- queue.dequeue()();
1923
- }
1924
- };
1586
+ let returnValue = '';
1587
+ let escapeCode;
1588
+ let escapeUrl;
1925
1589
 
1926
- const run = async (fn, resolve, args) => {
1927
- activeCount++;
1590
+ const lengths = wordLengths(string);
1591
+ let rows = [''];
1928
1592
 
1929
- const result = (async () => fn(...args))();
1593
+ for (const [index, word] of string.split(' ').entries()) {
1594
+ if (options.trim !== false) {
1595
+ rows[rows.length - 1] = rows[rows.length - 1].trimStart();
1596
+ }
1930
1597
 
1931
- resolve(result);
1598
+ let rowLength = stringWidth(rows[rows.length - 1]);
1932
1599
 
1933
- try {
1934
- await result;
1935
- } catch {}
1600
+ if (index !== 0) {
1601
+ if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
1602
+ // If we start with a new word but the current row length equals the length of the columns, add a new row
1603
+ rows.push('');
1604
+ rowLength = 0;
1605
+ }
1936
1606
 
1937
- next();
1938
- };
1607
+ if (rowLength > 0 || options.trim === false) {
1608
+ rows[rows.length - 1] += ' ';
1609
+ rowLength++;
1610
+ }
1611
+ }
1939
1612
 
1940
- const enqueue = (fn, resolve, args) => {
1941
- queue.enqueue(run.bind(undefined, fn, resolve, args));
1613
+ // In 'hard' wrap mode, the length of a line is never allowed to extend past 'columns'
1614
+ if (options.hard && lengths[index] > columns) {
1615
+ const remainingColumns = (columns - rowLength);
1616
+ const breaksStartingThisLine = 1 + Math.floor((lengths[index] - remainingColumns - 1) / columns);
1617
+ const breaksStartingNextLine = Math.floor((lengths[index] - 1) / columns);
1618
+ if (breaksStartingNextLine < breaksStartingThisLine) {
1619
+ rows.push('');
1620
+ }
1942
1621
 
1943
- (async () => {
1944
- // This function needs to wait until the next microtask before comparing
1945
- // `activeCount` to `concurrency`, because `activeCount` is updated asynchronously
1946
- // when the run function is dequeued and called. The comparison in the if-statement
1947
- // needs to happen asynchronously as well to get an up-to-date value for `activeCount`.
1948
- await Promise.resolve();
1622
+ wrapWord(rows, word, columns);
1623
+ continue;
1624
+ }
1949
1625
 
1950
- if (activeCount < concurrency && queue.size > 0) {
1951
- queue.dequeue()();
1626
+ if (rowLength + lengths[index] > columns && rowLength > 0 && lengths[index] > 0) {
1627
+ if (options.wordWrap === false && rowLength < columns) {
1628
+ wrapWord(rows, word, columns);
1629
+ continue;
1952
1630
  }
1953
- })();
1954
- };
1955
1631
 
1956
- const generator = (fn, ...args) => new Promise(resolve => {
1957
- enqueue(fn, resolve, args);
1958
- });
1632
+ rows.push('');
1633
+ }
1959
1634
 
1960
- Object.defineProperties(generator, {
1961
- activeCount: {
1962
- get: () => activeCount,
1963
- },
1964
- pendingCount: {
1965
- get: () => queue.size,
1966
- },
1967
- clearQueue: {
1968
- value: () => {
1969
- queue.clear();
1970
- },
1971
- },
1972
- });
1635
+ if (rowLength + lengths[index] > columns && options.wordWrap === false) {
1636
+ wrapWord(rows, word, columns);
1637
+ continue;
1638
+ }
1973
1639
 
1974
- return generator;
1975
- }
1640
+ rows[rows.length - 1] += word;
1641
+ }
1976
1642
 
1977
- class EndError extends Error {
1978
- constructor(value) {
1979
- super();
1980
- this.value = value;
1643
+ if (options.trim !== false) {
1644
+ rows = rows.map(row => stringVisibleTrimSpacesRight(row));
1981
1645
  }
1982
- }
1983
1646
 
1984
- // The input can also be a promise, so we await it.
1985
- const testElement = async (element, tester) => tester(await element);
1647
+ const pre = [...rows.join('\n')];
1986
1648
 
1987
- // The input can also be a promise, so we `Promise.all()` them both.
1988
- const finder = async element => {
1989
- const values = await Promise.all(element);
1990
- if (values[1] === true) {
1991
- throw new EndError(values[0]);
1992
- }
1649
+ for (const [index, character] of pre.entries()) {
1650
+ returnValue += character;
1993
1651
 
1994
- return false;
1995
- };
1652
+ if (ESCAPES.has(character)) {
1653
+ const {groups} = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`).exec(pre.slice(index).join('')) || {groups: {}};
1654
+ if (groups.code !== undefined) {
1655
+ const code = Number.parseFloat(groups.code);
1656
+ escapeCode = code === END_CODE ? undefined : code;
1657
+ } else if (groups.uri !== undefined) {
1658
+ escapeUrl = groups.uri.length === 0 ? undefined : groups.uri;
1659
+ }
1660
+ }
1996
1661
 
1997
- async function pLocate(
1998
- iterable,
1999
- tester,
2000
- {
2001
- concurrency = Number.POSITIVE_INFINITY,
2002
- preserveOrder = true,
2003
- } = {},
2004
- ) {
2005
- const limit = pLimit(concurrency);
1662
+ const code = ansiStyles.codes.get(Number(escapeCode));
2006
1663
 
2007
- // Start all the promises concurrently with optional limit.
2008
- const items = [...iterable].map(element => [element, limit(testElement, element, tester)]);
1664
+ if (pre[index + 1] === '\n') {
1665
+ if (escapeUrl) {
1666
+ returnValue += wrapAnsiHyperlink('');
1667
+ }
2009
1668
 
2010
- // Check the promises either serially or concurrently.
2011
- const checkLimit = pLimit(preserveOrder ? 1 : Number.POSITIVE_INFINITY);
1669
+ if (escapeCode && code) {
1670
+ returnValue += wrapAnsiCode(code);
1671
+ }
1672
+ } else if (character === '\n') {
1673
+ if (escapeCode && code) {
1674
+ returnValue += wrapAnsiCode(escapeCode);
1675
+ }
2012
1676
 
2013
- try {
2014
- await Promise.all(items.map(element => checkLimit(finder, element)));
2015
- } catch (error) {
2016
- if (error instanceof EndError) {
2017
- return error.value;
1677
+ if (escapeUrl) {
1678
+ returnValue += wrapAnsiHyperlink(escapeUrl);
1679
+ }
2018
1680
  }
2019
-
2020
- throw error;
2021
1681
  }
2022
- }
2023
1682
 
2024
- const typeMappings = {
2025
- directory: 'isDirectory',
2026
- file: 'isFile',
1683
+ return returnValue;
2027
1684
  };
2028
1685
 
2029
- function checkType(type) {
2030
- if (type in typeMappings) {
2031
- return;
2032
- }
2033
-
2034
- throw new Error(`Invalid type specified: ${type}`);
1686
+ // For each newline, invoke the method separately
1687
+ function wrapAnsi(string, columns, options) {
1688
+ return String(string)
1689
+ .normalize()
1690
+ .replace(/\r\n/g, '\n')
1691
+ .split('\n')
1692
+ .map(line => exec(line, columns, options))
1693
+ .join('\n');
2035
1694
  }
2036
1695
 
2037
- const matchType = (type, stat) => type === undefined || stat[typeMappings[type]]();
1696
+ const defaultTerminalHeight = 24;
2038
1697
 
2039
- async function locatePath(
2040
- paths,
2041
- {
2042
- cwd = process$2.cwd(),
2043
- type = 'file',
2044
- allowSymlinks = true,
2045
- concurrency,
2046
- preserveOrder,
2047
- } = {},
2048
- ) {
2049
- checkType(type);
1698
+ const getWidth = stream => {
1699
+ const {columns} = stream;
2050
1700
 
2051
- const statFunction = allowSymlinks ? promises.stat : promises.lstat;
1701
+ if (!columns) {
1702
+ return 80;
1703
+ }
2052
1704
 
2053
- return pLocate(paths, async path_ => {
2054
- try {
2055
- const stat = await statFunction(path.resolve(cwd, path_));
2056
- return matchType(type, stat);
2057
- } catch {
2058
- return false;
2059
- }
2060
- }, {concurrency, preserveOrder});
2061
- }
1705
+ return columns;
1706
+ };
1707
+
1708
+ const fitToTerminalHeight = (stream, text) => {
1709
+ const terminalHeight = stream.rows || defaultTerminalHeight;
1710
+ const lines = text.split('\n');
1711
+
1712
+ const toRemove = lines.length - terminalHeight;
1713
+ if (toRemove <= 0) {
1714
+ return text;
1715
+ }
2062
1716
 
2063
- const findUpStop = Symbol('findUpStop');
1717
+ return sliceAnsi(
1718
+ text,
1719
+ lines.slice(0, toRemove).join('\n').length + 1,
1720
+ text.length);
1721
+ };
2064
1722
 
2065
- async function findUpMultiple(name, options = {}) {
2066
- let directory = path.resolve(options.cwd || '');
2067
- const {root} = path.parse(directory);
2068
- const stopAt = path.resolve(directory, options.stopAt || root);
2069
- const limit = options.limit || Number.POSITIVE_INFINITY;
2070
- const paths = [name].flat();
1723
+ function createLogUpdate(stream, {showCursor = false} = {}) {
1724
+ let previousLineCount = 0;
1725
+ let previousWidth = getWidth(stream);
1726
+ let previousOutput = '';
2071
1727
 
2072
- const runMatcher = async locateOptions => {
2073
- if (typeof name !== 'function') {
2074
- return locatePath(paths, locateOptions);
1728
+ const render = (...arguments_) => {
1729
+ if (!showCursor) {
1730
+ cliCursor.hide();
2075
1731
  }
2076
1732
 
2077
- const foundPath = await name(locateOptions.cwd);
2078
- if (typeof foundPath === 'string') {
2079
- return locatePath([foundPath], locateOptions);
1733
+ let output = arguments_.join(' ') + '\n';
1734
+ output = fitToTerminalHeight(stream, output);
1735
+ const width = getWidth(stream);
1736
+ if (output === previousOutput && previousWidth === width) {
1737
+ return;
2080
1738
  }
2081
1739
 
2082
- return foundPath;
1740
+ previousOutput = output;
1741
+ previousWidth = width;
1742
+ output = wrapAnsi(output, width, {
1743
+ trim: false,
1744
+ hard: true,
1745
+ wordWrap: false,
1746
+ });
1747
+ stream.write(ansiEscapes.eraseLines(previousLineCount) + output);
1748
+ previousLineCount = output.split('\n').length;
2083
1749
  };
2084
1750
 
2085
- const matches = [];
2086
- // eslint-disable-next-line no-constant-condition
2087
- while (true) {
2088
- // eslint-disable-next-line no-await-in-loop
2089
- const foundPath = await runMatcher({...options, cwd: directory});
1751
+ render.clear = () => {
1752
+ stream.write(ansiEscapes.eraseLines(previousLineCount));
1753
+ previousOutput = '';
1754
+ previousWidth = getWidth(stream);
1755
+ previousLineCount = 0;
1756
+ };
2090
1757
 
2091
- if (foundPath === findUpStop) {
2092
- break;
2093
- }
1758
+ render.done = () => {
1759
+ previousOutput = '';
1760
+ previousWidth = getWidth(stream);
1761
+ previousLineCount = 0;
2094
1762
 
2095
- if (foundPath) {
2096
- matches.push(path.resolve(directory, foundPath));
1763
+ if (!showCursor) {
1764
+ cliCursor.show();
2097
1765
  }
1766
+ };
2098
1767
 
2099
- if (directory === stopAt || matches.length >= limit) {
2100
- break;
2101
- }
1768
+ return render;
1769
+ }
2102
1770
 
2103
- directory = path.dirname(directory);
2104
- }
1771
+ createLogUpdate(process$2.stdout);
1772
+
1773
+ createLogUpdate(process$2.stderr);
1774
+
1775
+ const DURATION_LONG = 300;
1776
+ const MAX_HEIGHT = 20;
1777
+ const spinnerMap = new WeakMap();
1778
+ const outputMap = new WeakMap();
1779
+ const pointer = c.yellow(F_POINTER);
1780
+ const skipped = c.yellow(F_DOWN);
1781
+ function divider(text, left, right) {
1782
+ let length = process.stdout.columns;
1783
+ if (!length || isNaN(length))
1784
+ length = 10;
1785
+ if (text) {
1786
+ const textLength = stripAnsi(text).length;
1787
+ if (left == null && right != null) {
1788
+ left = length - textLength - right;
1789
+ } else {
1790
+ left = left ?? Math.floor((length - textLength) / 2);
1791
+ right = length - textLength - left;
1792
+ }
1793
+ left = Math.max(0, left);
1794
+ right = Math.max(0, right);
1795
+ return `${F_LONG_DASH.repeat(left)}${text}${F_LONG_DASH.repeat(right)}`;
1796
+ }
1797
+ return F_LONG_DASH.repeat(length);
1798
+ }
1799
+ function formatTestPath(root, path) {
1800
+ var _a;
1801
+ if (isAbsolute(path))
1802
+ path = relative(root, path);
1803
+ const dir = dirname(path);
1804
+ const ext = ((_a = path.match(/(\.(spec|test)\.[cm]?[tj]sx?)$/)) == null ? void 0 : _a[0]) || "";
1805
+ const base = basename(path, ext);
1806
+ return slash(c.dim(`${dir}/`) + c.bold(base)) + c.dim(ext);
1807
+ }
1808
+ function renderSnapshotSummary(rootDir, snapshots) {
1809
+ const summary = [];
1810
+ if (snapshots.added)
1811
+ summary.push(c.bold(c.green(`${snapshots.added} written`)));
1812
+ if (snapshots.unmatched)
1813
+ summary.push(c.bold(c.red(`${snapshots.unmatched} failed`)));
1814
+ if (snapshots.updated)
1815
+ summary.push(c.bold(c.green(`${snapshots.updated} updated `)));
1816
+ if (snapshots.filesRemoved) {
1817
+ if (snapshots.didUpdate)
1818
+ summary.push(c.bold(c.green(`${snapshots.filesRemoved} files removed `)));
1819
+ else
1820
+ summary.push(c.bold(c.yellow(`${snapshots.filesRemoved} files obsolete `)));
1821
+ }
1822
+ if (snapshots.filesRemovedList && snapshots.filesRemovedList.length) {
1823
+ const [head, ...tail] = snapshots.filesRemovedList;
1824
+ summary.push(`${c.gray(F_DOWN_RIGHT)} ${formatTestPath(rootDir, head)}`);
1825
+ tail.forEach((key) => {
1826
+ summary.push(` ${c.gray(F_DOT)} ${formatTestPath(rootDir, key)}`);
1827
+ });
1828
+ }
1829
+ if (snapshots.unchecked) {
1830
+ if (snapshots.didUpdate)
1831
+ summary.push(c.bold(c.green(`${snapshots.unchecked} removed`)));
1832
+ else
1833
+ summary.push(c.bold(c.yellow(`${snapshots.unchecked} obsolete`)));
1834
+ snapshots.uncheckedKeysByFile.forEach((uncheckedFile) => {
1835
+ summary.push(`${c.gray(F_DOWN_RIGHT)} ${formatTestPath(rootDir, uncheckedFile.filePath)}`);
1836
+ uncheckedFile.keys.forEach((key) => summary.push(` ${c.gray(F_DOT)} ${key}`));
1837
+ });
1838
+ }
1839
+ return summary;
1840
+ }
1841
+ function getStateString(tasks, name = "tests") {
1842
+ if (tasks.length === 0)
1843
+ return c.dim(`no ${name}`);
1844
+ const passed = tasks.filter((i) => {
1845
+ var _a;
1846
+ return ((_a = i.result) == null ? void 0 : _a.state) === "pass";
1847
+ });
1848
+ const failed = tasks.filter((i) => {
1849
+ var _a;
1850
+ return ((_a = i.result) == null ? void 0 : _a.state) === "fail";
1851
+ });
1852
+ const skipped2 = tasks.filter((i) => i.mode === "skip");
1853
+ const todo = tasks.filter((i) => i.mode === "todo");
1854
+ return [
1855
+ failed.length ? c.bold(c.red(`${failed.length} failed`)) : null,
1856
+ passed.length ? c.bold(c.green(`${passed.length} passed`)) : null,
1857
+ skipped2.length ? c.yellow(`${skipped2.length} skipped`) : null,
1858
+ todo.length ? c.gray(`${todo.length} todo`) : null
1859
+ ].filter(Boolean).join(c.dim(" | ")) + c.gray(` (${tasks.length})`);
1860
+ }
1861
+ function getStateSymbol(task) {
1862
+ if (task.mode === "skip" || task.mode === "todo")
1863
+ return skipped;
1864
+ if (!task.result)
1865
+ return c.gray("\xB7");
1866
+ if (task.result.state === "run") {
1867
+ if (task.type === "suite")
1868
+ return pointer;
1869
+ let spinner = spinnerMap.get(task);
1870
+ if (!spinner) {
1871
+ spinner = elegantSpinner();
1872
+ spinnerMap.set(task, spinner);
1873
+ }
1874
+ return c.yellow(spinner());
1875
+ }
1876
+ if (task.result.state === "pass")
1877
+ return c.green(F_CHECK);
1878
+ if (task.result.state === "fail") {
1879
+ return task.type === "suite" ? pointer : c.red(F_CROSS);
1880
+ }
1881
+ return " ";
1882
+ }
1883
+ function renderTree(tasks, level = 0) {
1884
+ var _a, _b, _c, _d;
1885
+ let output = [];
1886
+ for (const task of tasks) {
1887
+ let suffix = "";
1888
+ const prefix = ` ${getStateSymbol(task)} `;
1889
+ if (task.mode === "skip" || task.mode === "todo")
1890
+ suffix += ` ${c.dim("[skipped]")}`;
1891
+ if (task.type === "suite")
1892
+ suffix += c.dim(` (${getTests(task).length})`);
1893
+ if ((_a = task.result) == null ? void 0 : _a.end) {
1894
+ const duration = task.result.end - task.result.start;
1895
+ if (duration > DURATION_LONG)
1896
+ suffix += c.yellow(` ${Math.round(duration)}${c.dim("ms")}`);
1897
+ }
1898
+ output.push(" ".repeat(level) + prefix + task.name + suffix);
1899
+ if (((_b = task.result) == null ? void 0 : _b.state) !== "pass" && outputMap.get(task) != null) {
1900
+ let data = outputMap.get(task);
1901
+ if (typeof data === "string") {
1902
+ data = stripAnsi(data.trim().split("\n").filter(Boolean).pop());
1903
+ if (data === "")
1904
+ data = void 0;
1905
+ }
1906
+ if (data != null) {
1907
+ const out = `${" ".repeat(level)}${F_RIGHT} ${data}`;
1908
+ output.push(` ${c.gray(cliTruncate(out, process.stdout.columns - 3))}`);
1909
+ }
1910
+ }
1911
+ if ((((_c = task.result) == null ? void 0 : _c.state) === "fail" || ((_d = task.result) == null ? void 0 : _d.state) === "run") && task.type === "suite" && task.tasks.length > 0)
1912
+ output = output.concat(renderTree(task.tasks, level + 1));
1913
+ }
1914
+ return output.slice(0, MAX_HEIGHT).join("\n");
1915
+ }
1916
+ const createRenderer = (_tasks) => {
1917
+ let tasks = _tasks;
1918
+ let timer;
1919
+ const stdout = process.stdout;
1920
+ const log = createLogUpdate(stdout);
1921
+ function update() {
1922
+ log(renderTree(tasks));
1923
+ }
1924
+ return {
1925
+ start() {
1926
+ if (timer)
1927
+ return this;
1928
+ timer = setInterval(update, 200);
1929
+ return this;
1930
+ },
1931
+ update(_tasks2) {
1932
+ tasks = _tasks2;
1933
+ update();
1934
+ return this;
1935
+ },
1936
+ async stop() {
1937
+ if (timer) {
1938
+ clearInterval(timer);
1939
+ timer = void 0;
1940
+ }
1941
+ log.clear();
1942
+ stdout.write(`${renderTree(tasks)}
1943
+ `);
1944
+ return this;
1945
+ },
1946
+ clear() {
1947
+ log.clear();
1948
+ }
1949
+ };
1950
+ };
1951
+ function getFullName(task) {
1952
+ return getNames(task).join(c.dim(" > "));
1953
+ }
1954
+ const spinnerFrames = process.platform === "win32" ? ["-", "\\", "|", "/"] : ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
1955
+ function elegantSpinner() {
1956
+ let index = 0;
1957
+ return () => {
1958
+ index = ++index % spinnerFrames.length;
1959
+ return spinnerFrames[index];
1960
+ };
1961
+ }
2105
1962
 
2106
- return matches;
1963
+ const isTTY = process.stdout.isTTY && !process.env.CI;
1964
+ class ConsoleReporter {
1965
+ constructor(ctx) {
1966
+ this.ctx = ctx;
1967
+ this.start = 0;
1968
+ this.end = 0;
1969
+ this.console = globalThis.console;
1970
+ this.isFirstWatchRun = true;
1971
+ const mode = ctx.config.watch ? c.yellow(" DEV ") : c.cyan(" RUN ");
1972
+ this.log(`${c.inverse(c.bold(mode))} ${c.gray(this.ctx.config.root)}
1973
+ `);
1974
+ this.start = performance.now();
1975
+ }
1976
+ log(...args) {
1977
+ if (this.ctx.config.silent)
1978
+ return;
1979
+ this.console.log(...args);
1980
+ }
1981
+ error(...args) {
1982
+ if (this.ctx.config.silent)
1983
+ return;
1984
+ this.console.error(...args);
1985
+ }
1986
+ relative(path) {
1987
+ return relative(this.ctx.config.root, path);
1988
+ }
1989
+ onStart() {
1990
+ if (isTTY) {
1991
+ const files = this.ctx.state.getFiles(this.watchFilters);
1992
+ if (!this.renderer)
1993
+ this.renderer = createRenderer(files).start();
1994
+ else
1995
+ this.renderer.update(files);
1996
+ }
1997
+ }
1998
+ onTaskUpdate(pack) {
1999
+ var _a, _b, _c;
2000
+ if (isTTY)
2001
+ return;
2002
+ const task = this.ctx.state.idMap[pack[0]];
2003
+ if (task.type === "test" && ((_a = task.result) == null ? void 0 : _a.state) && ((_b = task.result) == null ? void 0 : _b.state) !== "run") {
2004
+ this.log(` ${getStateSymbol(task)} ${getFullName(task)}`);
2005
+ if (task.result.state === "fail")
2006
+ this.log(c.red(` ${F_RIGHT} ${(_c = task.result.error) == null ? void 0 : _c.message}`));
2007
+ }
2008
+ }
2009
+ async onFinished(files = this.ctx.state.getFiles()) {
2010
+ var _a, _b;
2011
+ this.end = performance.now();
2012
+ await this.stopListRender();
2013
+ this.log();
2014
+ const suites = getSuites(files);
2015
+ const tests = getTests(files);
2016
+ const failedSuites = suites.filter((i) => {
2017
+ var _a2;
2018
+ return (_a2 = i.result) == null ? void 0 : _a2.error;
2019
+ });
2020
+ const failedTests = tests.filter((i) => {
2021
+ var _a2;
2022
+ return ((_a2 = i.result) == null ? void 0 : _a2.state) === "fail";
2023
+ });
2024
+ const failedTotal = failedSuites.length + failedTests.length;
2025
+ let current = 1;
2026
+ const errorDivider = () => this.error(`${c.red(c.dim(divider(`[${current++}/${failedTotal}]`, void 0, 1)))}
2027
+ `);
2028
+ if (failedSuites.length) {
2029
+ this.error(c.red(divider(c.bold(c.inverse(` Failed Suites ${failedSuites.length} `)))));
2030
+ this.error();
2031
+ for (const suite of failedSuites) {
2032
+ this.error(c.red(`
2033
+ - ${getFullName(suite)}`));
2034
+ await printError((_a = suite.result) == null ? void 0 : _a.error);
2035
+ errorDivider();
2036
+ }
2037
+ }
2038
+ if (failedTests.length) {
2039
+ this.error(c.red(divider(c.bold(c.inverse(` Failed Tests ${failedTests.length} `)))));
2040
+ this.error();
2041
+ for (const test of failedTests) {
2042
+ this.error(`${c.red(c.bold(c.inverse(" FAIL ")))} ${getFullName(test)}`);
2043
+ await printError((_b = test.result) == null ? void 0 : _b.error);
2044
+ errorDivider();
2045
+ }
2046
+ }
2047
+ const executionTime = this.end - this.start;
2048
+ const threadTime = tests.reduce((acc, test) => {
2049
+ var _a2;
2050
+ return acc + (((_a2 = test.result) == null ? void 0 : _a2.end) ? test.result.end - test.result.start : 0);
2051
+ }, 0);
2052
+ const padTitle = (str) => c.dim(`${str.padStart(10)} `);
2053
+ const time = (time2) => {
2054
+ if (time2 > 1e3)
2055
+ return `${(time2 / 1e3).toFixed(2)}s`;
2056
+ return `${Math.round(time2)}ms`;
2057
+ };
2058
+ const snapshotOutput = renderSnapshotSummary(this.ctx.config.root, this.ctx.snapshot.summary);
2059
+ if (snapshotOutput.length) {
2060
+ this.log(snapshotOutput.map((t, i) => i === 0 ? `${padTitle("Snapshots")} ${t}` : `${padTitle("")} ${t}`).join("\n"));
2061
+ if (snapshotOutput.length > 1)
2062
+ this.log();
2063
+ }
2064
+ this.log(padTitle("Test Files"), getStateString(files));
2065
+ this.log(padTitle("Tests"), getStateString(tests));
2066
+ if (this.watchFilters)
2067
+ this.log(padTitle("Time"), time(threadTime));
2068
+ else
2069
+ this.log(padTitle("Time"), time(executionTime) + c.gray(` (in thread ${time(threadTime)}, ${(executionTime / threadTime * 100).toFixed(2)}%)`));
2070
+ this.log();
2071
+ }
2072
+ async onWatcherStart() {
2073
+ await this.stopListRender();
2074
+ const failed = getTests(this.ctx.state.getFiles()).filter((i) => {
2075
+ var _a;
2076
+ return ((_a = i.result) == null ? void 0 : _a.state) === "fail";
2077
+ });
2078
+ if (failed.length)
2079
+ this.log(`
2080
+ ${c.bold(c.inverse(c.red(" FAIL ")))}${c.red(` ${failed.length} tests failed. Watching for file changes...`)}`);
2081
+ else
2082
+ this.log(`
2083
+ ${c.bold(c.inverse(c.green(" PASS ")))}${c.green(" Waiting for file changes...")}`);
2084
+ if (this.isFirstWatchRun) {
2085
+ this.isFirstWatchRun = false;
2086
+ this.log(c.gray("press any key to exit..."));
2087
+ }
2088
+ }
2089
+ async onWatcherRerun(files, trigger) {
2090
+ await this.stopListRender();
2091
+ this.watchFilters = files;
2092
+ this.console.clear();
2093
+ this.log(c.blue("Re-running tests...") + c.dim(` [ ${this.relative(trigger)} ]
2094
+ `));
2095
+ }
2096
+ async stopListRender() {
2097
+ var _a;
2098
+ (_a = this.renderer) == null ? void 0 : _a.stop();
2099
+ this.renderer = void 0;
2100
+ await new Promise((resolve) => setTimeout(resolve, 10));
2101
+ }
2102
+ onUserConsoleLog(log) {
2103
+ var _a;
2104
+ (_a = this.renderer) == null ? void 0 : _a.clear();
2105
+ const task = log.taskId ? this.ctx.state.idMap[log.taskId] : void 0;
2106
+ this.log(c.gray(log.type + c.dim(` | ${task ? getFullName(task) : "unknown test"}`)));
2107
+ process[log.type].write(`${log.content}
2108
+ `);
2109
+ }
2107
2110
  }
2108
2111
 
2109
- async function findUp(name, options = {}) {
2110
- const matches = await findUpMultiple(name, {...options, limit: 1});
2111
- return matches[0];
2112
+ class StateManager {
2113
+ constructor() {
2114
+ this.filesMap = {};
2115
+ this.idMap = {};
2116
+ this.taskFileMap = new WeakMap();
2117
+ }
2118
+ getFiles(keys) {
2119
+ if (keys)
2120
+ return keys.map((key) => this.filesMap[key]);
2121
+ return Object.values(this.filesMap);
2122
+ }
2123
+ collectFiles(files) {
2124
+ files.forEach((file) => {
2125
+ this.filesMap[file.filepath] = file;
2126
+ this.updateId(file);
2127
+ });
2128
+ }
2129
+ updateId(task) {
2130
+ if (this.idMap[task.id] === task)
2131
+ return;
2132
+ this.idMap[task.id] = task;
2133
+ if (task.type === "suite") {
2134
+ task.tasks.forEach((task2) => {
2135
+ this.updateId(task2);
2136
+ });
2137
+ }
2138
+ }
2139
+ updateTasks(packs) {
2140
+ for (const [id, result] of packs) {
2141
+ if (this.idMap[id])
2142
+ this.idMap[id].result = result;
2143
+ }
2144
+ }
2112
2145
  }
2113
2146
 
2114
2147
  var __defProp$1 = Object.defineProperty;
@@ -2127,16 +2160,7 @@ var __spreadValues$1 = (a, b) => {
2127
2160
  }
2128
2161
  return a;
2129
2162
  };
2130
- const configFiles = [
2131
- "vitest.config.ts",
2132
- "vitest.config.js",
2133
- "vitest.config.mjs",
2134
- "vite.config.ts",
2135
- "vite.config.js",
2136
- "vite.config.mjs"
2137
- ];
2138
- async function initViteServer(options = {}) {
2139
- var _a, _b;
2163
+ async function initVitest(options = {}) {
2140
2164
  const root = resolve(options.root || process.cwd());
2141
2165
  process.chdir(root);
2142
2166
  if (options.dom)
@@ -2145,13 +2169,27 @@ async function initViteServer(options = {}) {
2145
2169
  const resolved = __spreadValues$1({}, options);
2146
2170
  resolved.config = configPath;
2147
2171
  resolved.root = root;
2148
- if (options.cliFilters)
2149
- resolved.cliFilters = toArray(options.cliFilters);
2150
2172
  const server = await createServer({
2151
2173
  root,
2152
2174
  logLevel: "error",
2153
2175
  clearScreen: false,
2154
2176
  configFile: resolved.config,
2177
+ plugins: [
2178
+ {
2179
+ name: "vitest",
2180
+ configResolved(viteConfig) {
2181
+ resolveConfig(resolved, viteConfig);
2182
+ },
2183
+ async configureServer(server2) {
2184
+ if (resolved.api)
2185
+ server2.middlewares.use((await import('./middleware-fe2b1f7f.js')).default());
2186
+ }
2187
+ }
2188
+ ],
2189
+ server: {
2190
+ open: options.open,
2191
+ strictPort: true
2192
+ },
2155
2193
  optimizeDeps: {
2156
2194
  exclude: [
2157
2195
  "vitest"
@@ -2159,7 +2197,23 @@ async function initViteServer(options = {}) {
2159
2197
  }
2160
2198
  });
2161
2199
  await server.pluginContainer.buildStart({});
2162
- Object.assign(resolved, server.config.test);
2200
+ if (typeof resolved.api === "number")
2201
+ await server.listen(resolved.api);
2202
+ const ctx = {
2203
+ server,
2204
+ config: resolved,
2205
+ state: new StateManager(),
2206
+ snapshot: new SnapshotManager(resolved),
2207
+ reporters: toArray(resolved.reporters),
2208
+ console: globalThis.console
2209
+ };
2210
+ if (!ctx.reporters.length)
2211
+ ctx.reporters.push(new ConsoleReporter(ctx));
2212
+ return ctx;
2213
+ }
2214
+ function resolveConfig(resolved, viteConfig) {
2215
+ var _a, _b;
2216
+ Object.assign(resolved, viteConfig.test);
2163
2217
  resolved.depsInline = ((_a = resolved.deps) == null ? void 0 : _a.inline) || [];
2164
2218
  resolved.depsExternal = ((_b = resolved.deps) == null ? void 0 : _b.external) || [];
2165
2219
  resolved.environment = resolved.environment || "node";
@@ -2176,11 +2230,9 @@ async function initViteServer(options = {}) {
2176
2230
  resolved.maxThreads = parseInt(process.env.VITEST_MAX_THREADS);
2177
2231
  if (process.env.VITEST_MIN_THREADS)
2178
2232
  resolved.minThreads = parseInt(process.env.VITEST_MIN_THREADS);
2179
- resolved.setupFiles = Array.from(resolved.setupFiles || []).map((i) => resolve(root, i));
2180
- return {
2181
- server,
2182
- config: resolved
2183
- };
2233
+ resolved.setupFiles = Array.from(resolved.setupFiles || []).map((i) => resolve(resolved.root, i));
2234
+ if (resolved.api === true)
2235
+ resolved.api = defaultPort;
2184
2236
  }
2185
2237
 
2186
2238
  async function transformRequest(server, id) {
@@ -2255,7 +2307,6 @@ function createChannel(ctx) {
2255
2307
  const port = channel.port2;
2256
2308
  const workerPort = channel.port1;
2257
2309
  port.on("message", async ({ id, method, args = [] }) => {
2258
- var _a, _b, _c, _d, _e, _f;
2259
2310
  async function send(fn) {
2260
2311
  try {
2261
2312
  port.postMessage({ id, result: await fn() });
@@ -2264,20 +2315,32 @@ function createChannel(ctx) {
2264
2315
  }
2265
2316
  }
2266
2317
  switch (method) {
2318
+ case "processExit":
2319
+ process.exit(args[0] || 1);
2320
+ return;
2267
2321
  case "snapshotSaved":
2268
2322
  return send(() => ctx.snapshot.add(args[0]));
2269
2323
  case "fetch":
2270
2324
  return send(() => transformRequest(ctx.server, ...args));
2271
2325
  case "onCollected":
2272
2326
  ctx.state.collectFiles(args[0]);
2273
- (_b = (_a = ctx.reporter).onStart) == null ? void 0 : _b.call(_a, args[0].map((i) => i.filepath));
2327
+ ctx.reporters.forEach((r) => {
2328
+ var _a;
2329
+ return (_a = r.onStart) == null ? void 0 : _a.call(r, args[0].map((i) => i.filepath));
2330
+ });
2274
2331
  return;
2275
2332
  case "onTaskUpdate":
2276
2333
  ctx.state.updateTasks([args[0]]);
2277
- (_d = (_c = ctx.reporter).onTaskUpdate) == null ? void 0 : _d.call(_c, args[0]);
2334
+ ctx.reporters.forEach((r) => {
2335
+ var _a;
2336
+ return (_a = r.onTaskUpdate) == null ? void 0 : _a.call(r, args[0]);
2337
+ });
2278
2338
  return;
2279
2339
  case "log":
2280
- (_f = (_e = ctx.reporter).onUserConsoleLog) == null ? void 0 : _f.call(_e, args[0]);
2340
+ ctx.reporters.forEach((r) => {
2341
+ var _a;
2342
+ return (_a = r.onUserConsoleLog) == null ? void 0 : _a.call(r, args[0]);
2343
+ });
2281
2344
  return;
2282
2345
  }
2283
2346
  console.error("Unhandled message", method, args);
@@ -2304,9 +2367,11 @@ async function globTestFiles(config) {
2304
2367
 
2305
2368
  const WATCHER_DEBOUNCE = 50;
2306
2369
  async function startWatcher(ctx, pool) {
2307
- var _a;
2308
- const { reporter, server } = ctx;
2309
- (_a = reporter.onWatcherStart) == null ? void 0 : _a.call(reporter);
2370
+ const { server } = ctx;
2371
+ ctx.reporters.forEach((r) => {
2372
+ var _a;
2373
+ return (_a = r.onWatcherStart) == null ? void 0 : _a.call(r);
2374
+ });
2310
2375
  let timer;
2311
2376
  const changedTests = new Set();
2312
2377
  const seen = new Set();
@@ -2344,8 +2409,8 @@ async function startWatcher(ctx, pool) {
2344
2409
  }
2345
2410
  isFirstRun = false;
2346
2411
  ctx.state.getFiles().forEach((file) => {
2347
- var _a2;
2348
- if (((_a2 = file.result) == null ? void 0 : _a2.state) === "fail")
2412
+ var _a;
2413
+ if (((_a = file.result) == null ? void 0 : _a.state) === "fail")
2349
2414
  changedTests.add(file.filepath);
2350
2415
  });
2351
2416
  const invalidates = Array.from(seen);
@@ -2359,11 +2424,19 @@ async function startWatcher(ctx, pool) {
2359
2424
  }, WATCHER_DEBOUNCE);
2360
2425
  }
2361
2426
  async function start(tests, id, invalidates) {
2362
- var _a2, _b, _c;
2363
- await ((_a2 = reporter.onWatcherRerun) == null ? void 0 : _a2.call(reporter, tests, id));
2427
+ await Promise.all(ctx.reporters.map((r) => {
2428
+ var _a;
2429
+ return (_a = r.onWatcherRerun) == null ? void 0 : _a.call(r, tests, id);
2430
+ }));
2364
2431
  await pool.runTestFiles(tests, invalidates);
2365
- await ((_b = reporter.onFinished) == null ? void 0 : _b.call(reporter, ctx.state.getFiles(tests)));
2366
- await ((_c = reporter.onWatcherStart) == null ? void 0 : _c.call(reporter));
2432
+ await Promise.all(ctx.reporters.map((r) => {
2433
+ var _a;
2434
+ return (_a = r.onFinished) == null ? void 0 : _a.call(r, ctx.state.getFiles(tests));
2435
+ }));
2436
+ await Promise.all(ctx.reporters.map((r) => {
2437
+ var _a;
2438
+ return (_a = r.onWatcherStart) == null ? void 0 : _a.call(r);
2439
+ }));
2367
2440
  }
2368
2441
  if (process.stdin.isTTY) {
2369
2442
  readline.emitKeypressEvents(process.stdin);
@@ -2399,7 +2472,6 @@ function getAffectedTests(ctx, id, set = new Set(), seen = new Set()) {
2399
2472
  }
2400
2473
 
2401
2474
  async function start(ctx) {
2402
- var _a, _b;
2403
2475
  const { config } = ctx;
2404
2476
  const testFilepaths = await globTestFiles(config);
2405
2477
  if (!testFilepaths.length) {
@@ -2411,48 +2483,16 @@ async function start(ctx) {
2411
2483
  await pool.runTestFiles(testFilepaths);
2412
2484
  if (hasFailed(ctx.state.getFiles()))
2413
2485
  process.exitCode = 1;
2414
- await ((_b = (_a = ctx.reporter).onFinished) == null ? void 0 : _b.call(_a, ctx.state.getFiles()));
2486
+ await Promise.all(ctx.reporters.map((r) => {
2487
+ var _a;
2488
+ return (_a = r.onFinished) == null ? void 0 : _a.call(r, ctx.state.getFiles());
2489
+ }));
2415
2490
  if (config.watch)
2416
2491
  await startWatcher(ctx, pool);
2417
2492
  else
2418
2493
  await pool.close();
2419
2494
  }
2420
2495
 
2421
- class StateManager {
2422
- constructor() {
2423
- this.filesMap = {};
2424
- this.idMap = {};
2425
- this.taskFileMap = new WeakMap();
2426
- }
2427
- getFiles(keys) {
2428
- if (keys)
2429
- return keys.map((key) => this.filesMap[key]);
2430
- return Object.values(this.filesMap);
2431
- }
2432
- collectFiles(files) {
2433
- files.forEach((file) => {
2434
- this.filesMap[file.filepath] = file;
2435
- this.updateId(file);
2436
- });
2437
- }
2438
- updateId(task) {
2439
- if (this.idMap[task.id] === task)
2440
- return;
2441
- this.idMap[task.id] = task;
2442
- if (task.type === "suite") {
2443
- task.tasks.forEach((task2) => {
2444
- this.updateId(task2);
2445
- });
2446
- }
2447
- }
2448
- updateTasks(packs) {
2449
- for (const [id, result] of packs) {
2450
- if (this.idMap[id])
2451
- this.idMap[id].result = result;
2452
- }
2453
- }
2454
- }
2455
-
2456
2496
  var __defProp = Object.defineProperty;
2457
2497
  var __defProps = Object.defineProperties;
2458
2498
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
@@ -2473,7 +2513,7 @@ var __spreadValues = (a, b) => {
2473
2513
  };
2474
2514
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
2475
2515
  const cli = cac("vitest");
2476
- cli.version(version).option("-r, --root <path>", "root path").option("-c, --config <path>", "path to config file").option("-u, --update", "update snapshot").option("-w, --watch", "watch mode").option("--threads", "enabled threads", { default: true }).option("--silent", "silent").option("--global", "inject apis globally").option("--dom", "mock browser api with happy-dom").option("--environment <env>", "runner environment", {
2516
+ cli.version(version).option("-r, --root <path>", "root path").option("-c, --config <path>", "path to config file").option("-u, --update", "update snapshot").option("-w, --watch", "watch mode").option("-o, --open", "open Vitest UI").option("--api", "listen to port and serve API").option("--threads", "enabled threads", { default: true }).option("--silent", "silent").option("--global", "inject apis globally").option("--dom", "mock browser api with happy-dom").option("--environment <env>", "runner environment", {
2477
2517
  default: "node"
2478
2518
  }).help();
2479
2519
  cli.command("run [...filters]").action(run);
@@ -2493,23 +2533,15 @@ async function run(cliFilters, argv) {
2493
2533
  console.log(c.magenta(c.bold("\nVitest is in closed beta exclusively for Sponsors")));
2494
2534
  console.log(c.yellow("Learn more at https://vitest.dev\n"));
2495
2535
  }
2496
- const { config, server } = await initViteServer(__spreadProps(__spreadValues({}, argv), { cliFilters }));
2497
- const ctx = process.__vitest__ = {
2498
- server,
2499
- config,
2500
- state: new StateManager(),
2501
- snapshot: new SnapshotManager(config),
2502
- reporter: config.reporter,
2503
- console: globalThis.console
2504
- };
2505
- ctx.reporter = ctx.reporter || new DefaultReporter(ctx);
2536
+ const ctx = await initVitest(__spreadProps(__spreadValues({}, argv), { cliFilters }));
2537
+ process.__vitest__ = ctx;
2506
2538
  try {
2507
2539
  await start(ctx);
2508
2540
  } catch (e) {
2509
2541
  process.exitCode = 1;
2510
2542
  throw e;
2511
2543
  } finally {
2512
- if (!config.watch)
2513
- await server.close();
2544
+ if (!ctx.config.watch)
2545
+ await ctx.server.close();
2514
2546
  }
2515
2547
  }