@vitest/runner 3.1.0-beta.1 → 3.1.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-tasks.js +245 -243
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1435 -1314
- package/dist/{tasks.d-D-sw4YOL.d.ts → tasks.d-hsdzc98-.d.ts} +6 -2
- package/dist/types.d.ts +8 -3
- package/dist/utils.d.ts +2 -2
- package/package.json +2 -2
package/dist/chunk-tasks.js
CHANGED
@@ -3,297 +3,299 @@ import { relative } from 'pathe';
|
|
3
3
|
import { toArray } from '@vitest/utils';
|
4
4
|
|
5
5
|
function createChainable(keys, fn) {
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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;
|
30
31
|
}
|
31
32
|
|
33
|
+
/**
|
34
|
+
* If any tasks been marked as `only`, mark all other tasks as `skip`.
|
35
|
+
*/
|
32
36
|
function interpretTaskModes(file, namePattern, testLocations, onlyMode, parentIsOnly, allowOnly) {
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
);
|
99
|
-
}
|
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
|
+
}
|
100
102
|
}
|
101
103
|
function getTaskFullName(task) {
|
102
|
-
|
104
|
+
return `${task.suite ? `${getTaskFullName(task.suite)} ` : ""}${task.name}`;
|
103
105
|
}
|
104
106
|
function someTasksAreOnly(suite) {
|
105
|
-
|
106
|
-
(t) => t.mode === "only" || t.type === "suite" && someTasksAreOnly(t)
|
107
|
-
);
|
107
|
+
return suite.tasks.some((t) => t.mode === "only" || t.type === "suite" && someTasksAreOnly(t));
|
108
108
|
}
|
109
109
|
function skipAllTasks(suite) {
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
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
118
|
}
|
119
119
|
function todoAllTasks(suite) {
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
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
128
|
}
|
129
129
|
function checkAllowOnly(task, allowOnly) {
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
task.result = {
|
139
|
-
state: "fail",
|
140
|
-
errors: [error]
|
141
|
-
};
|
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
|
+
};
|
142
138
|
}
|
143
139
|
function generateHash(str) {
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
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}`;
|
154
150
|
}
|
155
151
|
function calculateSuiteHash(parent) {
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
152
|
+
parent.tasks.forEach((t, idx) => {
|
153
|
+
t.id = `${parent.id}_${idx}`;
|
154
|
+
if (t.type === "suite") {
|
155
|
+
calculateSuiteHash(t);
|
156
|
+
}
|
157
|
+
});
|
162
158
|
}
|
163
159
|
function createFileTask(filepath, root, projectName, pool) {
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
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;
|
179
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
|
+
*/
|
180
181
|
function generateFileHash(file, projectName) {
|
181
|
-
|
182
|
+
return generateHash(`${file}${projectName || ""}`);
|
182
183
|
}
|
183
184
|
|
185
|
+
/**
|
186
|
+
* Return a function for running multiple async operations with limited concurrency.
|
187
|
+
*/
|
184
188
|
function limitConcurrency(concurrency = Infinity) {
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
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
|
+
};
|
209
213
|
}
|
210
214
|
|
215
|
+
/**
|
216
|
+
* Partition in tasks groups by consecutive concurrent
|
217
|
+
*/
|
211
218
|
function partitionSuiteChildren(suite) {
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
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;
|
226
233
|
}
|
227
234
|
|
235
|
+
/**
|
236
|
+
* @deprecated use `isTestCase` instead
|
237
|
+
*/
|
228
238
|
function isAtomTest(s) {
|
229
|
-
|
239
|
+
return isTestCase(s);
|
230
240
|
}
|
231
241
|
function isTestCase(s) {
|
232
|
-
|
242
|
+
return s.type === "test";
|
233
243
|
}
|
234
244
|
function getTests(suite) {
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
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;
|
254
264
|
}
|
255
265
|
function getTasks(tasks = []) {
|
256
|
-
|
257
|
-
(s) => isTestCase(s) ? [s] : [s, ...getTasks(s.tasks)]
|
258
|
-
);
|
266
|
+
return toArray(tasks).flatMap((s) => isTestCase(s) ? [s] : [s, ...getTasks(s.tasks)]);
|
259
267
|
}
|
260
268
|
function getSuites(suite) {
|
261
|
-
|
262
|
-
(s) => s.type === "suite" ? [s, ...getSuites(s.tasks)] : []
|
263
|
-
);
|
269
|
+
return toArray(suite).flatMap((s) => s.type === "suite" ? [s, ...getSuites(s.tasks)] : []);
|
264
270
|
}
|
265
271
|
function hasTests(suite) {
|
266
|
-
|
267
|
-
(s) => s.tasks.some((c) => isTestCase(c) || hasTests(c))
|
268
|
-
);
|
272
|
+
return toArray(suite).some((s) => s.tasks.some((c) => isTestCase(c) || hasTests(c)));
|
269
273
|
}
|
270
274
|
function hasFailed(suite) {
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
}
|
276
|
-
);
|
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
|
+
});
|
277
279
|
}
|
278
280
|
function getNames(task) {
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
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;
|
291
293
|
}
|
292
294
|
function getFullName(task, separator = " > ") {
|
293
|
-
|
295
|
+
return getNames(task).join(separator);
|
294
296
|
}
|
295
297
|
function getTestName(task, separator = " > ") {
|
296
|
-
|
298
|
+
return getNames(task).slice(1).join(separator);
|
297
299
|
}
|
298
300
|
|
299
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 };
|
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-
|
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-
|
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';
|
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';
|