@vitest/runner 3.1.3 → 3.2.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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, g as Custom, S as Suite, h as SuiteHooks, F as File, i as TaskUpdateEvent, T as Task, j as TestAPI, k as SuiteAPI, l as SuiteCollector } from './tasks.d-hsdzc98-.js';
2
- export { D as DoneCallback, E as ExtendedContext, m as Fixture, n as FixtureFn, o as FixtureOptions, p as Fixtures, H as HookCleanupCallback, q as HookListener, I as InferFixturesTypes, R as RunMode, r as RuntimeContext, s as SequenceHooks, t as SequenceSetupFiles, u as SuiteFactory, v as TaskBase, w as TaskContext, x as TaskCustomOptions, y as TaskEventPack, z as TaskMeta, G as TaskPopulated, J as TaskResult, K as TaskResultPack, L as TaskState, M as TestContext, N as TestFunction, P as TestOptions, U as Use } from './tasks.d-hsdzc98-.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, g as Custom, S as Suite, h as SuiteHooks, F as File, i as TaskUpdateEvent, T as Task, j as TestAPI, k as SuiteAPI, l as SuiteCollector } from './tasks.d-hzpC0pGR.js';
2
+ export { D as DoneCallback, E as ExtendedContext, m as Fixture, n as FixtureFn, o as FixtureOptions, p as Fixtures, H as HookCleanupCallback, q as HookListener, I as InferFixturesTypes, R as RunMode, r as RuntimeContext, s as SequenceHooks, t as SequenceSetupFiles, u as SuiteFactory, v as TaskBase, w as TaskContext, x as TaskCustomOptions, y as TaskEventPack, z as TaskMeta, G as TaskPopulated, J as TaskResult, K as TaskResultPack, L as TaskState, M as TestContext, N as TestFunction, P as TestOptions, U as Use } from './tasks.d-hzpC0pGR.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
@@ -15,6 +15,14 @@ class PendingError extends Error {
15
15
  this.taskId = task.id;
16
16
  }
17
17
  }
18
+ class TestRunAbortError extends Error {
19
+ name = "TestRunAbortError";
20
+ reason;
21
+ constructor(message, reason) {
22
+ super(message);
23
+ this.reason = reason;
24
+ }
25
+ }
18
26
 
19
27
  const fnMap = new WeakMap();
20
28
  const testFixtureMap = new WeakMap();
@@ -240,6 +248,16 @@ function setCurrentTest(test) {
240
248
  function getCurrentTest() {
241
249
  return _test;
242
250
  }
251
+ const tests = [];
252
+ function addRunningTest(test) {
253
+ tests.push(test);
254
+ return () => {
255
+ tests.splice(tests.indexOf(test));
256
+ };
257
+ }
258
+ function getRunningTests() {
259
+ return tests;
260
+ }
243
261
 
244
262
  /**
245
263
  * Creates a suite of tests, allowing for grouping and hierarchical organization of tests.
@@ -481,7 +499,7 @@ function createSuiteCollector(name, factory = () => {}, mode, each, suiteOptions
481
499
  const stackTraceError = new Error("STACK_TRACE_ERROR");
482
500
  Error.stackTraceLimit = limit;
483
501
  if (handler) {
484
- setFn(task, withTimeout(withAwaitAsyncAssertions(withFixtures(handler, context), task), timeout, false, stackTraceError));
502
+ setFn(task, withTimeout(withAwaitAsyncAssertions(withFixtures(handler, context), task), timeout, false, stackTraceError, (_, error) => abortIfTimeout([context], error)));
485
503
  }
486
504
  if (runner.config.includeTaskLocation) {
487
505
  const error = stackTraceError.stack;
@@ -839,7 +857,7 @@ async function runWithSuite(suite, fn) {
839
857
  await fn();
840
858
  collectorContext.currentSuite = prev;
841
859
  }
842
- function withTimeout(fn, timeout, isHook = false, stackTraceError) {
860
+ function withTimeout(fn, timeout, isHook = false, stackTraceError, onTimeout) {
843
861
  if (timeout <= 0 || timeout === Number.POSITIVE_INFINITY) {
844
862
  return fn;
845
863
  }
@@ -857,7 +875,9 @@ function withTimeout(fn, timeout, isHook = false, stackTraceError) {
857
875
  }, timeout);
858
876
  (_timer$unref = timer.unref) === null || _timer$unref === void 0 ? void 0 : _timer$unref.call(timer);
859
877
  function rejectTimeoutError() {
860
- reject_(makeTimeoutError(isHook, timeout, stackTraceError));
878
+ const error = makeTimeoutError(isHook, timeout, stackTraceError);
879
+ onTimeout === null || onTimeout === void 0 ? void 0 : onTimeout(args, error);
880
+ reject_(error);
861
881
  }
862
882
  function resolve(result) {
863
883
  runner._currentTaskStartTime = undefined;
@@ -888,11 +908,27 @@ function withTimeout(fn, timeout, isHook = false, stackTraceError) {
888
908
  });
889
909
  };
890
910
  }
911
+ const abortControllers = new WeakMap();
912
+ function abortIfTimeout([context], error) {
913
+ if (context) {
914
+ abortContextSignal(context, error);
915
+ }
916
+ }
917
+ function abortContextSignal(context, error) {
918
+ const abortController = abortControllers.get(context);
919
+ abortController === null || abortController === void 0 ? void 0 : abortController.abort(error);
920
+ }
891
921
  function createTestContext(test, runner) {
892
922
  var _runner$extendTaskCon;
893
923
  const context = function() {
894
924
  throw new Error("done() callback is deprecated, use promise instead");
895
925
  };
926
+ let abortController = abortControllers.get(context);
927
+ if (!abortController) {
928
+ abortController = new AbortController();
929
+ abortControllers.set(context, abortController);
930
+ }
931
+ context.signal = abortController.signal;
896
932
  context.task = test;
897
933
  context.skip = (condition, note) => {
898
934
  if (condition === false) {
@@ -904,11 +940,11 @@ function createTestContext(test, runner) {
904
940
  };
905
941
  context.onTestFailed = (handler, timeout) => {
906
942
  test.onFailed || (test.onFailed = []);
907
- test.onFailed.push(withTimeout(handler, timeout ?? runner.config.hookTimeout, true, new Error("STACK_TRACE_ERROR")));
943
+ test.onFailed.push(withTimeout(handler, timeout ?? runner.config.hookTimeout, true, new Error("STACK_TRACE_ERROR"), (_, error) => abortController.abort(error)));
908
944
  };
909
945
  context.onTestFinished = (handler, timeout) => {
910
946
  test.onFinished || (test.onFinished = []);
911
- test.onFinished.push(withTimeout(handler, timeout ?? runner.config.hookTimeout, true, new Error("STACK_TRACE_ERROR")));
947
+ test.onFinished.push(withTimeout(handler, timeout ?? runner.config.hookTimeout, true, new Error("STACK_TRACE_ERROR"), (_, error) => abortController.abort(error)));
912
948
  };
913
949
  return ((_runner$extendTaskCon = runner.extendTaskContext) === null || _runner$extendTaskCon === void 0 ? void 0 : _runner$extendTaskCon.call(runner, context)) || context;
914
950
  }
@@ -926,11 +962,15 @@ function getDefaultHookTimeout() {
926
962
  }
927
963
  const CLEANUP_TIMEOUT_KEY = Symbol.for("VITEST_CLEANUP_TIMEOUT");
928
964
  const CLEANUP_STACK_TRACE_KEY = Symbol.for("VITEST_CLEANUP_STACK_TRACE");
929
- function getBeforeHookCleanupCallback(hook, result) {
965
+ function getBeforeHookCleanupCallback(hook, result, context) {
930
966
  if (typeof result === "function") {
931
967
  const timeout = CLEANUP_TIMEOUT_KEY in hook && typeof hook[CLEANUP_TIMEOUT_KEY] === "number" ? hook[CLEANUP_TIMEOUT_KEY] : getDefaultHookTimeout();
932
968
  const stackTraceError = CLEANUP_STACK_TRACE_KEY in hook && hook[CLEANUP_STACK_TRACE_KEY] instanceof Error ? hook[CLEANUP_STACK_TRACE_KEY] : undefined;
933
- return withTimeout(result, timeout, true, stackTraceError);
969
+ return withTimeout(result, timeout, true, stackTraceError, (_, error) => {
970
+ if (context) {
971
+ abortContextSignal(context, error);
972
+ }
973
+ });
934
974
  }
935
975
  }
936
976
  /**
@@ -999,7 +1039,7 @@ function afterAll(fn, timeout) {
999
1039
  function beforeEach(fn, timeout = getDefaultHookTimeout()) {
1000
1040
  assertTypes(fn, "\"beforeEach\" callback", ["function"]);
1001
1041
  const stackTraceError = new Error("STACK_TRACE_ERROR");
1002
- return getCurrentSuite().on("beforeEach", Object.assign(withTimeout(withFixtures(fn), timeout ?? getDefaultHookTimeout(), true, stackTraceError), {
1042
+ return getCurrentSuite().on("beforeEach", Object.assign(withTimeout(withFixtures(fn), timeout ?? getDefaultHookTimeout(), true, stackTraceError, abortIfTimeout), {
1003
1043
  [CLEANUP_TIMEOUT_KEY]: timeout,
1004
1044
  [CLEANUP_STACK_TRACE_KEY]: stackTraceError
1005
1045
  }));
@@ -1023,7 +1063,7 @@ function beforeEach(fn, timeout = getDefaultHookTimeout()) {
1023
1063
  */
1024
1064
  function afterEach(fn, timeout) {
1025
1065
  assertTypes(fn, "\"afterEach\" callback", ["function"]);
1026
- return getCurrentSuite().on("afterEach", withTimeout(withFixtures(fn), timeout ?? getDefaultHookTimeout(), true, new Error("STACK_TRACE_ERROR")));
1066
+ return getCurrentSuite().on("afterEach", withTimeout(withFixtures(fn), timeout ?? getDefaultHookTimeout(), true, new Error("STACK_TRACE_ERROR"), abortIfTimeout));
1027
1067
  }
1028
1068
  /**
1029
1069
  * Registers a callback function to be executed when a test fails within the current suite.
@@ -1045,7 +1085,7 @@ function afterEach(fn, timeout) {
1045
1085
  */
1046
1086
  const onTestFailed = createTestHook("onTestFailed", (test, handler, timeout) => {
1047
1087
  test.onFailed || (test.onFailed = []);
1048
- test.onFailed.push(withTimeout(handler, timeout ?? getDefaultHookTimeout(), true, new Error("STACK_TRACE_ERROR")));
1088
+ test.onFailed.push(withTimeout(handler, timeout ?? getDefaultHookTimeout(), true, new Error("STACK_TRACE_ERROR"), abortIfTimeout));
1049
1089
  });
1050
1090
  /**
1051
1091
  * Registers a callback function to be executed when the current test finishes, regardless of the outcome (pass or fail).
@@ -1072,7 +1112,7 @@ const onTestFailed = createTestHook("onTestFailed", (test, handler, timeout) =>
1072
1112
  */
1073
1113
  const onTestFinished = createTestHook("onTestFinished", (test, handler, timeout) => {
1074
1114
  test.onFinished || (test.onFinished = []);
1075
- test.onFinished.push(withTimeout(handler, timeout ?? getDefaultHookTimeout(), true, new Error("STACK_TRACE_ERROR")));
1115
+ test.onFinished.push(withTimeout(handler, timeout ?? getDefaultHookTimeout(), true, new Error("STACK_TRACE_ERROR"), abortIfTimeout));
1076
1116
  });
1077
1117
  function createTestHook(name, handler) {
1078
1118
  return (fn, timeout) => {
@@ -1197,12 +1237,13 @@ async function callTestHooks(runner, test, hooks, sequence) {
1197
1237
  if (!hooks.length) {
1198
1238
  return;
1199
1239
  }
1240
+ const context = test.context;
1200
1241
  const onTestFailed = test.context.onTestFailed;
1201
1242
  const onTestFinished = test.context.onTestFinished;
1202
- test.context.onTestFailed = () => {
1243
+ context.onTestFailed = () => {
1203
1244
  throw new Error(`Cannot call "onTestFailed" inside a test hook.`);
1204
1245
  };
1205
- test.context.onTestFinished = () => {
1246
+ context.onTestFinished = () => {
1206
1247
  throw new Error(`Cannot call "onTestFinished" inside a test hook.`);
1207
1248
  };
1208
1249
  if (sequence === "parallel") {
@@ -1220,8 +1261,8 @@ async function callTestHooks(runner, test, hooks, sequence) {
1220
1261
  }
1221
1262
  }
1222
1263
  }
1223
- test.context.onTestFailed = onTestFailed;
1224
- test.context.onTestFinished = onTestFinished;
1264
+ context.onTestFailed = onTestFailed;
1265
+ context.onTestFinished = onTestFinished;
1225
1266
  }
1226
1267
  async function callSuiteHook(suite, currentTask, name, runner, args) {
1227
1268
  const sequence = runner.config.sequence.hooks;
@@ -1235,7 +1276,7 @@ async function callSuiteHook(suite, currentTask, name, runner, args) {
1235
1276
  updateSuiteHookState(currentTask, name, "run", runner);
1236
1277
  }
1237
1278
  async function runHook(hook) {
1238
- return getBeforeHookCleanupCallback(hook, await hook(...args));
1279
+ return getBeforeHookCleanupCallback(hook, await hook(...args), name === "beforeEach" ? args[0] : undefined);
1239
1280
  }
1240
1281
  if (sequence === "parallel") {
1241
1282
  callbacks.push(...await Promise.all(hooks.map((hook) => runHook(hook))));
@@ -1334,6 +1375,7 @@ async function runTest(test, runner) {
1334
1375
  retryCount: 0
1335
1376
  };
1336
1377
  updateTask("test-prepare", test, runner);
1378
+ const cleanupRunningTest = addRunningTest(test);
1337
1379
  setCurrentTest(test);
1338
1380
  const suite = test.suite || test.file;
1339
1381
  const repeats = test.repeats ?? 0;
@@ -1403,6 +1445,7 @@ async function runTest(test, runner) {
1403
1445
  };
1404
1446
  updateTask("test-finished", test, runner);
1405
1447
  setCurrentTest(undefined);
1448
+ cleanupRunningTest();
1406
1449
  return;
1407
1450
  }
1408
1451
  if (test.result.state === "pass") {
@@ -1425,6 +1468,7 @@ async function runTest(test, runner) {
1425
1468
  test.result.errors = undefined;
1426
1469
  }
1427
1470
  }
1471
+ cleanupRunningTest();
1428
1472
  setCurrentTest(undefined);
1429
1473
  test.result.duration = now() - start;
1430
1474
  await ((_runner$onAfterRunTas = runner.onAfterRunTask) === null || _runner$onAfterRunTas === void 0 ? void 0 : _runner$onAfterRunTas.call(runner, test));
@@ -1562,16 +1606,27 @@ async function runFiles(files, runner) {
1562
1606
  }
1563
1607
  }
1564
1608
  async function startTests(specs, runner) {
1565
- var _runner$onBeforeColle, _runner$onCollected, _runner$onBeforeRunFi, _runner$onAfterRunFil;
1566
- const paths = specs.map((f) => typeof f === "string" ? f : f.filepath);
1567
- await ((_runner$onBeforeColle = runner.onBeforeCollect) === null || _runner$onBeforeColle === void 0 ? void 0 : _runner$onBeforeColle.call(runner, paths));
1568
- const files = await collectTests(specs, runner);
1569
- await ((_runner$onCollected = runner.onCollected) === null || _runner$onCollected === void 0 ? void 0 : _runner$onCollected.call(runner, files));
1570
- await ((_runner$onBeforeRunFi = runner.onBeforeRunFiles) === null || _runner$onBeforeRunFi === void 0 ? void 0 : _runner$onBeforeRunFi.call(runner, files));
1571
- await runFiles(files, runner);
1572
- await ((_runner$onAfterRunFil = runner.onAfterRunFiles) === null || _runner$onAfterRunFil === void 0 ? void 0 : _runner$onAfterRunFil.call(runner, files));
1573
- await finishSendTasksUpdate(runner);
1574
- return files;
1609
+ var _runner$cancel;
1610
+ const cancel = (_runner$cancel = runner.cancel) === null || _runner$cancel === void 0 ? void 0 : _runner$cancel.bind(runner);
1611
+ runner.cancel = (reason) => {
1612
+ const error = new TestRunAbortError("The test run was aborted by the user.", reason);
1613
+ getRunningTests().forEach((test) => abortContextSignal(test.context, error));
1614
+ return cancel === null || cancel === void 0 ? void 0 : cancel(reason);
1615
+ };
1616
+ try {
1617
+ var _runner$onBeforeColle, _runner$onCollected, _runner$onBeforeRunFi, _runner$onAfterRunFil;
1618
+ const paths = specs.map((f) => typeof f === "string" ? f : f.filepath);
1619
+ await ((_runner$onBeforeColle = runner.onBeforeCollect) === null || _runner$onBeforeColle === void 0 ? void 0 : _runner$onBeforeColle.call(runner, paths));
1620
+ const files = await collectTests(specs, runner);
1621
+ await ((_runner$onCollected = runner.onCollected) === null || _runner$onCollected === void 0 ? void 0 : _runner$onCollected.call(runner, files));
1622
+ await ((_runner$onBeforeRunFi = runner.onBeforeRunFiles) === null || _runner$onBeforeRunFi === void 0 ? void 0 : _runner$onBeforeRunFi.call(runner, files));
1623
+ await runFiles(files, runner);
1624
+ await ((_runner$onAfterRunFil = runner.onAfterRunFiles) === null || _runner$onAfterRunFil === void 0 ? void 0 : _runner$onAfterRunFil.call(runner, files));
1625
+ await finishSendTasksUpdate(runner);
1626
+ return files;
1627
+ } finally {
1628
+ runner.cancel = cancel;
1629
+ }
1575
1630
  }
1576
1631
  async function publicCollect(specs, runner) {
1577
1632
  var _runner$onBeforeColle2, _runner$onCollected2;
@@ -454,20 +454,25 @@ interface TestContext {
454
454
  /**
455
455
  * Metadata of the current test
456
456
  */
457
- task: Readonly<Test<TestContext>>;
457
+ readonly task: Readonly<Test>;
458
+ /**
459
+ * An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that will be aborted if the test times out or
460
+ * the test run was cancelled.
461
+ */
462
+ readonly signal: AbortSignal;
458
463
  /**
459
464
  * Extract hooks on test failed
460
465
  */
461
- onTestFailed: (fn: OnTestFailedHandler, timeout?: number) => void;
466
+ readonly onTestFailed: (fn: OnTestFailedHandler, timeout?: number) => void;
462
467
  /**
463
468
  * Extract hooks on test failed
464
469
  */
465
- onTestFinished: (fn: OnTestFinishedHandler, timeout?: number) => void;
470
+ readonly onTestFinished: (fn: OnTestFinishedHandler, timeout?: number) => void;
466
471
  /**
467
472
  * Mark tests as skipped. All execution after this call will be skipped.
468
473
  * This function throws an error, so make sure you are not catching it accidentally.
469
474
  */
470
- skip: {
475
+ readonly skip: {
471
476
  (note?: string): never
472
477
  (condition: boolean, note?: string): void
473
478
  };
package/dist/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DiffOptions } from '@vitest/utils/diff';
2
- import { F as File, T as Task, a as Test, S as Suite, K as TaskResultPack, y as TaskEventPack, M as TestContext, s as SequenceHooks, t as SequenceSetupFiles } from './tasks.d-hsdzc98-.js';
3
- export { A as AfterAllListener, b as AfterEachListener, B as BeforeAllListener, d as BeforeEachListener, g as Custom, j as CustomAPI, D as DoneCallback, E as ExtendedContext, m as Fixture, n as FixtureFn, o as FixtureOptions, p as Fixtures, H as HookCleanupCallback, q as HookListener, I as InferFixturesTypes, O as OnTestFailedHandler, f as OnTestFinishedHandler, R as RunMode, r as RuntimeContext, k as SuiteAPI, l as SuiteCollector, u as SuiteFactory, h as SuiteHooks, v as TaskBase, w as TaskContext, x as TaskCustomOptions, e as TaskHook, z as TaskMeta, G as TaskPopulated, J as TaskResult, L as TaskState, i as TaskUpdateEvent, j as TestAPI, N as TestFunction, P as TestOptions, U as Use } from './tasks.d-hsdzc98-.js';
2
+ import { F as File, T as Task, a as Test, S as Suite, K as TaskResultPack, y as TaskEventPack, M as TestContext, s as SequenceHooks, t as SequenceSetupFiles } from './tasks.d-hzpC0pGR.js';
3
+ export { A as AfterAllListener, b as AfterEachListener, B as BeforeAllListener, d as BeforeEachListener, g as Custom, j as CustomAPI, D as DoneCallback, E as ExtendedContext, m as Fixture, n as FixtureFn, o as FixtureOptions, p as Fixtures, H as HookCleanupCallback, q as HookListener, I as InferFixturesTypes, O as OnTestFailedHandler, f as OnTestFinishedHandler, R as RunMode, r as RuntimeContext, k as SuiteAPI, l as SuiteCollector, u as SuiteFactory, h as SuiteHooks, v as TaskBase, w as TaskContext, x as TaskCustomOptions, e as TaskHook, z as TaskMeta, G as TaskPopulated, J as TaskResult, L as TaskState, i as TaskUpdateEvent, j as TestAPI, N as TestFunction, P as TestOptions, U as Use } from './tasks.d-hzpC0pGR.js';
4
4
  import '@vitest/utils';
5
5
 
6
6
  /**
@@ -60,7 +60,7 @@ interface VitestRunner {
60
60
  * Runner should listen for this method and mark tests and suites as skipped in
61
61
  * "onBeforeRunSuite" and "onBeforeRunTask" when called.
62
62
  */
63
- onCancel?: (reason: CancelReason) => unknown;
63
+ cancel?: (reason: CancelReason) => unknown;
64
64
  /**
65
65
  * Called before running a single test. Doesn't have "result" yet.
66
66
  */
package/dist/utils.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as Suite, F as File, T as Task, a as Test } from './tasks.d-hsdzc98-.js';
2
- export { C as ChainableFunction, c as createChainable } from './tasks.d-hsdzc98-.js';
1
+ import { S as Suite, F as File, T as Task, a as Test } from './tasks.d-hzpC0pGR.js';
2
+ export { C as ChainableFunction, c as createChainable } from './tasks.d-hzpC0pGR.js';
3
3
  import { Arrayable } from '@vitest/utils';
4
4
 
5
5
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/runner",
3
3
  "type": "module",
4
- "version": "3.1.3",
4
+ "version": "3.2.0-beta.1",
5
5
  "description": "Vitest test runner",
6
6
  "license": "MIT",
7
7
  "funding": "https://opencollective.com/vitest",
@@ -39,7 +39,7 @@
39
39
  ],
40
40
  "dependencies": {
41
41
  "pathe": "^2.0.3",
42
- "@vitest/utils": "3.1.3"
42
+ "@vitest/utils": "3.2.0-beta.1"
43
43
  },
44
44
  "scripts": {
45
45
  "build": "rimraf dist && rollup -c",