@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.
@@ -3,297 +3,299 @@ import { relative } from 'pathe';
3
3
  import { toArray } from '@vitest/utils';
4
4
 
5
5
  function createChainable(keys, fn) {
6
- function create(context) {
7
- const chain2 = function(...args) {
8
- return fn.apply(context, args);
9
- };
10
- Object.assign(chain2, fn);
11
- chain2.withContext = () => chain2.bind(context);
12
- chain2.setContext = (key, value) => {
13
- context[key] = value;
14
- };
15
- chain2.mergeContext = (ctx) => {
16
- Object.assign(context, ctx);
17
- };
18
- for (const key of keys) {
19
- Object.defineProperty(chain2, key, {
20
- get() {
21
- return create({ ...context, [key]: true });
22
- }
23
- });
24
- }
25
- return chain2;
26
- }
27
- const chain = create({});
28
- chain.fn = fn;
29
- return chain;
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
- const matchedLocations = [];
34
- const traverseSuite = (suite, parentIsOnly2, parentMatchedWithLocation) => {
35
- const suiteIsOnly = parentIsOnly2 || suite.mode === "only";
36
- suite.tasks.forEach((t) => {
37
- const includeTask = suiteIsOnly || t.mode === "only";
38
- if (onlyMode) {
39
- if (t.type === "suite" && (includeTask || someTasksAreOnly(t))) {
40
- if (t.mode === "only") {
41
- checkAllowOnly(t, allowOnly);
42
- t.mode = "run";
43
- }
44
- } else if (t.mode === "run" && !includeTask) {
45
- t.mode = "skip";
46
- } else if (t.mode === "only") {
47
- checkAllowOnly(t, allowOnly);
48
- t.mode = "run";
49
- }
50
- }
51
- let hasLocationMatch = parentMatchedWithLocation;
52
- if (testLocations !== void 0 && testLocations.length !== 0) {
53
- if (t.location && (testLocations == null ? void 0 : testLocations.includes(t.location.line))) {
54
- t.mode = "run";
55
- matchedLocations.push(t.location.line);
56
- hasLocationMatch = true;
57
- } else if (parentMatchedWithLocation) {
58
- t.mode = "run";
59
- } else if (t.type === "test") {
60
- t.mode = "skip";
61
- }
62
- }
63
- if (t.type === "test") {
64
- if (namePattern && !getTaskFullName(t).match(namePattern)) {
65
- t.mode = "skip";
66
- }
67
- } else if (t.type === "suite") {
68
- if (t.mode === "skip") {
69
- skipAllTasks(t);
70
- } else if (t.mode === "todo") {
71
- todoAllTasks(t);
72
- } else {
73
- traverseSuite(t, includeTask, hasLocationMatch);
74
- }
75
- }
76
- });
77
- if (suite.mode === "run" || suite.mode === "queued") {
78
- if (suite.tasks.length && suite.tasks.every((i) => i.mode !== "run" && i.mode !== "queued")) {
79
- suite.mode = "skip";
80
- }
81
- }
82
- };
83
- traverseSuite(file, parentIsOnly, false);
84
- const nonMatching = testLocations == null ? void 0 : testLocations.filter((loc) => !matchedLocations.includes(loc));
85
- if (nonMatching && nonMatching.length !== 0) {
86
- const message = nonMatching.length === 1 ? `line ${nonMatching[0]}` : `lines ${nonMatching.join(", ")}`;
87
- if (file.result === void 0) {
88
- file.result = {
89
- state: "fail",
90
- errors: []
91
- };
92
- }
93
- if (file.result.errors === void 0) {
94
- file.result.errors = [];
95
- }
96
- file.result.errors.push(
97
- processError(new Error(`No test found in ${file.name} in ${message}`))
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
- return `${task.suite ? `${getTaskFullName(task.suite)} ` : ""}${task.name}`;
104
+ return `${task.suite ? `${getTaskFullName(task.suite)} ` : ""}${task.name}`;
103
105
  }
104
106
  function someTasksAreOnly(suite) {
105
- return suite.tasks.some(
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
- 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
- });
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
- 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
- });
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
- if (allowOnly) {
131
- return;
132
- }
133
- const error = processError(
134
- new Error(
135
- "[Vitest] Unexpected .only modifier. Remove it or pass --allowOnly argument to bypass this error"
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
- let hash = 0;
145
- if (str.length === 0) {
146
- return `${hash}`;
147
- }
148
- for (let i = 0; i < str.length; i++) {
149
- const char = str.charCodeAt(i);
150
- hash = (hash << 5) - hash + char;
151
- hash = hash & hash;
152
- }
153
- return `${hash}`;
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
- parent.tasks.forEach((t, idx) => {
157
- t.id = `${parent.id}_${idx}`;
158
- if (t.type === "suite") {
159
- calculateSuiteHash(t);
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
- const path = relative(root, filepath);
165
- const file = {
166
- id: generateFileHash(path, projectName),
167
- name: path,
168
- type: "suite",
169
- mode: "queued",
170
- filepath,
171
- tasks: [],
172
- meta: /* @__PURE__ */ Object.create(null),
173
- projectName,
174
- file: void 0,
175
- pool
176
- };
177
- file.file = file;
178
- return file;
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
- return generateHash(`${file}${projectName || ""}`);
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
- let count = 0;
186
- let head;
187
- let tail;
188
- const finish = () => {
189
- count--;
190
- if (head) {
191
- head[0]();
192
- head = head[1];
193
- tail = head && tail;
194
- }
195
- };
196
- return (func, ...args) => {
197
- return new Promise((resolve) => {
198
- if (count++ < concurrency) {
199
- resolve();
200
- } else if (tail) {
201
- tail = tail[1] = [resolve];
202
- } else {
203
- head = tail = [resolve];
204
- }
205
- }).then(() => {
206
- return func(...args);
207
- }).finally(finish);
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
- let tasksGroup = [];
213
- const tasksGroups = [];
214
- for (const c of suite.tasks) {
215
- if (tasksGroup.length === 0 || c.concurrent === tasksGroup[0].concurrent) {
216
- tasksGroup.push(c);
217
- } else {
218
- tasksGroups.push(tasksGroup);
219
- tasksGroup = [c];
220
- }
221
- }
222
- if (tasksGroup.length > 0) {
223
- tasksGroups.push(tasksGroup);
224
- }
225
- return tasksGroups;
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
- return isTestCase(s);
239
+ return isTestCase(s);
230
240
  }
231
241
  function isTestCase(s) {
232
- return s.type === "test";
242
+ return s.type === "test";
233
243
  }
234
244
  function getTests(suite) {
235
- const tests = [];
236
- const arraySuites = toArray(suite);
237
- for (const s of arraySuites) {
238
- if (isTestCase(s)) {
239
- tests.push(s);
240
- } else {
241
- for (const task of s.tasks) {
242
- if (isTestCase(task)) {
243
- tests.push(task);
244
- } else {
245
- const taskTests = getTests(task);
246
- for (const test of taskTests) {
247
- tests.push(test);
248
- }
249
- }
250
- }
251
- }
252
- }
253
- return tests;
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
- return toArray(tasks).flatMap(
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
- return toArray(suite).flatMap(
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
- return toArray(suite).some(
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
- return toArray(suite).some(
272
- (s) => {
273
- var _a;
274
- return ((_a = s.result) == null ? void 0 : _a.state) === "fail" || s.type === "suite" && hasFailed(s.tasks);
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
- const names = [task.name];
280
- let current = task;
281
- while (current == null ? void 0 : current.suite) {
282
- current = current.suite;
283
- if (current == null ? void 0 : current.name) {
284
- names.unshift(current.name);
285
- }
286
- }
287
- if (current !== task.file) {
288
- names.unshift(task.file.name);
289
- }
290
- return names;
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
- return getNames(task).join(separator);
295
+ return getNames(task).join(separator);
294
296
  }
295
297
  function getTestName(task, separator = " > ") {
296
- return getNames(task).slice(1).join(separator);
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-D-sw4YOL.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-D-sw4YOL.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-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';