@vitest/runner 3.2.0-beta.2 → 3.2.0
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/chunk-hooks.js +2243 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -1638
- package/dist/{tasks.d-hzpC0pGR.d.ts → tasks.d-CkscK4of.d.ts} +67 -5
- package/dist/types.d.ts +21 -8
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +3 -2
- package/package.json +2 -2
- package/dist/chunk-tasks.js +0 -301
@@ -3,6 +3,7 @@ import { ErrorWithDiff, Awaitable } from '@vitest/utils';
|
|
3
3
|
interface FixtureItem extends FixtureOptions {
|
4
4
|
prop: string;
|
5
5
|
value: any;
|
6
|
+
scope: "test" | "file" | "worker";
|
6
7
|
/**
|
7
8
|
* Indicates whether the fixture is a function
|
8
9
|
*/
|
@@ -156,16 +157,24 @@ interface TaskResult {
|
|
156
157
|
* `repeats` option is set. This number also contains `retryCount`.
|
157
158
|
*/
|
158
159
|
repeatCount?: number;
|
159
|
-
|
160
|
-
|
160
|
+
}
|
161
|
+
/** The time spent importing & executing a non-externalized file. */
|
162
|
+
interface ImportDuration {
|
163
|
+
/** The time spent importing & executing the file itself, not counting all non-externalized imports that the file does. */
|
164
|
+
selfTime: number;
|
165
|
+
/** The time spent importing & executing the file and all its imports. */
|
166
|
+
totalTime: number;
|
161
167
|
}
|
162
168
|
/**
|
163
169
|
* The tuple representing a single task update.
|
164
170
|
* Usually reported after the task finishes.
|
165
171
|
*/
|
166
172
|
type TaskResultPack = [id: string, result: TaskResult | undefined, meta: TaskMeta];
|
167
|
-
|
168
|
-
|
173
|
+
interface TaskEventData {
|
174
|
+
annotation?: TestAnnotation | undefined;
|
175
|
+
}
|
176
|
+
type TaskEventPack = [id: string, event: TaskUpdateEvent, data: TaskEventData | undefined];
|
177
|
+
type TaskUpdateEvent = "test-failed-early" | "suite-failed-early" | "test-prepare" | "test-finished" | "test-retried" | "suite-prepare" | "suite-finished" | "before-hook-start" | "before-hook-end" | "after-hook-start" | "after-hook-end" | "test-annotation";
|
169
178
|
interface Suite extends TaskBase {
|
170
179
|
type: "suite";
|
171
180
|
/**
|
@@ -200,6 +209,8 @@ interface File extends Suite {
|
|
200
209
|
* The time it took to import the setup file.
|
201
210
|
*/
|
202
211
|
setupDuration?: number;
|
212
|
+
/** The time spent importing every non-externalized dependency that Vitest has processed. */
|
213
|
+
importDurations?: Record<string, ImportDuration>;
|
203
214
|
}
|
204
215
|
interface Test<ExtraContext = object> extends TaskPopulated {
|
205
216
|
type: "test";
|
@@ -211,6 +222,26 @@ interface Test<ExtraContext = object> extends TaskPopulated {
|
|
211
222
|
* The test timeout in milliseconds.
|
212
223
|
*/
|
213
224
|
timeout: number;
|
225
|
+
/**
|
226
|
+
* An array of custom annotations.
|
227
|
+
*/
|
228
|
+
annotations: TestAnnotation[];
|
229
|
+
}
|
230
|
+
interface TestAttachment {
|
231
|
+
contentType?: string;
|
232
|
+
path?: string;
|
233
|
+
body?: string | Uint8Array;
|
234
|
+
}
|
235
|
+
interface TestAnnotationLocation {
|
236
|
+
line: number;
|
237
|
+
column: number;
|
238
|
+
file: string;
|
239
|
+
}
|
240
|
+
interface TestAnnotation {
|
241
|
+
message: string;
|
242
|
+
type: string;
|
243
|
+
location?: TestAnnotationLocation;
|
244
|
+
attachment?: TestAttachment;
|
214
245
|
}
|
215
246
|
/**
|
216
247
|
* @deprecated Use `Test` instead. `type: 'custom'` is not used since 2.2
|
@@ -222,6 +253,7 @@ type Task = Test | Suite | File;
|
|
222
253
|
*/
|
223
254
|
type DoneCallback = (error?: any) => void;
|
224
255
|
type TestFunction<ExtraContext = object> = (context: TestContext & ExtraContext) => Awaitable<any> | void;
|
256
|
+
// jest's ExtractEachCallbackArgs
|
225
257
|
type ExtractEachCallbackArgs<T extends ReadonlyArray<any>> = {
|
226
258
|
1: [T[0]]
|
227
259
|
2: [T[0], T[1]]
|
@@ -257,7 +289,14 @@ interface TestForFunctionReturn<
|
|
257
289
|
(name: string | Function, options: TestCollectorOptions, fn: (args: Arg, context: Context) => Awaitable<void>): void;
|
258
290
|
}
|
259
291
|
interface TestForFunction<ExtraContext> {
|
292
|
+
// test.for([1, 2, 3])
|
293
|
+
// test.for([[1, 2], [3, 4, 5]])
|
260
294
|
<T>(cases: ReadonlyArray<T>): TestForFunctionReturn<T, TestContext & ExtraContext>;
|
295
|
+
// test.for`
|
296
|
+
// a | b
|
297
|
+
// {1} | {2}
|
298
|
+
// {3} | {4}
|
299
|
+
// `
|
261
300
|
(strings: TemplateStringsArray, ...values: any[]): TestForFunctionReturn<any, TestContext & ExtraContext>;
|
262
301
|
}
|
263
302
|
interface SuiteForFunction {
|
@@ -339,12 +378,23 @@ type TestAPI<ExtraContext = object> = ChainableTestAPI<ExtraContext> & ExtendedA
|
|
339
378
|
interface FixtureOptions {
|
340
379
|
/**
|
341
380
|
* Whether to automatically set up current fixture, even though it's not being used in tests.
|
381
|
+
* @default false
|
342
382
|
*/
|
343
383
|
auto?: boolean;
|
344
384
|
/**
|
345
385
|
* Indicated if the injected value from the config should be preferred over the fixture value
|
346
386
|
*/
|
347
387
|
injected?: boolean;
|
388
|
+
/**
|
389
|
+
* When should the fixture be set up.
|
390
|
+
* - **test**: fixture will be set up before every test
|
391
|
+
* - **worker**: fixture will be set up once per worker
|
392
|
+
* - **file**: fixture will be set up once per file
|
393
|
+
*
|
394
|
+
* **Warning:** The `vmThreads` and `vmForks` pools initiate worker fixtures once per test file.
|
395
|
+
* @default 'test'
|
396
|
+
*/
|
397
|
+
scope?: "test" | "worker" | "file";
|
348
398
|
}
|
349
399
|
type Use<T> = (value: T) => Promise<void>;
|
350
400
|
type FixtureFn<
|
@@ -458,24 +508,36 @@ interface TestContext {
|
|
458
508
|
/**
|
459
509
|
* An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that will be aborted if the test times out or
|
460
510
|
* the test run was cancelled.
|
511
|
+
* @see {@link https://vitest.dev/guide/test-context#signal}
|
461
512
|
*/
|
462
513
|
readonly signal: AbortSignal;
|
463
514
|
/**
|
464
515
|
* Extract hooks on test failed
|
516
|
+
* @see {@link https://vitest.dev/guide/test-context#ontestfailed}
|
465
517
|
*/
|
466
518
|
readonly onTestFailed: (fn: OnTestFailedHandler, timeout?: number) => void;
|
467
519
|
/**
|
468
520
|
* Extract hooks on test failed
|
521
|
+
* @see {@link https://vitest.dev/guide/test-context#ontestfinished}
|
469
522
|
*/
|
470
523
|
readonly onTestFinished: (fn: OnTestFinishedHandler, timeout?: number) => void;
|
471
524
|
/**
|
472
525
|
* Mark tests as skipped. All execution after this call will be skipped.
|
473
526
|
* This function throws an error, so make sure you are not catching it accidentally.
|
527
|
+
* @see {@link https://vitest.dev/guide/test-context#skip}
|
474
528
|
*/
|
475
529
|
readonly skip: {
|
476
530
|
(note?: string): never
|
477
531
|
(condition: boolean, note?: string): void
|
478
532
|
};
|
533
|
+
/**
|
534
|
+
* Add a test annotation that will be displayed by your reporter.
|
535
|
+
* @see {@link https://vitest.dev/guide/test-context#annotate}
|
536
|
+
*/
|
537
|
+
readonly annotate: {
|
538
|
+
(message: string, type?: string, attachment?: TestAttachment): Promise<TestAnnotation>
|
539
|
+
(message: string, attachment?: TestAttachment): Promise<TestAnnotation>
|
540
|
+
};
|
479
541
|
}
|
480
542
|
/**
|
481
543
|
* Context that's always available in the test function.
|
@@ -493,4 +555,4 @@ type SequenceHooks = "stack" | "list" | "parallel";
|
|
493
555
|
type SequenceSetupFiles = "list" | "parallel";
|
494
556
|
|
495
557
|
export { createChainable as c };
|
496
|
-
export type { AfterAllListener as A, BeforeAllListener as B, ChainableFunction as C, DoneCallback as D, ExtendedContext as E, File as F,
|
558
|
+
export type { AfterAllListener as A, BeforeAllListener as B, ChainableFunction as C, DoneCallback as D, ExtendedContext as E, File as F, TaskMeta as G, HookCleanupCallback as H, ImportDuration as I, TaskPopulated as J, TaskResult as K, TaskResultPack as L, TaskState as M, TestAnnotation as N, OnTestFailedHandler as O, TestAnnotationLocation as P, TestAttachment as Q, RunMode as R, Suite as S, Task as T, TestContext as U, TestFunction as V, TestOptions as W, Use as X, Test as a, AfterEachListener as b, BeforeEachListener as d, TaskHook as e, OnTestFinishedHandler as f, Custom as g, SuiteHooks as h, TaskUpdateEvent as i, TestAPI as j, SuiteAPI as k, SuiteCollector as l, Fixture as m, FixtureFn as n, FixtureOptions as o, Fixtures as p, HookListener as q, InferFixturesTypes as r, RuntimeContext as s, SequenceHooks as t, SequenceSetupFiles as u, SuiteFactory as v, TaskBase as w, TaskContext as x, TaskCustomOptions as y, TaskEventPack as z };
|
package/dist/types.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { DiffOptions } from '@vitest/utils/diff';
|
2
|
-
import { F as File,
|
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,
|
2
|
+
import { F as File, a as Test, S as Suite, L as TaskResultPack, z as TaskEventPack, N as TestAnnotation, U as TestContext, I as ImportDuration, t as SequenceHooks, u as SequenceSetupFiles } from './tasks.d-CkscK4of.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, r as InferFixturesTypes, O as OnTestFailedHandler, f as OnTestFinishedHandler, R as RunMode, s as RuntimeContext, k as SuiteAPI, l as SuiteCollector, v as SuiteFactory, h as SuiteHooks, T as Task, w as TaskBase, x as TaskContext, y as TaskCustomOptions, e as TaskHook, G as TaskMeta, J as TaskPopulated, K as TaskResult, M as TaskState, i as TaskUpdateEvent, j as TestAPI, P as TestAnnotationLocation, Q as TestAttachment, V as TestFunction, W as TestOptions, X as Use } from './tasks.d-CkscK4of.js';
|
4
4
|
import '@vitest/utils';
|
5
5
|
|
6
6
|
/**
|
@@ -64,11 +64,11 @@ interface VitestRunner {
|
|
64
64
|
/**
|
65
65
|
* Called before running a single test. Doesn't have "result" yet.
|
66
66
|
*/
|
67
|
-
onBeforeRunTask?: (test:
|
67
|
+
onBeforeRunTask?: (test: Test) => unknown;
|
68
68
|
/**
|
69
69
|
* Called before actually running the test function. Already has "result" with "state" and "startTime".
|
70
70
|
*/
|
71
|
-
onBeforeTryTask?: (test:
|
71
|
+
onBeforeTryTask?: (test: Test, options: {
|
72
72
|
retry: number
|
73
73
|
repeats: number
|
74
74
|
}) => unknown;
|
@@ -79,11 +79,11 @@ interface VitestRunner {
|
|
79
79
|
/**
|
80
80
|
* Called after result and state are set.
|
81
81
|
*/
|
82
|
-
onAfterRunTask?: (test:
|
82
|
+
onAfterRunTask?: (test: Test) => unknown;
|
83
83
|
/**
|
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
|
-
onAfterTryTask?: (test:
|
86
|
+
onAfterTryTask?: (test: Test, options: {
|
87
87
|
retry: number
|
88
88
|
repeats: number
|
89
89
|
}) => unknown;
|
@@ -104,12 +104,16 @@ interface VitestRunner {
|
|
104
104
|
* If defined, will be called instead of usual Vitest handling. Useful, if you have your custom test function.
|
105
105
|
* "before" and "after" hooks will not be ignored.
|
106
106
|
*/
|
107
|
-
runTask?: (test:
|
107
|
+
runTask?: (test: Test) => Promise<void>;
|
108
108
|
/**
|
109
109
|
* Called, when a task is updated. The same as "onTaskUpdate" in a reporter, but this is running in the same thread as tests.
|
110
110
|
*/
|
111
111
|
onTaskUpdate?: (task: TaskResultPack[], events: TaskEventPack[]) => Promise<void>;
|
112
112
|
/**
|
113
|
+
* Called when annotation is added via the `context.annotate` method.
|
114
|
+
*/
|
115
|
+
onTestAnnotate?: (test: Test, annotation: TestAnnotation) => Promise<TestAnnotation>;
|
116
|
+
/**
|
113
117
|
* Called before running all tests in collected paths.
|
114
118
|
*/
|
115
119
|
onBeforeRunFiles?: (files: File[]) => unknown;
|
@@ -133,6 +137,10 @@ interface VitestRunner {
|
|
133
137
|
*/
|
134
138
|
injectValue?: (key: string) => unknown;
|
135
139
|
/**
|
140
|
+
* Gets the time spent importing each individual non-externalized file that Vitest collected.
|
141
|
+
*/
|
142
|
+
getImportDurations?: () => Record<string, ImportDuration>;
|
143
|
+
/**
|
136
144
|
* Publicly available configuration.
|
137
145
|
*/
|
138
146
|
config: VitestRunnerConfig;
|
@@ -140,11 +148,16 @@ interface VitestRunner {
|
|
140
148
|
* The name of the current pool. Can affect how stack trace is inferred on the server side.
|
141
149
|
*/
|
142
150
|
pool?: string;
|
151
|
+
/**
|
152
|
+
* Return the worker context for fixtures specified with `scope: 'worker'`
|
153
|
+
*/
|
154
|
+
getWorkerContext?: () => Record<string, unknown>;
|
155
|
+
onCleanupWorkerContext?: (cleanup: () => unknown) => void;
|
143
156
|
/** @private */
|
144
157
|
_currentTaskStartTime?: number;
|
145
158
|
/** @private */
|
146
159
|
_currentTaskTimeout?: number;
|
147
160
|
}
|
148
161
|
|
149
|
-
export { File, SequenceHooks, SequenceSetupFiles, Suite,
|
162
|
+
export { File, ImportDuration, SequenceHooks, SequenceSetupFiles, Suite, TaskEventPack, TaskResultPack, Test, TestAnnotation, TestContext };
|
150
163
|
export type { CancelReason, FileSpecification, VitestRunner, VitestRunnerConfig, VitestRunnerConstructor, VitestRunnerImportSource };
|
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-
|
2
|
-
export { C as ChainableFunction, c as createChainable } from './tasks.d-
|
1
|
+
import { S as Suite, F as File, T as Task, a as Test } from './tasks.d-CkscK4of.js';
|
2
|
+
export { C as ChainableFunction, c as createChainable } from './tasks.d-CkscK4of.js';
|
3
3
|
import { Arrayable } from '@vitest/utils';
|
4
4
|
|
5
5
|
/**
|
package/dist/utils.js
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
export {
|
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';
|
2
|
+
import '@vitest/utils';
|
3
|
+
import '@vitest/utils/source-map';
|
2
4
|
import '@vitest/utils/error';
|
3
5
|
import 'pathe';
|
4
|
-
import '@vitest/utils';
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vitest/runner",
|
3
3
|
"type": "module",
|
4
|
-
"version": "3.2.0
|
4
|
+
"version": "3.2.0",
|
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.2.0
|
42
|
+
"@vitest/utils": "3.2.0"
|
43
43
|
},
|
44
44
|
"scripts": {
|
45
45
|
"build": "rimraf dist && rollup -c",
|
package/dist/chunk-tasks.js
DELETED
@@ -1,301 +0,0 @@
|
|
1
|
-
import { processError } from '@vitest/utils/error';
|
2
|
-
import { relative } from 'pathe';
|
3
|
-
import { toArray } from '@vitest/utils';
|
4
|
-
|
5
|
-
function createChainable(keys, fn) {
|
6
|
-
function create(context) {
|
7
|
-
const chain = function(...args) {
|
8
|
-
return fn.apply(context, args);
|
9
|
-
};
|
10
|
-
Object.assign(chain, fn);
|
11
|
-
chain.withContext = () => chain.bind(context);
|
12
|
-
chain.setContext = (key, value) => {
|
13
|
-
context[key] = value;
|
14
|
-
};
|
15
|
-
chain.mergeContext = (ctx) => {
|
16
|
-
Object.assign(context, ctx);
|
17
|
-
};
|
18
|
-
for (const key of keys) {
|
19
|
-
Object.defineProperty(chain, key, { get() {
|
20
|
-
return create({
|
21
|
-
...context,
|
22
|
-
[key]: true
|
23
|
-
});
|
24
|
-
} });
|
25
|
-
}
|
26
|
-
return chain;
|
27
|
-
}
|
28
|
-
const chain = create({});
|
29
|
-
chain.fn = fn;
|
30
|
-
return chain;
|
31
|
-
}
|
32
|
-
|
33
|
-
/**
|
34
|
-
* If any tasks been marked as `only`, mark all other tasks as `skip`.
|
35
|
-
*/
|
36
|
-
function interpretTaskModes(file, namePattern, testLocations, onlyMode, parentIsOnly, allowOnly) {
|
37
|
-
const matchedLocations = [];
|
38
|
-
const traverseSuite = (suite, parentIsOnly, parentMatchedWithLocation) => {
|
39
|
-
const suiteIsOnly = parentIsOnly || suite.mode === "only";
|
40
|
-
suite.tasks.forEach((t) => {
|
41
|
-
const includeTask = suiteIsOnly || t.mode === "only";
|
42
|
-
if (onlyMode) {
|
43
|
-
if (t.type === "suite" && (includeTask || someTasksAreOnly(t))) {
|
44
|
-
if (t.mode === "only") {
|
45
|
-
checkAllowOnly(t, allowOnly);
|
46
|
-
t.mode = "run";
|
47
|
-
}
|
48
|
-
} else if (t.mode === "run" && !includeTask) {
|
49
|
-
t.mode = "skip";
|
50
|
-
} else if (t.mode === "only") {
|
51
|
-
checkAllowOnly(t, allowOnly);
|
52
|
-
t.mode = "run";
|
53
|
-
}
|
54
|
-
}
|
55
|
-
let hasLocationMatch = parentMatchedWithLocation;
|
56
|
-
if (testLocations !== undefined && testLocations.length !== 0) {
|
57
|
-
if (t.location && (testLocations === null || testLocations === void 0 ? void 0 : testLocations.includes(t.location.line))) {
|
58
|
-
t.mode = "run";
|
59
|
-
matchedLocations.push(t.location.line);
|
60
|
-
hasLocationMatch = true;
|
61
|
-
} else if (parentMatchedWithLocation) {
|
62
|
-
t.mode = "run";
|
63
|
-
} else if (t.type === "test") {
|
64
|
-
t.mode = "skip";
|
65
|
-
}
|
66
|
-
}
|
67
|
-
if (t.type === "test") {
|
68
|
-
if (namePattern && !getTaskFullName(t).match(namePattern)) {
|
69
|
-
t.mode = "skip";
|
70
|
-
}
|
71
|
-
} else if (t.type === "suite") {
|
72
|
-
if (t.mode === "skip") {
|
73
|
-
skipAllTasks(t);
|
74
|
-
} else if (t.mode === "todo") {
|
75
|
-
todoAllTasks(t);
|
76
|
-
} else {
|
77
|
-
traverseSuite(t, includeTask, hasLocationMatch);
|
78
|
-
}
|
79
|
-
}
|
80
|
-
});
|
81
|
-
if (suite.mode === "run" || suite.mode === "queued") {
|
82
|
-
if (suite.tasks.length && suite.tasks.every((i) => i.mode !== "run" && i.mode !== "queued")) {
|
83
|
-
suite.mode = "skip";
|
84
|
-
}
|
85
|
-
}
|
86
|
-
};
|
87
|
-
traverseSuite(file, parentIsOnly, false);
|
88
|
-
const nonMatching = testLocations === null || testLocations === void 0 ? void 0 : testLocations.filter((loc) => !matchedLocations.includes(loc));
|
89
|
-
if (nonMatching && nonMatching.length !== 0) {
|
90
|
-
const message = nonMatching.length === 1 ? `line ${nonMatching[0]}` : `lines ${nonMatching.join(", ")}`;
|
91
|
-
if (file.result === undefined) {
|
92
|
-
file.result = {
|
93
|
-
state: "fail",
|
94
|
-
errors: []
|
95
|
-
};
|
96
|
-
}
|
97
|
-
if (file.result.errors === undefined) {
|
98
|
-
file.result.errors = [];
|
99
|
-
}
|
100
|
-
file.result.errors.push(processError(new Error(`No test found in ${file.name} in ${message}`)));
|
101
|
-
}
|
102
|
-
}
|
103
|
-
function getTaskFullName(task) {
|
104
|
-
return `${task.suite ? `${getTaskFullName(task.suite)} ` : ""}${task.name}`;
|
105
|
-
}
|
106
|
-
function someTasksAreOnly(suite) {
|
107
|
-
return suite.tasks.some((t) => t.mode === "only" || t.type === "suite" && someTasksAreOnly(t));
|
108
|
-
}
|
109
|
-
function skipAllTasks(suite) {
|
110
|
-
suite.tasks.forEach((t) => {
|
111
|
-
if (t.mode === "run" || t.mode === "queued") {
|
112
|
-
t.mode = "skip";
|
113
|
-
if (t.type === "suite") {
|
114
|
-
skipAllTasks(t);
|
115
|
-
}
|
116
|
-
}
|
117
|
-
});
|
118
|
-
}
|
119
|
-
function todoAllTasks(suite) {
|
120
|
-
suite.tasks.forEach((t) => {
|
121
|
-
if (t.mode === "run" || t.mode === "queued") {
|
122
|
-
t.mode = "todo";
|
123
|
-
if (t.type === "suite") {
|
124
|
-
todoAllTasks(t);
|
125
|
-
}
|
126
|
-
}
|
127
|
-
});
|
128
|
-
}
|
129
|
-
function checkAllowOnly(task, allowOnly) {
|
130
|
-
if (allowOnly) {
|
131
|
-
return;
|
132
|
-
}
|
133
|
-
const error = processError(new Error("[Vitest] Unexpected .only modifier. Remove it or pass --allowOnly argument to bypass this error"));
|
134
|
-
task.result = {
|
135
|
-
state: "fail",
|
136
|
-
errors: [error]
|
137
|
-
};
|
138
|
-
}
|
139
|
-
function generateHash(str) {
|
140
|
-
let hash = 0;
|
141
|
-
if (str.length === 0) {
|
142
|
-
return `${hash}`;
|
143
|
-
}
|
144
|
-
for (let i = 0; i < str.length; i++) {
|
145
|
-
const char = str.charCodeAt(i);
|
146
|
-
hash = (hash << 5) - hash + char;
|
147
|
-
hash = hash & hash;
|
148
|
-
}
|
149
|
-
return `${hash}`;
|
150
|
-
}
|
151
|
-
function calculateSuiteHash(parent) {
|
152
|
-
parent.tasks.forEach((t, idx) => {
|
153
|
-
t.id = `${parent.id}_${idx}`;
|
154
|
-
if (t.type === "suite") {
|
155
|
-
calculateSuiteHash(t);
|
156
|
-
}
|
157
|
-
});
|
158
|
-
}
|
159
|
-
function createFileTask(filepath, root, projectName, pool) {
|
160
|
-
const path = relative(root, filepath);
|
161
|
-
const file = {
|
162
|
-
id: generateFileHash(path, projectName),
|
163
|
-
name: path,
|
164
|
-
type: "suite",
|
165
|
-
mode: "queued",
|
166
|
-
filepath,
|
167
|
-
tasks: [],
|
168
|
-
meta: Object.create(null),
|
169
|
-
projectName,
|
170
|
-
file: undefined,
|
171
|
-
pool
|
172
|
-
};
|
173
|
-
file.file = file;
|
174
|
-
return file;
|
175
|
-
}
|
176
|
-
/**
|
177
|
-
* Generate a unique ID for a file based on its path and project name
|
178
|
-
* @param file File relative to the root of the project to keep ID the same between different machines
|
179
|
-
* @param projectName The name of the test project
|
180
|
-
*/
|
181
|
-
function generateFileHash(file, projectName) {
|
182
|
-
return generateHash(`${file}${projectName || ""}`);
|
183
|
-
}
|
184
|
-
|
185
|
-
/**
|
186
|
-
* Return a function for running multiple async operations with limited concurrency.
|
187
|
-
*/
|
188
|
-
function limitConcurrency(concurrency = Infinity) {
|
189
|
-
let count = 0;
|
190
|
-
let head;
|
191
|
-
let tail;
|
192
|
-
const finish = () => {
|
193
|
-
count--;
|
194
|
-
if (head) {
|
195
|
-
head[0]();
|
196
|
-
head = head[1];
|
197
|
-
tail = head && tail;
|
198
|
-
}
|
199
|
-
};
|
200
|
-
return (func, ...args) => {
|
201
|
-
return new Promise((resolve) => {
|
202
|
-
if (count++ < concurrency) {
|
203
|
-
resolve();
|
204
|
-
} else if (tail) {
|
205
|
-
tail = tail[1] = [resolve];
|
206
|
-
} else {
|
207
|
-
head = tail = [resolve];
|
208
|
-
}
|
209
|
-
}).then(() => {
|
210
|
-
return func(...args);
|
211
|
-
}).finally(finish);
|
212
|
-
};
|
213
|
-
}
|
214
|
-
|
215
|
-
/**
|
216
|
-
* Partition in tasks groups by consecutive concurrent
|
217
|
-
*/
|
218
|
-
function partitionSuiteChildren(suite) {
|
219
|
-
let tasksGroup = [];
|
220
|
-
const tasksGroups = [];
|
221
|
-
for (const c of suite.tasks) {
|
222
|
-
if (tasksGroup.length === 0 || c.concurrent === tasksGroup[0].concurrent) {
|
223
|
-
tasksGroup.push(c);
|
224
|
-
} else {
|
225
|
-
tasksGroups.push(tasksGroup);
|
226
|
-
tasksGroup = [c];
|
227
|
-
}
|
228
|
-
}
|
229
|
-
if (tasksGroup.length > 0) {
|
230
|
-
tasksGroups.push(tasksGroup);
|
231
|
-
}
|
232
|
-
return tasksGroups;
|
233
|
-
}
|
234
|
-
|
235
|
-
/**
|
236
|
-
* @deprecated use `isTestCase` instead
|
237
|
-
*/
|
238
|
-
function isAtomTest(s) {
|
239
|
-
return isTestCase(s);
|
240
|
-
}
|
241
|
-
function isTestCase(s) {
|
242
|
-
return s.type === "test";
|
243
|
-
}
|
244
|
-
function getTests(suite) {
|
245
|
-
const tests = [];
|
246
|
-
const arraySuites = toArray(suite);
|
247
|
-
for (const s of arraySuites) {
|
248
|
-
if (isTestCase(s)) {
|
249
|
-
tests.push(s);
|
250
|
-
} else {
|
251
|
-
for (const task of s.tasks) {
|
252
|
-
if (isTestCase(task)) {
|
253
|
-
tests.push(task);
|
254
|
-
} else {
|
255
|
-
const taskTests = getTests(task);
|
256
|
-
for (const test of taskTests) {
|
257
|
-
tests.push(test);
|
258
|
-
}
|
259
|
-
}
|
260
|
-
}
|
261
|
-
}
|
262
|
-
}
|
263
|
-
return tests;
|
264
|
-
}
|
265
|
-
function getTasks(tasks = []) {
|
266
|
-
return toArray(tasks).flatMap((s) => isTestCase(s) ? [s] : [s, ...getTasks(s.tasks)]);
|
267
|
-
}
|
268
|
-
function getSuites(suite) {
|
269
|
-
return toArray(suite).flatMap((s) => s.type === "suite" ? [s, ...getSuites(s.tasks)] : []);
|
270
|
-
}
|
271
|
-
function hasTests(suite) {
|
272
|
-
return toArray(suite).some((s) => s.tasks.some((c) => isTestCase(c) || hasTests(c)));
|
273
|
-
}
|
274
|
-
function hasFailed(suite) {
|
275
|
-
return toArray(suite).some((s) => {
|
276
|
-
var _s$result;
|
277
|
-
return ((_s$result = s.result) === null || _s$result === void 0 ? void 0 : _s$result.state) === "fail" || s.type === "suite" && hasFailed(s.tasks);
|
278
|
-
});
|
279
|
-
}
|
280
|
-
function getNames(task) {
|
281
|
-
const names = [task.name];
|
282
|
-
let current = task;
|
283
|
-
while (current === null || current === void 0 ? void 0 : current.suite) {
|
284
|
-
current = current.suite;
|
285
|
-
if (current === null || current === void 0 ? void 0 : current.name) {
|
286
|
-
names.unshift(current.name);
|
287
|
-
}
|
288
|
-
}
|
289
|
-
if (current !== task.file) {
|
290
|
-
names.unshift(task.file.name);
|
291
|
-
}
|
292
|
-
return names;
|
293
|
-
}
|
294
|
-
function getFullName(task, separator = " > ") {
|
295
|
-
return getNames(task).join(separator);
|
296
|
-
}
|
297
|
-
function getTestName(task, separator = " > ") {
|
298
|
-
return getNames(task).slice(1).join(separator);
|
299
|
-
}
|
300
|
-
|
301
|
-
export { calculateSuiteHash as a, createFileTask as b, createChainable as c, generateHash as d, getFullName as e, getNames as f, generateFileHash as g, getSuites as h, interpretTaskModes as i, getTasks as j, getTestName as k, limitConcurrency as l, getTests as m, hasFailed as n, hasTests as o, partitionSuiteChildren as p, isAtomTest as q, isTestCase as r, someTasksAreOnly as s };
|