@vitest/runner 4.0.0-beta.2 → 4.0.0-beta.4

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.
@@ -1,7 +1,7 @@
1
1
  import { isObject, createDefer, toArray, isNegativeNaN, format, objectAttr, objDisplay, getSafeTimers, shuffle, assertTypes } from '@vitest/utils';
2
- import { parseSingleStack } from '@vitest/utils/source-map';
3
2
  import { processError } from '@vitest/utils/error';
4
3
  import { stripLiteral } from 'strip-literal';
4
+ import { parseSingleStack } from '@vitest/utils/source-map';
5
5
  import { relative } from 'pathe';
6
6
 
7
7
  class PendingError extends Error {
@@ -391,6 +391,309 @@ function createChainable(keys, fn) {
391
391
  return chain;
392
392
  }
393
393
 
394
+ /**
395
+ * If any tasks been marked as `only`, mark all other tasks as `skip`.
396
+ */
397
+ function interpretTaskModes(file, namePattern, testLocations, onlyMode, parentIsOnly, allowOnly) {
398
+ const matchedLocations = [];
399
+ const traverseSuite = (suite, parentIsOnly, parentMatchedWithLocation) => {
400
+ const suiteIsOnly = parentIsOnly || suite.mode === "only";
401
+ suite.tasks.forEach((t) => {
402
+ // Check if either the parent suite or the task itself are marked as included
403
+ const includeTask = suiteIsOnly || t.mode === "only";
404
+ if (onlyMode) {
405
+ if (t.type === "suite" && (includeTask || someTasksAreOnly(t))) {
406
+ // Don't skip this suite
407
+ if (t.mode === "only") {
408
+ checkAllowOnly(t, allowOnly);
409
+ t.mode = "run";
410
+ }
411
+ } else if (t.mode === "run" && !includeTask) {
412
+ t.mode = "skip";
413
+ } else if (t.mode === "only") {
414
+ checkAllowOnly(t, allowOnly);
415
+ t.mode = "run";
416
+ }
417
+ }
418
+ let hasLocationMatch = parentMatchedWithLocation;
419
+ // Match test location against provided locations, only run if present
420
+ // in `testLocations`. Note: if `includeTaskLocations` is not enabled,
421
+ // all test will be skipped.
422
+ if (testLocations !== undefined && testLocations.length !== 0) {
423
+ if (t.location && (testLocations === null || testLocations === void 0 ? void 0 : testLocations.includes(t.location.line))) {
424
+ t.mode = "run";
425
+ matchedLocations.push(t.location.line);
426
+ hasLocationMatch = true;
427
+ } else if (parentMatchedWithLocation) {
428
+ t.mode = "run";
429
+ } else if (t.type === "test") {
430
+ t.mode = "skip";
431
+ }
432
+ }
433
+ if (t.type === "test") {
434
+ if (namePattern && !getTaskFullName(t).match(namePattern)) {
435
+ t.mode = "skip";
436
+ }
437
+ } else if (t.type === "suite") {
438
+ if (t.mode === "skip") {
439
+ skipAllTasks(t);
440
+ } else if (t.mode === "todo") {
441
+ todoAllTasks(t);
442
+ } else {
443
+ traverseSuite(t, includeTask, hasLocationMatch);
444
+ }
445
+ }
446
+ });
447
+ // if all subtasks are skipped, mark as skip
448
+ if (suite.mode === "run" || suite.mode === "queued") {
449
+ if (suite.tasks.length && suite.tasks.every((i) => i.mode !== "run" && i.mode !== "queued")) {
450
+ suite.mode = "skip";
451
+ }
452
+ }
453
+ };
454
+ traverseSuite(file, parentIsOnly, false);
455
+ const nonMatching = testLocations === null || testLocations === void 0 ? void 0 : testLocations.filter((loc) => !matchedLocations.includes(loc));
456
+ if (nonMatching && nonMatching.length !== 0) {
457
+ const message = nonMatching.length === 1 ? `line ${nonMatching[0]}` : `lines ${nonMatching.join(", ")}`;
458
+ if (file.result === undefined) {
459
+ file.result = {
460
+ state: "fail",
461
+ errors: []
462
+ };
463
+ }
464
+ if (file.result.errors === undefined) {
465
+ file.result.errors = [];
466
+ }
467
+ file.result.errors.push(processError(new Error(`No test found in ${file.name} in ${message}`)));
468
+ }
469
+ }
470
+ function getTaskFullName(task) {
471
+ return `${task.suite ? `${getTaskFullName(task.suite)} ` : ""}${task.name}`;
472
+ }
473
+ function someTasksAreOnly(suite) {
474
+ return suite.tasks.some((t) => t.mode === "only" || t.type === "suite" && someTasksAreOnly(t));
475
+ }
476
+ function skipAllTasks(suite) {
477
+ suite.tasks.forEach((t) => {
478
+ if (t.mode === "run" || t.mode === "queued") {
479
+ t.mode = "skip";
480
+ if (t.type === "suite") {
481
+ skipAllTasks(t);
482
+ }
483
+ }
484
+ });
485
+ }
486
+ function todoAllTasks(suite) {
487
+ suite.tasks.forEach((t) => {
488
+ if (t.mode === "run" || t.mode === "queued") {
489
+ t.mode = "todo";
490
+ if (t.type === "suite") {
491
+ todoAllTasks(t);
492
+ }
493
+ }
494
+ });
495
+ }
496
+ function checkAllowOnly(task, allowOnly) {
497
+ if (allowOnly) {
498
+ return;
499
+ }
500
+ const error = processError(new Error("[Vitest] Unexpected .only modifier. Remove it or pass --allowOnly argument to bypass this error"));
501
+ task.result = {
502
+ state: "fail",
503
+ errors: [error]
504
+ };
505
+ }
506
+ function generateHash(str) {
507
+ let hash = 0;
508
+ if (str.length === 0) {
509
+ return `${hash}`;
510
+ }
511
+ for (let i = 0; i < str.length; i++) {
512
+ const char = str.charCodeAt(i);
513
+ hash = (hash << 5) - hash + char;
514
+ hash = hash & hash;
515
+ }
516
+ return `${hash}`;
517
+ }
518
+ function calculateSuiteHash(parent) {
519
+ parent.tasks.forEach((t, idx) => {
520
+ t.id = `${parent.id}_${idx}`;
521
+ if (t.type === "suite") {
522
+ calculateSuiteHash(t);
523
+ }
524
+ });
525
+ }
526
+ function createFileTask(filepath, root, projectName, pool) {
527
+ const path = relative(root, filepath);
528
+ const file = {
529
+ id: generateFileHash(path, projectName),
530
+ name: path,
531
+ type: "suite",
532
+ mode: "queued",
533
+ filepath,
534
+ tasks: [],
535
+ meta: Object.create(null),
536
+ projectName,
537
+ file: undefined,
538
+ pool
539
+ };
540
+ file.file = file;
541
+ setFileContext(file, Object.create(null));
542
+ return file;
543
+ }
544
+ /**
545
+ * Generate a unique ID for a file based on its path and project name
546
+ * @param file File relative to the root of the project to keep ID the same between different machines
547
+ * @param projectName The name of the test project
548
+ */
549
+ function generateFileHash(file, projectName) {
550
+ return generateHash(`${file}${projectName || ""}`);
551
+ }
552
+ function findTestFileStackTrace(testFilePath, error) {
553
+ // first line is the error message
554
+ const lines = error.split("\n").slice(1);
555
+ for (const line of lines) {
556
+ const stack = parseSingleStack(line);
557
+ if (stack && stack.file === testFilePath) {
558
+ return stack;
559
+ }
560
+ }
561
+ }
562
+
563
+ /**
564
+ * Return a function for running multiple async operations with limited concurrency.
565
+ */
566
+ function limitConcurrency(concurrency = Infinity) {
567
+ // The number of currently active + pending tasks.
568
+ let count = 0;
569
+ // The head and tail of the pending task queue, built using a singly linked list.
570
+ // Both head and tail are initially undefined, signifying an empty queue.
571
+ // They both become undefined again whenever there are no pending tasks.
572
+ let head;
573
+ let tail;
574
+ // A bookkeeping function executed whenever a task has been run to completion.
575
+ const finish = () => {
576
+ count--;
577
+ // Check if there are further pending tasks in the queue.
578
+ if (head) {
579
+ // Allow the next pending task to run and pop it from the queue.
580
+ head[0]();
581
+ head = head[1];
582
+ // The head may now be undefined if there are no further pending tasks.
583
+ // In that case, set tail to undefined as well.
584
+ tail = head && tail;
585
+ }
586
+ };
587
+ return (func, ...args) => {
588
+ // Create a promise chain that:
589
+ // 1. Waits for its turn in the task queue (if necessary).
590
+ // 2. Runs the task.
591
+ // 3. Allows the next pending task (if any) to run.
592
+ return new Promise((resolve) => {
593
+ if (count++ < concurrency) {
594
+ // No need to queue if fewer than maxConcurrency tasks are running.
595
+ resolve();
596
+ } else if (tail) {
597
+ // There are pending tasks, so append to the queue.
598
+ tail = tail[1] = [resolve];
599
+ } else {
600
+ // No other pending tasks, initialize the queue with a new tail and head.
601
+ head = tail = [resolve];
602
+ }
603
+ }).then(() => {
604
+ // Running func here ensures that even a non-thenable result or an
605
+ // immediately thrown error gets wrapped into a Promise.
606
+ return func(...args);
607
+ }).finally(finish);
608
+ };
609
+ }
610
+
611
+ /**
612
+ * Partition in tasks groups by consecutive concurrent
613
+ */
614
+ function partitionSuiteChildren(suite) {
615
+ let tasksGroup = [];
616
+ const tasksGroups = [];
617
+ for (const c of suite.tasks) {
618
+ if (tasksGroup.length === 0 || c.concurrent === tasksGroup[0].concurrent) {
619
+ tasksGroup.push(c);
620
+ } else {
621
+ tasksGroups.push(tasksGroup);
622
+ tasksGroup = [c];
623
+ }
624
+ }
625
+ if (tasksGroup.length > 0) {
626
+ tasksGroups.push(tasksGroup);
627
+ }
628
+ return tasksGroups;
629
+ }
630
+
631
+ /**
632
+ * @deprecated use `isTestCase` instead
633
+ */
634
+ function isAtomTest(s) {
635
+ return isTestCase(s);
636
+ }
637
+ function isTestCase(s) {
638
+ return s.type === "test";
639
+ }
640
+ function getTests(suite) {
641
+ const tests = [];
642
+ const arraySuites = toArray(suite);
643
+ for (const s of arraySuites) {
644
+ if (isTestCase(s)) {
645
+ tests.push(s);
646
+ } else {
647
+ for (const task of s.tasks) {
648
+ if (isTestCase(task)) {
649
+ tests.push(task);
650
+ } else {
651
+ const taskTests = getTests(task);
652
+ for (const test of taskTests) {
653
+ tests.push(test);
654
+ }
655
+ }
656
+ }
657
+ }
658
+ }
659
+ return tests;
660
+ }
661
+ function getTasks(tasks = []) {
662
+ return toArray(tasks).flatMap((s) => isTestCase(s) ? [s] : [s, ...getTasks(s.tasks)]);
663
+ }
664
+ function getSuites(suite) {
665
+ return toArray(suite).flatMap((s) => s.type === "suite" ? [s, ...getSuites(s.tasks)] : []);
666
+ }
667
+ function hasTests(suite) {
668
+ return toArray(suite).some((s) => s.tasks.some((c) => isTestCase(c) || hasTests(c)));
669
+ }
670
+ function hasFailed(suite) {
671
+ return toArray(suite).some((s) => {
672
+ var _s$result;
673
+ return ((_s$result = s.result) === null || _s$result === void 0 ? void 0 : _s$result.state) === "fail" || s.type === "suite" && hasFailed(s.tasks);
674
+ });
675
+ }
676
+ function getNames(task) {
677
+ const names = [task.name];
678
+ let current = task;
679
+ while (current === null || current === void 0 ? void 0 : current.suite) {
680
+ current = current.suite;
681
+ if (current === null || current === void 0 ? void 0 : current.name) {
682
+ names.unshift(current.name);
683
+ }
684
+ }
685
+ if (current !== task.file) {
686
+ names.unshift(task.file.name);
687
+ }
688
+ return names;
689
+ }
690
+ function getFullName(task, separator = " > ") {
691
+ return getNames(task).join(separator);
692
+ }
693
+ function getTestName(task, separator = " > ") {
694
+ return getNames(task).slice(1).join(separator);
695
+ }
696
+
394
697
  /**
395
698
  * Creates a suite of tests, allowing for grouping and hierarchical organization of tests.
396
699
  * Suites can contain both tests and other suites, enabling complex test structures.
@@ -530,9 +833,6 @@ function getDefaultSuite() {
530
833
  assert(defaultSuite, "the default suite");
531
834
  return defaultSuite;
532
835
  }
533
- function getTestFilepath() {
534
- return currentTestFilepath;
535
- }
536
836
  function getRunner() {
537
837
  assert(runner, "the runner");
538
838
  return runner;
@@ -642,9 +942,12 @@ function createSuiteCollector(name, factory = () => {}, mode, each, suiteOptions
642
942
  }
643
943
  if (runner.config.includeTaskLocation) {
644
944
  const error = stackTraceError.stack;
645
- const stack = findTestFileStackTrace(error);
945
+ const stack = findTestFileStackTrace(currentTestFilepath, error);
646
946
  if (stack) {
647
- task.location = stack;
947
+ task.location = {
948
+ line: stack.line,
949
+ column: stack.column
950
+ };
648
951
  }
649
952
  }
650
953
  tasks.push(task);
@@ -715,9 +1018,12 @@ function createSuiteCollector(name, factory = () => {}, mode, each, suiteOptions
715
1018
  Error.stackTraceLimit = 15;
716
1019
  const error = new Error("stacktrace").stack;
717
1020
  Error.stackTraceLimit = limit;
718
- const stack = findTestFileStackTrace(error);
1021
+ const stack = findTestFileStackTrace(currentTestFilepath, error);
719
1022
  if (stack) {
720
- suite.location = stack;
1023
+ suite.location = {
1024
+ line: stack.line,
1025
+ column: stack.column
1026
+ };
721
1027
  }
722
1028
  }
723
1029
  setHooks(suite, createSuiteHooks());
@@ -898,6 +1204,7 @@ function createTaskCollector(fn, context) {
898
1204
  const _context = mergeContextFixtures(fixtures, context || {}, runner);
899
1205
  const originalWrapper = fn;
900
1206
  return createTest(function(name, optionsOrFn, optionsOrTest) {
1207
+ var _collector$options;
901
1208
  const collector = getCurrentSuite();
902
1209
  const scopedFixtures = collector.fixtures();
903
1210
  const context = { ...this };
@@ -905,7 +1212,7 @@ function createTaskCollector(fn, context) {
905
1212
  context.fixtures = mergeScopedFixtures(context.fixtures || [], scopedFixtures);
906
1213
  }
907
1214
  const { handler, options } = parseArguments(optionsOrFn, optionsOrTest);
908
- const timeout = options.timeout ?? (runner === null || runner === void 0 ? void 0 : runner.config.testTimeout);
1215
+ const timeout = options.timeout ?? ((_collector$options = collector.options) === null || _collector$options === void 0 ? void 0 : _collector$options.timeout) ?? (runner === null || runner === void 0 ? void 0 : runner.config.testTimeout);
909
1216
  originalWrapper.call(context, formatName(name), handler, timeout);
910
1217
  }, _context);
911
1218
  };
@@ -915,236 +1222,63 @@ function createTaskCollector(fn, context) {
915
1222
  "skip",
916
1223
  "only",
917
1224
  "todo",
918
- "fails"
919
- ], taskFn);
920
- if (context) {
921
- _test.mergeContext(context);
922
- }
923
- return _test;
924
- }
925
- function createTest(fn, context) {
926
- return createTaskCollector(fn, context);
927
- }
928
- function formatName(name) {
929
- return typeof name === "string" ? name : typeof name === "function" ? name.name || "<anonymous>" : String(name);
930
- }
931
- function formatTitle(template, items, idx) {
932
- if (template.includes("%#") || template.includes("%$")) {
933
- // '%#' match index of the test case
934
- template = template.replace(/%%/g, "__vitest_escaped_%__").replace(/%#/g, `${idx}`).replace(/%\$/g, `${idx + 1}`).replace(/__vitest_escaped_%__/g, "%%");
935
- }
936
- const count = template.split("%").length - 1;
937
- if (template.includes("%f")) {
938
- const placeholders = template.match(/%f/g) || [];
939
- placeholders.forEach((_, i) => {
940
- if (isNegativeNaN(items[i]) || Object.is(items[i], -0)) {
941
- // Replace the i-th occurrence of '%f' with '-%f'
942
- let occurrence = 0;
943
- template = template.replace(/%f/g, (match) => {
944
- occurrence++;
945
- return occurrence === i + 1 ? "-%f" : match;
946
- });
947
- }
948
- });
949
- }
950
- let formatted = format(template, ...items.slice(0, count));
951
- const isObjectItem = isObject(items[0]);
952
- formatted = formatted.replace(/\$([$\w.]+)/g, (_, key) => {
953
- var _runner$config;
954
- const isArrayKey = /^\d+$/.test(key);
955
- if (!isObjectItem && !isArrayKey) {
956
- return `$${key}`;
957
- }
958
- const arrayElement = isArrayKey ? objectAttr(items, key) : undefined;
959
- const value = isObjectItem ? objectAttr(items[0], key, arrayElement) : arrayElement;
960
- return objDisplay(value, { truncate: runner === null || runner === void 0 || (_runner$config = runner.config) === null || _runner$config === void 0 || (_runner$config = _runner$config.chaiConfig) === null || _runner$config === void 0 ? void 0 : _runner$config.truncateThreshold });
961
- });
962
- return formatted;
963
- }
964
- function formatTemplateString(cases, args) {
965
- const header = cases.join("").trim().replace(/ /g, "").split("\n").map((i) => i.split("|"))[0];
966
- const res = [];
967
- for (let i = 0; i < Math.floor(args.length / header.length); i++) {
968
- const oneCase = {};
969
- for (let j = 0; j < header.length; j++) {
970
- oneCase[header[j]] = args[i * header.length + j];
971
- }
972
- res.push(oneCase);
973
- }
974
- return res;
975
- }
976
- function findTestFileStackTrace(error) {
977
- const testFilePath = getTestFilepath();
978
- // first line is the error message
979
- const lines = error.split("\n").slice(1);
980
- for (const line of lines) {
981
- const stack = parseSingleStack(line);
982
- if (stack && stack.file === testFilePath) {
983
- return {
984
- line: stack.line,
985
- column: stack.column
986
- };
987
- }
988
- }
989
- }
990
-
991
- /**
992
- * If any tasks been marked as `only`, mark all other tasks as `skip`.
993
- */
994
- function interpretTaskModes(file, namePattern, testLocations, onlyMode, parentIsOnly, allowOnly) {
995
- const matchedLocations = [];
996
- const traverseSuite = (suite, parentIsOnly, parentMatchedWithLocation) => {
997
- const suiteIsOnly = parentIsOnly || suite.mode === "only";
998
- suite.tasks.forEach((t) => {
999
- // Check if either the parent suite or the task itself are marked as included
1000
- const includeTask = suiteIsOnly || t.mode === "only";
1001
- if (onlyMode) {
1002
- if (t.type === "suite" && (includeTask || someTasksAreOnly(t))) {
1003
- // Don't skip this suite
1004
- if (t.mode === "only") {
1005
- checkAllowOnly(t, allowOnly);
1006
- t.mode = "run";
1007
- }
1008
- } else if (t.mode === "run" && !includeTask) {
1009
- t.mode = "skip";
1010
- } else if (t.mode === "only") {
1011
- checkAllowOnly(t, allowOnly);
1012
- t.mode = "run";
1013
- }
1014
- }
1015
- let hasLocationMatch = parentMatchedWithLocation;
1016
- // Match test location against provided locations, only run if present
1017
- // in `testLocations`. Note: if `includeTaskLocations` is not enabled,
1018
- // all test will be skipped.
1019
- if (testLocations !== undefined && testLocations.length !== 0) {
1020
- if (t.location && (testLocations === null || testLocations === void 0 ? void 0 : testLocations.includes(t.location.line))) {
1021
- t.mode = "run";
1022
- matchedLocations.push(t.location.line);
1023
- hasLocationMatch = true;
1024
- } else if (parentMatchedWithLocation) {
1025
- t.mode = "run";
1026
- } else if (t.type === "test") {
1027
- t.mode = "skip";
1028
- }
1029
- }
1030
- if (t.type === "test") {
1031
- if (namePattern && !getTaskFullName(t).match(namePattern)) {
1032
- t.mode = "skip";
1033
- }
1034
- } else if (t.type === "suite") {
1035
- if (t.mode === "skip") {
1036
- skipAllTasks(t);
1037
- } else if (t.mode === "todo") {
1038
- todoAllTasks(t);
1039
- } else {
1040
- traverseSuite(t, includeTask, hasLocationMatch);
1041
- }
1042
- }
1043
- });
1044
- // if all subtasks are skipped, mark as skip
1045
- if (suite.mode === "run" || suite.mode === "queued") {
1046
- if (suite.tasks.length && suite.tasks.every((i) => i.mode !== "run" && i.mode !== "queued")) {
1047
- suite.mode = "skip";
1048
- }
1049
- }
1050
- };
1051
- traverseSuite(file, parentIsOnly, false);
1052
- const nonMatching = testLocations === null || testLocations === void 0 ? void 0 : testLocations.filter((loc) => !matchedLocations.includes(loc));
1053
- if (nonMatching && nonMatching.length !== 0) {
1054
- const message = nonMatching.length === 1 ? `line ${nonMatching[0]}` : `lines ${nonMatching.join(", ")}`;
1055
- if (file.result === undefined) {
1056
- file.result = {
1057
- state: "fail",
1058
- errors: []
1059
- };
1060
- }
1061
- if (file.result.errors === undefined) {
1062
- file.result.errors = [];
1063
- }
1064
- file.result.errors.push(processError(new Error(`No test found in ${file.name} in ${message}`)));
1225
+ "fails"
1226
+ ], taskFn);
1227
+ if (context) {
1228
+ _test.mergeContext(context);
1065
1229
  }
1230
+ return _test;
1066
1231
  }
1067
- function getTaskFullName(task) {
1068
- return `${task.suite ? `${getTaskFullName(task.suite)} ` : ""}${task.name}`;
1232
+ function createTest(fn, context) {
1233
+ return createTaskCollector(fn, context);
1069
1234
  }
1070
- function someTasksAreOnly(suite) {
1071
- return suite.tasks.some((t) => t.mode === "only" || t.type === "suite" && someTasksAreOnly(t));
1235
+ function formatName(name) {
1236
+ return typeof name === "string" ? name : typeof name === "function" ? name.name || "<anonymous>" : String(name);
1072
1237
  }
1073
- function skipAllTasks(suite) {
1074
- suite.tasks.forEach((t) => {
1075
- if (t.mode === "run" || t.mode === "queued") {
1076
- t.mode = "skip";
1077
- if (t.type === "suite") {
1078
- skipAllTasks(t);
1238
+ function formatTitle(template, items, idx) {
1239
+ if (template.includes("%#") || template.includes("%$")) {
1240
+ // '%#' match index of the test case
1241
+ template = template.replace(/%%/g, "__vitest_escaped_%__").replace(/%#/g, `${idx}`).replace(/%\$/g, `${idx + 1}`).replace(/__vitest_escaped_%__/g, "%%");
1242
+ }
1243
+ const count = template.split("%").length - 1;
1244
+ if (template.includes("%f")) {
1245
+ const placeholders = template.match(/%f/g) || [];
1246
+ placeholders.forEach((_, i) => {
1247
+ if (isNegativeNaN(items[i]) || Object.is(items[i], -0)) {
1248
+ // Replace the i-th occurrence of '%f' with '-%f'
1249
+ let occurrence = 0;
1250
+ template = template.replace(/%f/g, (match) => {
1251
+ occurrence++;
1252
+ return occurrence === i + 1 ? "-%f" : match;
1253
+ });
1079
1254
  }
1255
+ });
1256
+ }
1257
+ let formatted = format(template, ...items.slice(0, count));
1258
+ const isObjectItem = isObject(items[0]);
1259
+ formatted = formatted.replace(/\$([$\w.]+)/g, (_, key) => {
1260
+ var _runner$config;
1261
+ const isArrayKey = /^\d+$/.test(key);
1262
+ if (!isObjectItem && !isArrayKey) {
1263
+ return `$${key}`;
1080
1264
  }
1265
+ const arrayElement = isArrayKey ? objectAttr(items, key) : undefined;
1266
+ const value = isObjectItem ? objectAttr(items[0], key, arrayElement) : arrayElement;
1267
+ return objDisplay(value, { truncate: runner === null || runner === void 0 || (_runner$config = runner.config) === null || _runner$config === void 0 || (_runner$config = _runner$config.chaiConfig) === null || _runner$config === void 0 ? void 0 : _runner$config.truncateThreshold });
1081
1268
  });
1269
+ return formatted;
1082
1270
  }
1083
- function todoAllTasks(suite) {
1084
- suite.tasks.forEach((t) => {
1085
- if (t.mode === "run" || t.mode === "queued") {
1086
- t.mode = "todo";
1087
- if (t.type === "suite") {
1088
- todoAllTasks(t);
1089
- }
1271
+ function formatTemplateString(cases, args) {
1272
+ const header = cases.join("").trim().replace(/ /g, "").split("\n").map((i) => i.split("|"))[0];
1273
+ const res = [];
1274
+ for (let i = 0; i < Math.floor(args.length / header.length); i++) {
1275
+ const oneCase = {};
1276
+ for (let j = 0; j < header.length; j++) {
1277
+ oneCase[header[j]] = args[i * header.length + j];
1090
1278
  }
1091
- });
1092
- }
1093
- function checkAllowOnly(task, allowOnly) {
1094
- if (allowOnly) {
1095
- return;
1096
- }
1097
- const error = processError(new Error("[Vitest] Unexpected .only modifier. Remove it or pass --allowOnly argument to bypass this error"));
1098
- task.result = {
1099
- state: "fail",
1100
- errors: [error]
1101
- };
1102
- }
1103
- function generateHash(str) {
1104
- let hash = 0;
1105
- if (str.length === 0) {
1106
- return `${hash}`;
1107
- }
1108
- for (let i = 0; i < str.length; i++) {
1109
- const char = str.charCodeAt(i);
1110
- hash = (hash << 5) - hash + char;
1111
- hash = hash & hash;
1279
+ res.push(oneCase);
1112
1280
  }
1113
- return `${hash}`;
1114
- }
1115
- function calculateSuiteHash(parent) {
1116
- parent.tasks.forEach((t, idx) => {
1117
- t.id = `${parent.id}_${idx}`;
1118
- if (t.type === "suite") {
1119
- calculateSuiteHash(t);
1120
- }
1121
- });
1122
- }
1123
- function createFileTask(filepath, root, projectName, pool) {
1124
- const path = relative(root, filepath);
1125
- const file = {
1126
- id: generateFileHash(path, projectName),
1127
- name: path,
1128
- type: "suite",
1129
- mode: "queued",
1130
- filepath,
1131
- tasks: [],
1132
- meta: Object.create(null),
1133
- projectName,
1134
- file: undefined,
1135
- pool
1136
- };
1137
- file.file = file;
1138
- setFileContext(file, Object.create(null));
1139
- return file;
1140
- }
1141
- /**
1142
- * Generate a unique ID for a file based on its path and project name
1143
- * @param file File relative to the root of the project to keep ID the same between different machines
1144
- * @param projectName The name of the test project
1145
- */
1146
- function generateFileHash(file, projectName) {
1147
- return generateHash(`${file}${projectName || ""}`);
1281
+ return res;
1148
1282
  }
1149
1283
 
1150
1284
  const now$2 = globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now;
@@ -1225,140 +1359,6 @@ function mergeHooks(baseHooks, hooks) {
1225
1359
  return baseHooks;
1226
1360
  }
1227
1361
 
1228
- /**
1229
- * Return a function for running multiple async operations with limited concurrency.
1230
- */
1231
- function limitConcurrency(concurrency = Infinity) {
1232
- // The number of currently active + pending tasks.
1233
- let count = 0;
1234
- // The head and tail of the pending task queue, built using a singly linked list.
1235
- // Both head and tail are initially undefined, signifying an empty queue.
1236
- // They both become undefined again whenever there are no pending tasks.
1237
- let head;
1238
- let tail;
1239
- // A bookkeeping function executed whenever a task has been run to completion.
1240
- const finish = () => {
1241
- count--;
1242
- // Check if there are further pending tasks in the queue.
1243
- if (head) {
1244
- // Allow the next pending task to run and pop it from the queue.
1245
- head[0]();
1246
- head = head[1];
1247
- // The head may now be undefined if there are no further pending tasks.
1248
- // In that case, set tail to undefined as well.
1249
- tail = head && tail;
1250
- }
1251
- };
1252
- return (func, ...args) => {
1253
- // Create a promise chain that:
1254
- // 1. Waits for its turn in the task queue (if necessary).
1255
- // 2. Runs the task.
1256
- // 3. Allows the next pending task (if any) to run.
1257
- return new Promise((resolve) => {
1258
- if (count++ < concurrency) {
1259
- // No need to queue if fewer than maxConcurrency tasks are running.
1260
- resolve();
1261
- } else if (tail) {
1262
- // There are pending tasks, so append to the queue.
1263
- tail = tail[1] = [resolve];
1264
- } else {
1265
- // No other pending tasks, initialize the queue with a new tail and head.
1266
- head = tail = [resolve];
1267
- }
1268
- }).then(() => {
1269
- // Running func here ensures that even a non-thenable result or an
1270
- // immediately thrown error gets wrapped into a Promise.
1271
- return func(...args);
1272
- }).finally(finish);
1273
- };
1274
- }
1275
-
1276
- /**
1277
- * Partition in tasks groups by consecutive concurrent
1278
- */
1279
- function partitionSuiteChildren(suite) {
1280
- let tasksGroup = [];
1281
- const tasksGroups = [];
1282
- for (const c of suite.tasks) {
1283
- if (tasksGroup.length === 0 || c.concurrent === tasksGroup[0].concurrent) {
1284
- tasksGroup.push(c);
1285
- } else {
1286
- tasksGroups.push(tasksGroup);
1287
- tasksGroup = [c];
1288
- }
1289
- }
1290
- if (tasksGroup.length > 0) {
1291
- tasksGroups.push(tasksGroup);
1292
- }
1293
- return tasksGroups;
1294
- }
1295
-
1296
- /**
1297
- * @deprecated use `isTestCase` instead
1298
- */
1299
- function isAtomTest(s) {
1300
- return isTestCase(s);
1301
- }
1302
- function isTestCase(s) {
1303
- return s.type === "test";
1304
- }
1305
- function getTests(suite) {
1306
- const tests = [];
1307
- const arraySuites = toArray(suite);
1308
- for (const s of arraySuites) {
1309
- if (isTestCase(s)) {
1310
- tests.push(s);
1311
- } else {
1312
- for (const task of s.tasks) {
1313
- if (isTestCase(task)) {
1314
- tests.push(task);
1315
- } else {
1316
- const taskTests = getTests(task);
1317
- for (const test of taskTests) {
1318
- tests.push(test);
1319
- }
1320
- }
1321
- }
1322
- }
1323
- }
1324
- return tests;
1325
- }
1326
- function getTasks(tasks = []) {
1327
- return toArray(tasks).flatMap((s) => isTestCase(s) ? [s] : [s, ...getTasks(s.tasks)]);
1328
- }
1329
- function getSuites(suite) {
1330
- return toArray(suite).flatMap((s) => s.type === "suite" ? [s, ...getSuites(s.tasks)] : []);
1331
- }
1332
- function hasTests(suite) {
1333
- return toArray(suite).some((s) => s.tasks.some((c) => isTestCase(c) || hasTests(c)));
1334
- }
1335
- function hasFailed(suite) {
1336
- return toArray(suite).some((s) => {
1337
- var _s$result;
1338
- return ((_s$result = s.result) === null || _s$result === void 0 ? void 0 : _s$result.state) === "fail" || s.type === "suite" && hasFailed(s.tasks);
1339
- });
1340
- }
1341
- function getNames(task) {
1342
- const names = [task.name];
1343
- let current = task;
1344
- while (current === null || current === void 0 ? void 0 : current.suite) {
1345
- current = current.suite;
1346
- if (current === null || current === void 0 ? void 0 : current.name) {
1347
- names.unshift(current.name);
1348
- }
1349
- }
1350
- if (current !== task.file) {
1351
- names.unshift(task.file.name);
1352
- }
1353
- return names;
1354
- }
1355
- function getFullName(task, separator = " > ") {
1356
- return getNames(task).join(separator);
1357
- }
1358
- function getTestName(task, separator = " > ") {
1359
- return getNames(task).slice(1).join(separator);
1360
- }
1361
-
1362
1362
  const now$1 = globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now;
1363
1363
  const unixNow = Date.now;
1364
1364
  const { clearTimeout, setTimeout } = getSafeTimers();
@@ -1974,16 +1974,13 @@ function createTestContext(test, runner) {
1974
1974
  if (test.result && test.result.state !== "run") {
1975
1975
  throw new Error(`Cannot annotate tests outside of the test run. The test "${test.name}" finished running with the "${test.result.state}" state already.`);
1976
1976
  }
1977
+ const stack = findTestFileStackTrace(test.file.filepath, new Error("STACK_TRACE").stack);
1977
1978
  let location;
1978
- const stack = new Error("STACK_TRACE").stack;
1979
- const index = stack.includes("STACK_TRACE") ? 2 : 1;
1980
- const stackLine = stack.split("\n")[index];
1981
- const parsed = parseSingleStack(stackLine);
1982
- if (parsed) {
1979
+ if (stack) {
1983
1980
  location = {
1984
- file: parsed.file,
1985
- line: parsed.line,
1986
- column: parsed.column
1981
+ file: stack.file,
1982
+ line: stack.line,
1983
+ column: stack.column
1987
1984
  };
1988
1985
  }
1989
1986
  if (typeof type === "object") {
@@ -2251,4 +2248,4 @@ function createTestHook(name, handler) {
2251
2248
  };
2252
2249
  }
2253
2250
 
2254
- export { someTasksAreOnly as A, limitConcurrency as B, partitionSuiteChildren as C, getFullName as D, getNames as E, getSuites as F, getTasks as G, getTestName as H, getTests as I, hasFailed as J, hasTests as K, isAtomTest as L, isTestCase as M, afterAll as a, afterEach as b, beforeAll as c, beforeEach as d, onTestFinished as e, getHooks as f, getFn as g, setHooks as h, startTests as i, createTaskCollector as j, describe as k, getCurrentSuite as l, it as m, suite as n, onTestFailed as o, publicCollect as p, getCurrentTest as q, createChainable as r, setFn as s, test as t, updateTask as u, calculateSuiteHash as v, createFileTask as w, generateFileHash as x, generateHash as y, interpretTaskModes as z };
2251
+ export { interpretTaskModes as A, someTasksAreOnly as B, limitConcurrency as C, partitionSuiteChildren as D, getFullName as E, getNames as F, getSuites as G, getTasks as H, getTestName as I, getTests as J, hasFailed as K, hasTests as L, isAtomTest as M, isTestCase as N, afterAll as a, afterEach as b, beforeAll as c, beforeEach as d, onTestFinished as e, getHooks as f, getFn as g, setHooks as h, startTests as i, createTaskCollector as j, describe as k, getCurrentSuite as l, it as m, suite as n, onTestFailed as o, publicCollect as p, getCurrentTest as q, createChainable as r, setFn as s, test as t, updateTask as u, calculateSuiteHash as v, createFileTask as w, findTestFileStackTrace as x, generateFileHash as y, generateHash as z };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AfterAllListener, b as AfterEachListener, B as BeforeAllListener, d as BeforeEachListener, e as TaskHook, O as OnTestFailedHandler, f as OnTestFinishedHandler, a as Test, S as Suite, g as SuiteHooks, F as File, h as TaskUpdateEvent, T as Task, i as TestAPI, j as SuiteAPI, k as SuiteCollector } from './tasks.d-BPS2nWLO.js';
2
- export { l as Fixture, m as FixtureFn, n as FixtureOptions, o as Fixtures, H as HookCleanupCallback, p as HookListener, I as ImportDuration, q as InferFixturesTypes, R as RunMode, r as RuntimeContext, s as SequenceHooks, t as SequenceSetupFiles, u as SuiteFactory, v as TaskBase, w as TaskCustomOptions, x as TaskEventPack, y as TaskMeta, z as TaskPopulated, D as TaskResult, E as TaskResultPack, G as TaskState, J as TestAnnotation, K as TestAnnotationLocation, L as TestAttachment, M as TestContext, N as TestFunction, P as TestOptions, U as Use } from './tasks.d-BPS2nWLO.js';
1
+ import { A as AfterAllListener, b as AfterEachListener, B as BeforeAllListener, d as BeforeEachListener, e as TaskHook, O as OnTestFailedHandler, f as OnTestFinishedHandler, a as Test, S as Suite, g as SuiteHooks, F as File, h as TaskUpdateEvent, T as Task, i as TestAPI, j as SuiteAPI, k as SuiteCollector } from './tasks.d-B1vSIWO6.js';
2
+ export { l as Fixture, m as FixtureFn, n as FixtureOptions, o as Fixtures, H as HookCleanupCallback, p as HookListener, I as ImportDuration, q as InferFixturesTypes, R as RunMode, r as RuntimeContext, s as SequenceHooks, t as SequenceSetupFiles, u as SuiteFactory, v as TaskBase, w as TaskCustomOptions, x as TaskEventPack, y as TaskMeta, z as TaskPopulated, D as TaskResult, E as TaskResultPack, G as TaskState, J as TestAnnotation, K as TestAnnotationLocation, L as TestAttachment, M as TestContext, N as TestFunction, P as TestOptions, U as Use } from './tasks.d-B1vSIWO6.js';
3
3
  import { Awaitable } from '@vitest/utils';
4
4
  import { FileSpecification, VitestRunner } from './types.js';
5
5
  export { CancelReason, VitestRunnerConfig, VitestRunnerConstructor, VitestRunnerImportSource } from './types.js';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { a as afterAll, b as afterEach, c as beforeAll, d as beforeEach, p as collectTests, j as createTaskCollector, k as describe, l as getCurrentSuite, q as getCurrentTest, g as getFn, f as getHooks, m as it, o as onTestFailed, e as onTestFinished, s as setFn, h as setHooks, i as startTests, n as suite, t as test, u as updateTask } from './chunk-hooks.js';
2
2
  export { processError } from '@vitest/utils/error';
3
3
  import '@vitest/utils';
4
- import '@vitest/utils/source-map';
5
4
  import 'strip-literal';
5
+ import '@vitest/utils/source-map';
6
6
  import 'pathe';
@@ -19,7 +19,7 @@ type ChainableFunction<
19
19
  F extends (...args: any) => any,
20
20
  C = object
21
21
  > = F & { [x in T] : ChainableFunction<T, F, C> } & {
22
- fn: (this: Record<T, any>, ...args: Parameters<F>) => ReturnType<F>
22
+ fn: (this: Record<T, any>, ...args: Parameters<F>) => ReturnType<F>;
23
23
  } & C;
24
24
  declare function createChainable<
25
25
  T extends string,
@@ -92,8 +92,8 @@ interface TaskBase {
92
92
  * and parsing the stack trace, so the location might differ depending on the runtime.
93
93
  */
94
94
  location?: {
95
- line: number
96
- column: number
95
+ line: number;
96
+ column: number;
97
97
  };
98
98
  }
99
99
  interface TaskPopulated extends TaskBase {
@@ -247,17 +247,17 @@ type Task = Test | Suite | File;
247
247
  type TestFunction<ExtraContext = object> = (context: TestContext & ExtraContext) => Awaitable<any> | void;
248
248
  // jest's ExtractEachCallbackArgs
249
249
  type ExtractEachCallbackArgs<T extends ReadonlyArray<any>> = {
250
- 1: [T[0]]
251
- 2: [T[0], T[1]]
252
- 3: [T[0], T[1], T[2]]
253
- 4: [T[0], T[1], T[2], T[3]]
254
- 5: [T[0], T[1], T[2], T[3], T[4]]
255
- 6: [T[0], T[1], T[2], T[3], T[4], T[5]]
256
- 7: [T[0], T[1], T[2], T[3], T[4], T[5], T[6]]
257
- 8: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7]]
258
- 9: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8]]
259
- 10: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9]]
260
- fallback: Array<T extends ReadonlyArray<infer U> ? U : any>
250
+ 1: [T[0]];
251
+ 2: [T[0], T[1]];
252
+ 3: [T[0], T[1], T[2]];
253
+ 4: [T[0], T[1], T[2], T[3]];
254
+ 5: [T[0], T[1], T[2], T[3], T[4]];
255
+ 6: [T[0], T[1], T[2], T[3], T[4], T[5]];
256
+ 7: [T[0], T[1], T[2], T[3], T[4], T[5], T[6]];
257
+ 8: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7]];
258
+ 9: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8]];
259
+ 10: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9]];
260
+ fallback: Array<T extends ReadonlyArray<infer U> ? U : any>;
261
261
  }[T extends Readonly<[any]> ? 1 : T extends Readonly<[any, any]> ? 2 : T extends Readonly<[any, any, any]> ? 3 : T extends Readonly<[any, any, any, any]> ? 4 : T extends Readonly<[any, any, any, any, any]> ? 5 : T extends Readonly<[any, any, any, any, any, any]> ? 6 : T extends Readonly<[any, any, any, any, any, any, any]> ? 7 : T extends Readonly<[any, any, any, any, any, any, any, any]> ? 8 : T extends Readonly<[any, any, any, any, any, any, any, any, any]> ? 9 : T extends Readonly<[any, any, any, any, any, any, any, any, any, any]> ? 10 : "fallback"];
262
262
  interface EachFunctionReturn<T extends any[]> {
263
263
  /**
@@ -304,8 +304,8 @@ interface TestCollectorCallable<C = object> {
304
304
  <ExtraContext extends C>(name: string | Function, options?: TestCollectorOptions, fn?: TestFunction<ExtraContext>): void;
305
305
  }
306
306
  type ChainableTestAPI<ExtraContext = object> = ChainableFunction<"concurrent" | "sequential" | "only" | "skip" | "todo" | "fails", TestCollectorCallable<ExtraContext>, {
307
- each: TestEachFunction
308
- for: TestForFunction<ExtraContext>
307
+ each: TestEachFunction;
308
+ for: TestForFunction<ExtraContext>;
309
309
  }>;
310
310
  type TestCollectorOptions = Omit<TestOptions, "shuffle">;
311
311
  interface TestOptions {
@@ -363,8 +363,8 @@ interface ExtendedAPI<ExtraContext> {
363
363
  runIf: (condition: any) => ChainableTestAPI<ExtraContext>;
364
364
  }
365
365
  type TestAPI<ExtraContext = object> = ChainableTestAPI<ExtraContext> & ExtendedAPI<ExtraContext> & {
366
- extend: <T extends Record<string, any> = object>(fixtures: Fixtures<T, ExtraContext>) => TestAPI<{ [K in keyof T | keyof ExtraContext] : K extends keyof T ? T[K] : K extends keyof ExtraContext ? ExtraContext[K] : never }>
367
- scoped: (fixtures: Fixtures<Partial<ExtraContext>>) => void
366
+ extend: <T extends Record<string, any> = object>(fixtures: Fixtures<T, ExtraContext>) => TestAPI<{ [K in keyof T | keyof ExtraContext] : K extends keyof T ? T[K] : K extends keyof ExtraContext ? ExtraContext[K] : never }>;
367
+ scoped: (fixtures: Fixtures<Partial<ExtraContext>>) => void;
368
368
  };
369
369
  interface FixtureOptions {
370
370
  /**
@@ -412,12 +412,12 @@ interface SuiteCollectorCallable<ExtraContext = object> {
412
412
  <OverrideExtraContext extends ExtraContext = ExtraContext>(name: string | Function, options: TestOptions, fn?: SuiteFactory<OverrideExtraContext>): SuiteCollector<OverrideExtraContext>;
413
413
  }
414
414
  type ChainableSuiteAPI<ExtraContext = object> = ChainableFunction<"concurrent" | "sequential" | "only" | "skip" | "todo" | "shuffle", SuiteCollectorCallable<ExtraContext>, {
415
- each: TestEachFunction
416
- for: SuiteForFunction
415
+ each: TestEachFunction;
416
+ for: SuiteForFunction;
417
417
  }>;
418
418
  type SuiteAPI<ExtraContext = object> = ChainableSuiteAPI<ExtraContext> & {
419
- skipIf: (condition: any) => ChainableSuiteAPI<ExtraContext>
420
- runIf: (condition: any) => ChainableSuiteAPI<ExtraContext>
419
+ skipIf: (condition: any) => ChainableSuiteAPI<ExtraContext>;
420
+ runIf: (condition: any) => ChainableSuiteAPI<ExtraContext>;
421
421
  };
422
422
  /**
423
423
  * @deprecated
@@ -518,16 +518,16 @@ interface TestContext {
518
518
  * @see {@link https://vitest.dev/guide/test-context#skip}
519
519
  */
520
520
  readonly skip: {
521
- (note?: string): never
522
- (condition: boolean, note?: string): void
521
+ (note?: string): never;
522
+ (condition: boolean, note?: string): void;
523
523
  };
524
524
  /**
525
525
  * Add a test annotation that will be displayed by your reporter.
526
526
  * @see {@link https://vitest.dev/guide/test-context#annotate}
527
527
  */
528
528
  readonly annotate: {
529
- (message: string, type?: string, attachment?: TestAttachment): Promise<TestAnnotation>
530
- (message: string, attachment?: TestAttachment): Promise<TestAnnotation>
529
+ (message: string, type?: string, attachment?: TestAttachment): Promise<TestAnnotation>;
530
+ (message: string, attachment?: TestAttachment): Promise<TestAnnotation>;
531
531
  };
532
532
  }
533
533
  type OnTestFailedHandler = (context: TestContext) => Awaitable<void>;
package/dist/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DiffOptions } from '@vitest/utils/diff';
2
- import { F as File, a as Test, S as Suite, E as TaskResultPack, x as TaskEventPack, J as TestAnnotation, M as TestContext, I as ImportDuration, s as SequenceHooks, t as SequenceSetupFiles } from './tasks.d-BPS2nWLO.js';
3
- export { A as AfterAllListener, b as AfterEachListener, B as BeforeAllListener, d as BeforeEachListener, l as Fixture, m as FixtureFn, n as FixtureOptions, o as Fixtures, H as HookCleanupCallback, p as HookListener, q as InferFixturesTypes, O as OnTestFailedHandler, f as OnTestFinishedHandler, R as RunMode, r as RuntimeContext, j as SuiteAPI, k as SuiteCollector, u as SuiteFactory, g as SuiteHooks, T as Task, v as TaskBase, w as TaskCustomOptions, e as TaskHook, y as TaskMeta, z as TaskPopulated, D as TaskResult, G as TaskState, h as TaskUpdateEvent, i as TestAPI, K as TestAnnotationLocation, L as TestAttachment, N as TestFunction, P as TestOptions, U as Use } from './tasks.d-BPS2nWLO.js';
2
+ import { F as File, a as Test, S as Suite, E as TaskResultPack, x as TaskEventPack, J as TestAnnotation, M as TestContext, I as ImportDuration, s as SequenceHooks, t as SequenceSetupFiles } from './tasks.d-B1vSIWO6.js';
3
+ export { A as AfterAllListener, b as AfterEachListener, B as BeforeAllListener, d as BeforeEachListener, l as Fixture, m as FixtureFn, n as FixtureOptions, o as Fixtures, H as HookCleanupCallback, p as HookListener, q as InferFixturesTypes, O as OnTestFailedHandler, f as OnTestFinishedHandler, R as RunMode, r as RuntimeContext, j as SuiteAPI, k as SuiteCollector, u as SuiteFactory, g as SuiteHooks, T as Task, v as TaskBase, w as TaskCustomOptions, e as TaskHook, y as TaskMeta, z as TaskPopulated, D as TaskResult, G as TaskState, h as TaskUpdateEvent, i as TestAPI, K as TestAnnotationLocation, L as TestAttachment, N as TestFunction, P as TestOptions, U as Use } from './tasks.d-B1vSIWO6.js';
4
4
  import '@vitest/utils';
5
5
 
6
6
  /**
@@ -14,14 +14,14 @@ interface VitestRunnerConfig {
14
14
  testNamePattern?: RegExp;
15
15
  allowOnly?: boolean;
16
16
  sequence: {
17
- shuffle?: boolean
18
- concurrent?: boolean
19
- seed: number
20
- hooks: SequenceHooks
21
- setupFiles: SequenceSetupFiles
17
+ shuffle?: boolean;
18
+ concurrent?: boolean;
19
+ seed: number;
20
+ hooks: SequenceHooks;
21
+ setupFiles: SequenceSetupFiles;
22
22
  };
23
23
  chaiConfig?: {
24
- truncateThreshold?: number
24
+ truncateThreshold?: number;
25
25
  };
26
26
  maxConcurrency: number;
27
27
  testTimeout: number;
@@ -69,8 +69,8 @@ interface VitestRunner {
69
69
  * Called before actually running the test function. Already has "result" with "state" and "startTime".
70
70
  */
71
71
  onBeforeTryTask?: (test: Test, options: {
72
- retry: number
73
- repeats: number
72
+ retry: number;
73
+ repeats: number;
74
74
  }) => unknown;
75
75
  /**
76
76
  * When the task has finished running, but before cleanup hooks are called
@@ -84,8 +84,8 @@ interface VitestRunner {
84
84
  * Called right after running the test function. Doesn't have new state yet. Will not be called, if the test function throws.
85
85
  */
86
86
  onAfterTryTask?: (test: Test, options: {
87
- retry: number
88
- repeats: number
87
+ retry: number;
88
+ repeats: number;
89
89
  }) => unknown;
90
90
  /**
91
91
  * Called before running a single suite. Doesn't have "result" yet.
package/dist/utils.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { S as Suite, F as File, T as Task, a as Test } from './tasks.d-BPS2nWLO.js';
2
- export { C as ChainableFunction, c as createChainable } from './tasks.d-BPS2nWLO.js';
3
- import { Arrayable } from '@vitest/utils';
1
+ import { S as Suite, F as File, T as Task, a as Test } from './tasks.d-B1vSIWO6.js';
2
+ export { C as ChainableFunction, c as createChainable } from './tasks.d-B1vSIWO6.js';
3
+ import { ParsedStack, Arrayable } from '@vitest/utils';
4
4
 
5
5
  /**
6
6
  * If any tasks been marked as `only`, mark all other tasks as `skip`.
@@ -16,6 +16,7 @@ declare function createFileTask(filepath: string, root: string, projectName: str
16
16
  * @param projectName The name of the test project
17
17
  */
18
18
  declare function generateFileHash(file: string, projectName: string | undefined): string;
19
+ declare function findTestFileStackTrace(testFilePath: string, error: string): ParsedStack | undefined;
19
20
 
20
21
  /**
21
22
  * Return a function for running multiple async operations with limited concurrency.
@@ -44,4 +45,4 @@ declare function getNames(task: Task): string[];
44
45
  declare function getFullName(task: Task, separator?: string): string;
45
46
  declare function getTestName(task: Task, separator?: string): string;
46
47
 
47
- export { calculateSuiteHash, createFileTask, generateFileHash, generateHash, getFullName, getNames, getSuites, getTasks, getTestName, getTests, hasFailed, hasTests, interpretTaskModes, isAtomTest, isTestCase, limitConcurrency, partitionSuiteChildren, someTasksAreOnly };
48
+ export { calculateSuiteHash, createFileTask, findTestFileStackTrace, generateFileHash, generateHash, getFullName, getNames, getSuites, getTasks, getTestName, getTests, hasFailed, hasTests, interpretTaskModes, isAtomTest, isTestCase, limitConcurrency, partitionSuiteChildren, someTasksAreOnly };
package/dist/utils.js CHANGED
@@ -1,6 +1,6 @@
1
- export { v as calculateSuiteHash, r as createChainable, w as createFileTask, x as generateFileHash, y as generateHash, D as getFullName, E as getNames, F as getSuites, G as getTasks, H as getTestName, I as getTests, J as hasFailed, K as hasTests, z as interpretTaskModes, L as isAtomTest, M as isTestCase, B as limitConcurrency, C as partitionSuiteChildren, A as someTasksAreOnly } from './chunk-hooks.js';
1
+ export { v as calculateSuiteHash, r as createChainable, w as createFileTask, x as findTestFileStackTrace, y as generateFileHash, z as generateHash, E as getFullName, F as getNames, G as getSuites, H as getTasks, I as getTestName, J as getTests, K as hasFailed, L as hasTests, A as interpretTaskModes, M as isAtomTest, N as isTestCase, C as limitConcurrency, D as partitionSuiteChildren, B as someTasksAreOnly } from './chunk-hooks.js';
2
2
  import '@vitest/utils';
3
- import '@vitest/utils/source-map';
4
3
  import '@vitest/utils/error';
5
4
  import 'strip-literal';
5
+ import '@vitest/utils/source-map';
6
6
  import 'pathe';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/runner",
3
3
  "type": "module",
4
- "version": "4.0.0-beta.2",
4
+ "version": "4.0.0-beta.4",
5
5
  "description": "Vitest test runner",
6
6
  "license": "MIT",
7
7
  "funding": "https://opencollective.com/vitest",
@@ -40,7 +40,7 @@
40
40
  "dependencies": {
41
41
  "pathe": "^2.0.3",
42
42
  "strip-literal": "^3.0.0",
43
- "@vitest/utils": "4.0.0-beta.2"
43
+ "@vitest/utils": "4.0.0-beta.4"
44
44
  },
45
45
  "scripts": {
46
46
  "build": "rimraf dist && rollup -c",