cli.mjs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. import { EventEmitter } from 'events';
  2. import { p as picocolors } from './chunk-constants.71e8a211.mjs';
  3. import { v as version, s as startVitest, d as divider } from './chunk-vite-node-externalize.8d8032d0.mjs';
  4. import 'tty';
  5. import 'url';
  6. import 'path';
  7. import './chunk-integrations-coverage.99c020eb.mjs';
  8. import 'local-pkg';
  9. import './chunk-env-node.ceb43f1c.mjs';
  10. import 'console';
  11. import './chunk-mock-date.2917be60.mjs';
  12. import 'vite';
  13. import 'process';
  14. import 'fs';
  15. import 'os';
  16. import 'util';
  17. import 'stream';
  18. import './vendor-_commonjsHelpers.4da45ef5.mjs';
  19. import './chunk-vite-node-client.da0a17ff.mjs';
  20. import 'module';
  21. import 'vm';
  22. import './chunk-vite-node-utils.473cd0b2.mjs';
  23. import 'assert';
  24. import 'debug';
  25. import 'perf_hooks';
  26. import 'worker_threads';
  27. import 'tinypool';
  28. import './chunk-utils-source-map.2be5aa48.mjs';
  29. import './chunk-utils-timers.b48455ed.mjs';
  30. import 'crypto';
  31. import './vendor-index.9d9196cc.mjs';
  32. import './vendor-index.29636037.mjs';
  33. import './chunk-magic-string.56b2b543.mjs';
  34. import 'strip-literal';
  35. import 'readline';
  36. import './vendor-index.ae96af6e.mjs';
  37. function toArr(any) {
  38. return any == null ? [] : Array.isArray(any) ? any : [any];
  39. }
  40. function toVal(out, key, val, opts) {
  41. var x, old=out[key], nxt=(
  42. !!~opts.string.indexOf(key) ? (val == null || val === true ? '' : String(val))
  43. : typeof val === 'boolean' ? val
  44. : !!~opts.boolean.indexOf(key) ? (val === 'false' ? false : val === 'true' || (out._.push((x = +val,x * 0 === 0) ? x : val),!!val))
  45. : (x = +val,x * 0 === 0) ? x : val
  46. );
  47. out[key] = old == null ? nxt : (Array.isArray(old) ? old.concat(nxt) : [old, nxt]);
  48. }
  49. function mri2 (args, opts) {
  50. args = args || [];
  51. opts = opts || {};
  52. var k, arr, arg, name, val, out={ _:[] };
  53. var i=0, j=0, idx=0, len=args.length;
  54. const alibi = opts.alias !== void 0;
  55. const strict = opts.unknown !== void 0;
  56. const defaults = opts.default !== void 0;
  57. opts.alias = opts.alias || {};
  58. opts.string = toArr(opts.string);
  59. opts.boolean = toArr(opts.boolean);
  60. if (alibi) {
  61. for (k in opts.alias) {
  62. arr = opts.alias[k] = toArr(opts.alias[k]);
  63. for (i=0; i < arr.length; i++) {
  64. (opts.alias[arr[i]] = arr.concat(k)).splice(i, 1);
  65. }
  66. }
  67. }
  68. for (i=opts.boolean.length; i-- > 0;) {
  69. arr = opts.alias[opts.boolean[i]] || [];
  70. for (j=arr.length; j-- > 0;) opts.boolean.push(arr[j]);
  71. }
  72. for (i=opts.string.length; i-- > 0;) {
  73. arr = opts.alias[opts.string[i]] || [];
  74. for (j=arr.length; j-- > 0;) opts.string.push(arr[j]);
  75. }
  76. if (defaults) {
  77. for (k in opts.default) {
  78. name = typeof opts.default[k];
  79. arr = opts.alias[k] = opts.alias[k] || [];
  80. if (opts[name] !== void 0) {
  81. opts[name].push(k);
  82. for (i=0; i < arr.length; i++) {
  83. opts[name].push(arr[i]);
  84. }
  85. }
  86. }
  87. }
  88. const keys = strict ? Object.keys(opts.alias) : [];
  89. for (i=0; i < len; i++) {
  90. arg = args[i];
  91. if (arg === '--') {
  92. out._ = out._.concat(args.slice(++i));
  93. break;
  94. }
  95. for (j=0; j < arg.length; j++) {
  96. if (arg.charCodeAt(j) !== 45) break; // "-"
  97. }
  98. if (j === 0) {
  99. out._.push(arg);
  100. } else if (arg.substring(j, j + 3) === 'no-') {
  101. name = arg.substring(j + 3);
  102. if (strict && !~keys.indexOf(name)) {
  103. return opts.unknown(arg);
  104. }
  105. out[name] = false;
  106. } else {
  107. for (idx=j+1; idx < arg.length; idx++) {
  108. if (arg.charCodeAt(idx) === 61) break; // "="
  109. }
  110. name = arg.substring(j, idx);
  111. val = arg.substring(++idx) || (i+1 === len || (''+args[i+1]).charCodeAt(0) === 45 || args[++i]);
  112. arr = (j === 2 ? [name] : name);
  113. for (idx=0; idx < arr.length; idx++) {
  114. name = arr[idx];
  115. if (strict && !~keys.indexOf(name)) return opts.unknown('-'.repeat(j) + name);
  116. toVal(out, name, (idx + 1 < arr.length) || val, opts);
  117. }
  118. }
  119. }
  120. if (defaults) {
  121. for (k in opts.default) {
  122. if (out[k] === void 0) {
  123. out[k] = opts.default[k];
  124. }
  125. }
  126. }
  127. if (alibi) {
  128. for (k in out) {
  129. arr = opts.alias[k] || [];
  130. while (arr.length > 0) {
  131. out[arr.shift()] = out[k];
  132. }
  133. }
  134. }
  135. return out;
  136. }
  137. const removeBrackets = (v) => v.replace(/[<[].+/, "").trim();
  138. const findAllBrackets = (v) => {
  139. const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g;
  140. const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g;
  141. const res = [];
  142. const parse = (match) => {
  143. let variadic = false;
  144. let value = match[1];
  145. if (value.startsWith("...")) {
  146. value = value.slice(3);
  147. variadic = true;
  148. }
  149. return {
  150. required: match[0].startsWith("<"),
  151. value,
  152. variadic
  153. };
  154. };
  155. let angledMatch;
  156. while (angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v)) {
  157. res.push(parse(angledMatch));
  158. }
  159. let squareMatch;
  160. while (squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v)) {
  161. res.push(parse(squareMatch));
  162. }
  163. return res;
  164. };
  165. const getMriOptions = (options) => {
  166. const result = {alias: {}, boolean: []};
  167. for (const [index, option] of options.entries()) {
  168. if (option.names.length > 1) {
  169. result.alias[option.names[0]] = option.names.slice(1);
  170. }
  171. if (option.isBoolean) {
  172. if (option.negated) {
  173. const hasStringTypeOption = options.some((o, i) => {
  174. return i !== index && o.names.some((name) => option.names.includes(name)) && typeof o.required === "boolean";
  175. });
  176. if (!hasStringTypeOption) {
  177. result.boolean.push(option.names[0]);
  178. }
  179. } else {
  180. result.boolean.push(option.names[0]);
  181. }
  182. }
  183. }
  184. return result;
  185. };
  186. const findLongest = (arr) => {
  187. return arr.sort((a, b) => {
  188. return a.length > b.length ? -1 : 1;
  189. })[0];
  190. };
  191. const padRight = (str, length) => {
  192. return str.length >= length ? str : `${str}${" ".repeat(length - str.length)}`;
  193. };
  194. const camelcase = (input) => {
  195. return input.replace(/([a-z])-([a-z])/g, (_, p1, p2) => {
  196. return p1 + p2.toUpperCase();
  197. });
  198. };
  199. const setDotProp = (obj, keys, val) => {
  200. let i = 0;
  201. let length = keys.length;
  202. let t = obj;
  203. let x;
  204. for (; i < length; ++i) {
  205. x = t[keys[i]];
  206. t = t[keys[i]] = i === length - 1 ? val : x != null ? x : !!~keys[i + 1].indexOf(".") || !(+keys[i + 1] > -1) ? {} : [];
  207. }
  208. };
  209. const setByType = (obj, transforms) => {
  210. for (const key of Object.keys(transforms)) {
  211. const transform = transforms[key];
  212. if (transform.shouldTransform) {
  213. obj[key] = Array.prototype.concat.call([], obj[key]);
  214. if (typeof transform.transformFunction === "function") {
  215. obj[key] = obj[key].map(transform.transformFunction);
  216. }
  217. }
  218. }
  219. };
  220. const getFileName = (input) => {
  221. const m = /([^\\\/]+)$/.exec(input);
  222. return m ? m[1] : "";
  223. };
  224. const camelcaseOptionName = (name) => {
  225. return name.split(".").map((v, i) => {
  226. return i === 0 ? camelcase(v) : v;
  227. }).join(".");
  228. };
  229. class CACError extends Error {
  230. constructor(message) {
  231. super(message);
  232. this.name = this.constructor.name;
  233. if (typeof Error.captureStackTrace === "function") {
  234. Error.captureStackTrace(this, this.constructor);
  235. } else {
  236. this.stack = new Error(message).stack;
  237. }
  238. }
  239. }
  240. class Option {
  241. constructor(rawName, description, config) {
  242. this.rawName = rawName;
  243. this.description = description;
  244. this.config = Object.assign({}, config);
  245. rawName = rawName.replace(/\.\*/g, "");
  246. this.negated = false;
  247. this.names = removeBrackets(rawName).split(",").map((v) => {
  248. let name = v.trim().replace(/^-{1,2}/, "");
  249. if (name.startsWith("no-")) {
  250. this.negated = true;
  251. name = name.replace(/^no-/, "");
  252. }
  253. return camelcaseOptionName(name);
  254. }).sort((a, b) => a.length > b.length ? 1 : -1);
  255. this.name = this.names[this.names.length - 1];
  256. if (this.negated && this.config.default == null) {
  257. this.config.default = true;
  258. }
  259. if (rawName.includes("<")) {
  260. this.required = true;
  261. } else if (rawName.includes("[")) {
  262. this.required = false;
  263. } else {
  264. this.isBoolean = true;
  265. }
  266. }
  267. }
  268. const processArgs = process.argv;
  269. const platformInfo = `${process.platform}-${process.arch} node-${process.version}`;
  270. class Command {
  271. constructor(rawName, description, config = {}, cli) {
  272. this.rawName = rawName;
  273. this.description = description;
  274. this.config = config;
  275. this.cli = cli;
  276. this.options = [];
  277. this.aliasNames = [];
  278. this.name = removeBrackets(rawName);
  279. this.args = findAllBrackets(rawName);
  280. this.examples = [];
  281. }
  282. usage(text) {
  283. this.usageText = text;
  284. return this;
  285. }
  286. allowUnknownOptions() {
  287. this.config.allowUnknownOptions = true;
  288. return this;
  289. }
  290. ignoreOptionDefaultValue() {
  291. this.config.ignoreOptionDefaultValue = true;
  292. return this;
  293. }
  294. version(version, customFlags = "-v, --version") {
  295. this.versionNumber = version;
  296. this.option(customFlags, "Display version number");
  297. return this;
  298. }
  299. example(example) {
  300. this.examples.push(example);
  301. return this;
  302. }
  303. option(rawName, description, config) {
  304. const option = new Option(rawName, description, config);
  305. this.options.push(option);
  306. return this;
  307. }
  308. alias(name) {
  309. this.aliasNames.push(name);
  310. return this;
  311. }
  312. action(callback) {
  313. this.commandAction = callback;
  314. return this;
  315. }
  316. isMatched(name) {
  317. return this.name === name || this.aliasNames.includes(name);
  318. }
  319. get isDefaultCommand() {
  320. return this.name === "" || this.aliasNames.includes("!");
  321. }
  322. get isGlobalCommand() {
  323. return this instanceof GlobalCommand;
  324. }
  325. hasOption(name) {
  326. name = name.split(".")[0];
  327. return this.options.find((option) => {
  328. return option.names.includes(name);
  329. });
  330. }
  331. outputHelp() {
  332. const {name, commands} = this.cli;
  333. const {
  334. versionNumber,
  335. options: globalOptions,
  336. helpCallback
  337. } = this.cli.globalCommand;
  338. let sections = [
  339. {
  340. body: `${name}${versionNumber ? `/${versionNumber}` : ""}`
  341. }
  342. ];
  343. sections.push({
  344. title: "Usage",
  345. body: ` $ ${name} ${this.usageText || this.rawName}`
  346. });
  347. const showCommands = (this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0;
  348. if (showCommands) {
  349. const longestCommandName = findLongest(commands.map((command) => command.rawName));
  350. sections.push({
  351. title: "Commands",
  352. body: commands.map((command) => {
  353. return ` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`;
  354. }).join("\n")
  355. });
  356. sections.push({
  357. title: `For more info, run any command with the \`--help\` flag`,
  358. body: commands.map((command) => ` $ ${name}${command.name === "" ? "" : ` ${command.name}`} --help`).join("\n")
  359. });
  360. }
  361. let options = this.isGlobalCommand ? globalOptions : [...this.options, ...globalOptions || []];
  362. if (!this.isGlobalCommand && !this.isDefaultCommand) {
  363. options = options.filter((option) => option.name !== "version");
  364. }
  365. if (options.length > 0) {
  366. const longestOptionName = findLongest(options.map((option) => option.rawName));
  367. sections.push({
  368. title: "Options",
  369. body: options.map((option) => {
  370. return ` ${padRight(option.rawName, longestOptionName.length)} ${option.description} ${option.config.default === void 0 ? "" : `(default: ${option.config.default})`}`;
  371. }).join("\n")
  372. });
  373. }
  374. if (this.examples.length > 0) {
  375. sections.push({
  376. title: "Examples",
  377. body: this.examples.map((example) => {
  378. if (typeof example === "function") {
  379. return example(name);
  380. }
  381. return example;
  382. }).join("\n")
  383. });
  384. }
  385. if (helpCallback) {
  386. sections = helpCallback(sections) || sections;
  387. }
  388. console.log(sections.map((section) => {
  389. return section.title ? `${section.title}:
  390. ${section.body}` : section.body;
  391. }).join("\n\n"));
  392. }
  393. outputVersion() {
  394. const {name} = this.cli;
  395. const {versionNumber} = this.cli.globalCommand;
  396. if (versionNumber) {
  397. console.log(`${name}/${versionNumber} ${platformInfo}`);
  398. }
  399. }
  400. checkRequiredArgs() {
  401. const minimalArgsCount = this.args.filter((arg) => arg.required).length;
  402. if (this.cli.args.length < minimalArgsCount) {
  403. throw new CACError(`missing required args for command \`${this.rawName}\``);
  404. }
  405. }
  406. checkUnknownOptions() {
  407. const {options, globalCommand} = this.cli;
  408. if (!this.config.allowUnknownOptions) {
  409. for (const name of Object.keys(options)) {
  410. if (name !== "--" && !this.hasOption(name) && !globalCommand.hasOption(name)) {
  411. throw new CACError(`Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``);
  412. }
  413. }
  414. }
  415. }
  416. checkOptionValue() {
  417. const {options: parsedOptions, globalCommand} = this.cli;
  418. const options = [...globalCommand.options, ...this.options];
  419. for (const option of options) {
  420. const value = parsedOptions[option.name.split(".")[0]];
  421. if (option.required) {
  422. const hasNegated = options.some((o) => o.negated && o.names.includes(option.name));
  423. if (value === true || value === false && !hasNegated) {
  424. throw new CACError(`option \`${option.rawName}\` value is missing`);
  425. }
  426. }
  427. }
  428. }
  429. }
  430. class GlobalCommand extends Command {
  431. constructor(cli) {
  432. super("@@global@@", "", {}, cli);
  433. }
  434. }
  435. var __assign = Object.assign;
  436. class CAC extends EventEmitter {
  437. constructor(name = "") {
  438. super();
  439. this.name = name;
  440. this.commands = [];
  441. this.rawArgs = [];
  442. this.args = [];
  443. this.options = {};
  444. this.globalCommand = new GlobalCommand(this);
  445. this.globalCommand.usage("<command> [options]");
  446. }
  447. usage(text) {
  448. this.globalCommand.usage(text);
  449. return this;
  450. }
  451. command(rawName, description, config) {
  452. const command = new Command(rawName, description || "", config, this);
  453. command.globalCommand = this.globalCommand;
  454. this.commands.push(command);
  455. return command;
  456. }
  457. option(rawName, description, config) {
  458. this.globalCommand.option(rawName, description, config);
  459. return this;
  460. }
  461. help(callback) {
  462. this.globalCommand.option("-h, --help", "Display this message");
  463. this.globalCommand.helpCallback = callback;
  464. this.showHelpOnExit = true;
  465. return this;
  466. }
  467. version(version, customFlags = "-v, --version") {
  468. this.globalCommand.version(version, customFlags);
  469. this.showVersionOnExit = true;
  470. return this;
  471. }
  472. example(example) {
  473. this.globalCommand.example(example);
  474. return this;
  475. }
  476. outputHelp() {
  477. if (this.matchedCommand) {
  478. this.matchedCommand.outputHelp();
  479. } else {
  480. this.globalCommand.outputHelp();
  481. }
  482. }
  483. outputVersion() {
  484. this.globalCommand.outputVersion();
  485. }
  486. setParsedInfo({args, options}, matchedCommand, matchedCommandName) {
  487. this.args = args;
  488. this.options = options;
  489. if (matchedCommand) {
  490. this.matchedCommand = matchedCommand;
  491. }
  492. if (matchedCommandName) {
  493. this.matchedCommandName = matchedCommandName;
  494. }
  495. return this;
  496. }
  497. unsetMatchedCommand() {
  498. this.matchedCommand = void 0;
  499. this.matchedCommandName = void 0;
  500. }
  501. parse(argv = processArgs, {
  502. run = true
  503. } = {}) {
  504. this.rawArgs = argv;
  505. if (!this.name) {
  506. this.name = argv[1] ? getFileName(argv[1]) : "cli";
  507. }
  508. let shouldParse = true;
  509. for (const command of this.commands) {
  510. const parsed = this.mri(argv.slice(2), command);
  511. const commandName = parsed.args[0];
  512. if (command.isMatched(commandName)) {
  513. shouldParse = false;
  514. const parsedInfo = __assign(__assign({}, parsed), {
  515. args: parsed.args.slice(1)
  516. });
  517. this.setParsedInfo(parsedInfo, command, commandName);
  518. this.emit(`command:${commandName}`, command);
  519. }
  520. }
  521. if (shouldParse) {
  522. for (const command of this.commands) {
  523. if (command.name === "") {
  524. shouldParse = false;
  525. const parsed = this.mri(argv.slice(2), command);
  526. this.setParsedInfo(parsed, command);
  527. this.emit(`command:!`, command);
  528. }
  529. }
  530. }
  531. if (shouldParse) {
  532. const parsed = this.mri(argv.slice(2));
  533. this.setParsedInfo(parsed);
  534. }
  535. if (this.options.help && this.showHelpOnExit) {
  536. this.outputHelp();
  537. run = false;
  538. this.unsetMatchedCommand();
  539. }
  540. if (this.options.version && this.showVersionOnExit && this.matchedCommandName == null) {
  541. this.outputVersion();
  542. run = false;
  543. this.unsetMatchedCommand();
  544. }
  545. const parsedArgv = {args: this.args, options: this.options};
  546. if (run) {
  547. this.runMatchedCommand();
  548. }
  549. if (!this.matchedCommand && this.args[0]) {
  550. this.emit("command:*");
  551. }
  552. return parsedArgv;
  553. }
  554. mri(argv, command) {
  555. const cliOptions = [
  556. ...this.globalCommand.options,
  557. ...command ? command.options : []
  558. ];
  559. const mriOptions = getMriOptions(cliOptions);
  560. let argsAfterDoubleDashes = [];
  561. const doubleDashesIndex = argv.indexOf("--");
  562. if (doubleDashesIndex > -1) {
  563. argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1);
  564. argv = argv.slice(0, doubleDashesIndex);
  565. }
  566. let parsed = mri2(argv, mriOptions);
  567. parsed = Object.keys(parsed).reduce((res, name) => {
  568. return __assign(__assign({}, res), {
  569. [camelcaseOptionName(name)]: parsed[name]
  570. });
  571. }, {_: []});
  572. const args = parsed._;
  573. const options = {
  574. "--": argsAfterDoubleDashes
  575. };
  576. const ignoreDefault = command && command.config.ignoreOptionDefaultValue ? command.config.ignoreOptionDefaultValue : this.globalCommand.config.ignoreOptionDefaultValue;
  577. let transforms = Object.create(null);
  578. for (const cliOption of cliOptions) {
  579. if (!ignoreDefault && cliOption.config.default !== void 0) {
  580. for (const name of cliOption.names) {
  581. options[name] = cliOption.config.default;
  582. }
  583. }
  584. if (Array.isArray(cliOption.config.type)) {
  585. if (transforms[cliOption.name] === void 0) {
  586. transforms[cliOption.name] = Object.create(null);
  587. transforms[cliOption.name]["shouldTransform"] = true;
  588. transforms[cliOption.name]["transformFunction"] = cliOption.config.type[0];
  589. }
  590. }
  591. }
  592. for (const key of Object.keys(parsed)) {
  593. if (key !== "_") {
  594. const keys = key.split(".");
  595. setDotProp(options, keys, parsed[key]);
  596. setByType(options, transforms);
  597. }
  598. }
  599. return {
  600. args,
  601. options
  602. };
  603. }
  604. runMatchedCommand() {
  605. const {args, options, matchedCommand: command} = this;
  606. if (!command || !command.commandAction)
  607. return;
  608. command.checkUnknownOptions();
  609. command.checkOptionValue();
  610. command.checkRequiredArgs();
  611. const actionArgs = [];
  612. command.args.forEach((arg, index) => {
  613. if (arg.variadic) {
  614. actionArgs.push(args.slice(index));
  615. } else {
  616. actionArgs.push(args[index]);
  617. }
  618. });
  619. actionArgs.push(options);
  620. return command.commandAction.apply(this, actionArgs);
  621. }
  622. }
  623. const cac = (name = "") => new CAC(name);
  624. const cli = cac("vitest");
  625. 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("-t, --testNamePattern <pattern>", "run tests with full names matching the specified pattern").option("--dir <path>", "base directory to scan for the test files").option("--ui", "enable UI").option("--open", "open UI automatically (default: !process.env.CI))").option("--api [api]", "serve API, available options: --api.port <port>, --api.host [host] and --api.strictPort").option("--threads", "enabled threads (default: true)").option("--silent", "silent console output from tests").option("--isolate", "isolate environment for each test file (default: true)").option("--reporter <name>", "reporter").option("--outputTruncateLength <length>", "diff output length (default: 80)").option("--outputDiffLines <lines>", "number of diff output lines (default: 15)").option("--outputFile <filename/-s>", "write test results to a file when the --reporter=json or --reporter=junit option is also specified, use cac's dot notation for individual outputs of multiple reporters").option("--coverage", "enable coverage report").option("--run", "do not watch").option("--mode <name>", "override Vite mode (default: test)").option("--globals", "inject apis globally").option("--dom", "mock browser api with happy-dom").option("--browser", "run tests in browser").option("--environment <env>", "runner environment (default: node)").option("--passWithNoTests", "pass when no tests found").option("--allowOnly", "Allow tests and suites that are marked as only (default: !process.env.CI)").option("--dangerouslyIgnoreUnhandledErrors", "Ignore any unhandled errors that occur").option("--shard <shard>", "Test suite shard to execute in a format of <index>/<count>").option("--changed [since]", "Run tests that are affected by the changed files (default: false)").option("--sequence <options>", "Define in what order to run tests (use --sequence.shuffle to run tests in random order)").option("--no-color", "Removes colors from the console output").option("--segfault-retry <times>", "Return tests on segment fault (default: 0)", { default: 0 }).option("--inspect", "Enable Node.js inspector").option("--inspect-brk", "Enable Node.js inspector with break").help();
  626. cli.command("run [...filters]").action(run);
  627. cli.command("related [...filters]").action(runRelated);
  628. cli.command("watch [...filters]").action(watch);
  629. cli.command("dev [...filters]").action(watch);
  630. cli.command("bench [...filters]").action(benchmark);
  631. cli.command("[...filters]").action((filters, options) => start("test", filters, options));
  632. cli.parse();
  633. async function runRelated(relatedFiles, argv) {
  634. argv.related = relatedFiles;
  635. argv.passWithNoTests ?? (argv.passWithNoTests = true);
  636. await start("test", [], argv);
  637. }
  638. async function watch(cliFilters, options) {
  639. options.watch = true;
  640. await start("test", cliFilters, options);
  641. }
  642. async function run(cliFilters, options) {
  643. options.run = true;
  644. await start("test", cliFilters, options);
  645. }
  646. async function benchmark(cliFilters, options) {
  647. console.warn(picocolors.exports.yellow("Benchmarking is an experimental feature.\nBreaking changes might not follow semver, please pin Vitest's version when using it."));
  648. await start("benchmark", cliFilters, options);
  649. }
  650. async function start(mode, cliFilters, options) {
  651. try {
  652. if (await startVitest(mode, cliFilters, options) === false)
  653. process.exit();
  654. } catch (e) {
  655. process.exitCode = 1;
  656. console.error(`
  657. ${picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(" Unhandled Error "))))}`);
  658. console.error(e);
  659. console.error("\n\n");
  660. }
  661. }