vitest 4.0.0-beta.5 → 4.0.0-beta.7
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/LICENSE.md +1 -1
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +2 -2
- package/dist/chunks/{base.DMfOuRWD.js → base.BXI97p6t.js} +7 -16
- package/dist/chunks/{benchmark.CtuRzf-i.js → benchmark.UW6Ezvxy.js} +4 -9
- package/dist/chunks/{browser.d.Cawq_X_N.d.ts → browser.d.DOMmqJQx.d.ts} +1 -1
- package/dist/chunks/{cac.CKnbxhn2.js → cac.Dsn7ixFt.js} +38 -113
- package/dist/chunks/{cli-api.COn58yrl.js → cli-api.DfGJyldU.js} +829 -1232
- package/dist/chunks/{config.d.CKNVOKm0.d.ts → config.d._GBBbReY.d.ts} +1 -0
- package/dist/chunks/{console.Duv2dVIC.js → console.B0quX7yH.js} +32 -68
- package/dist/chunks/{coverage.B6cReEn1.js → coverage.Dvxug1RM.js} +210 -579
- package/dist/chunks/{creator.DUVZ6rfm.js → creator.KEg6n5IC.js} +28 -74
- package/dist/chunks/{date.Bq6ZW5rf.js → date.-jtEtIeV.js} +6 -17
- package/dist/chunks/{git.BVQ8w_Sw.js → git.BFNcloKD.js} +1 -2
- package/dist/chunks/{globals.CJQ63oO0.js → globals.lgsmH00r.js} +5 -5
- package/dist/chunks/{index.QZr3S3vQ.js → index.AR8aAkCC.js} +2 -2
- package/dist/chunks/{index.DQhAfQQU.js → index.C3EbxYwt.js} +276 -607
- package/dist/chunks/{index.oWRWx-nj.js → index.CsFXYRkW.js} +17 -36
- package/dist/chunks/{index.DgN0Zk9a.js → index.D2B6d2vv.js} +14 -24
- package/dist/chunks/{index.BRtIe7r8.js → index.DfviD7lX.js} +55 -110
- package/dist/chunks/{inspector.C914Efll.js → inspector.CvQD-Nie.js} +10 -25
- package/dist/chunks/{moduleRunner.d.mmOmOGrW.d.ts → moduleRunner.d.CX4DuqOx.d.ts} +2 -2
- package/dist/chunks/{node.4JV5OXkt.js → node.BOqcT2jW.js} +1 -1
- package/dist/chunks/{plugin.d.CvOlgjxK.d.ts → plugin.d.vcD4xbMS.d.ts} +1 -1
- package/dist/chunks/{reporters.d.CYE9sT5z.d.ts → reporters.d.BC86JJdB.d.ts} +799 -758
- package/dist/chunks/{resolver.D5bG4zy5.js → resolver.Bx6lE0iq.js} +21 -64
- package/dist/chunks/{rpc.DGoW_Vl-.js → rpc.RpPylpp0.js} +7 -21
- package/dist/chunks/{runBaseTests.B3KcKqlF.js → runBaseTests.D6sfuWBM.js} +25 -54
- package/dist/chunks/{setup-common.lgPs-bYv.js → setup-common.hLGRxhC8.js} +9 -22
- package/dist/chunks/{startModuleRunner.C8FtT_BY.js → startModuleRunner.C8TW8zTN.js} +83 -205
- package/dist/chunks/{typechecker.BgoW4nTA.js → typechecker.DSo_maXz.js} +97 -209
- package/dist/chunks/{utils.CcGm2cd1.js → utils.C2YI6McM.js} +4 -13
- package/dist/chunks/{utils.B9FY3b73.js → utils.C7__0Iv5.js} +5 -14
- package/dist/chunks/{vi.DGAfBY4R.js → vi.BfdOiD4j.js} +110 -267
- package/dist/chunks/{vm.BKfKvaKl.js → vm.BHBje7cC.js} +73 -177
- package/dist/chunks/{worker.d.Db-UVmXc.d.ts → worker.d.BKu8cnnX.d.ts} +1 -1
- package/dist/chunks/{worker.d.D9QWnzAe.d.ts → worker.d.DYlqbejz.d.ts} +1 -1
- package/dist/cli.js +3 -3
- package/dist/config.d.ts +7 -7
- package/dist/coverage.d.ts +4 -4
- package/dist/coverage.js +2 -2
- package/dist/environments.js +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +5 -5
- package/dist/module-evaluator.d.ts +3 -3
- package/dist/module-evaluator.js +33 -84
- package/dist/module-runner.js +2 -2
- package/dist/node.d.ts +11 -9
- package/dist/node.js +16 -27
- package/dist/reporters.d.ts +5 -5
- package/dist/reporters.js +3 -3
- package/dist/runners.d.ts +1 -1
- package/dist/runners.js +23 -51
- package/dist/snapshot.js +2 -2
- package/dist/suite.js +2 -2
- package/dist/worker.js +18 -34
- package/dist/workers/forks.js +4 -4
- package/dist/workers/runVmTests.js +19 -37
- package/dist/workers/threads.js +4 -4
- package/dist/workers/vmForks.js +7 -7
- package/dist/workers/vmThreads.js +7 -7
- package/dist/workers.d.ts +3 -3
- package/dist/workers.js +11 -11
- package/package.json +11 -11
|
@@ -12,10 +12,7 @@ import { MockerRegistry, mockObject, RedirectedModule, AutomockedModule } from '
|
|
|
12
12
|
import { ModuleRunner } from 'vite/module-runner';
|
|
13
13
|
import { V as VitestTransport } from './moduleTransport.I-bgQy0S.js';
|
|
14
14
|
|
|
15
|
-
const bareVitestRegexp = /^@?vitest(?:\/|$)
|
|
16
|
-
const normalizedDistDir = normalize$1(distDir);
|
|
17
|
-
const relativeIds = {};
|
|
18
|
-
const externalizeMap = /* @__PURE__ */ new Map();
|
|
15
|
+
const bareVitestRegexp = /^@?vitest(?:\/|$)/, normalizedDistDir = normalize$1(distDir), relativeIds = {}, externalizeMap = /* @__PURE__ */ new Map();
|
|
19
16
|
// all Vitest imports always need to be externalized
|
|
20
17
|
function getCachedVitestImport(id, state) {
|
|
21
18
|
if (id.startsWith("/@fs/") || id.startsWith("\\@fs\\")) id = id.slice(process.platform === "win32" ? 5 : 4);
|
|
@@ -25,99 +22,66 @@ function getCachedVitestImport(id, state) {
|
|
|
25
22
|
};
|
|
26
23
|
// always externalize Vitest because we import from there before running tests
|
|
27
24
|
// so we already have it cached by Node.js
|
|
28
|
-
const root = state().config.root;
|
|
29
|
-
const relativeRoot = relativeIds[root] ?? (relativeIds[root] = normalizedDistDir.slice(root.length));
|
|
25
|
+
const root = state().config.root, relativeRoot = relativeIds[root] ?? (relativeIds[root] = normalizedDistDir.slice(root.length));
|
|
30
26
|
if (id.includes(distDir) || id.includes(normalizedDistDir)) {
|
|
31
27
|
const externalize = id.startsWith("file://") ? id : pathToFileURL(id).toString();
|
|
32
|
-
externalizeMap.set(id, externalize)
|
|
33
|
-
return {
|
|
28
|
+
return externalizeMap.set(id, externalize), {
|
|
34
29
|
externalize,
|
|
35
30
|
type: "module"
|
|
36
31
|
};
|
|
37
32
|
}
|
|
38
33
|
if (relativeRoot && relativeRoot !== "/" && id.startsWith(relativeRoot)) {
|
|
39
|
-
const path = join$1(root, id);
|
|
40
|
-
|
|
41
|
-
externalizeMap.set(id, externalize);
|
|
42
|
-
return {
|
|
34
|
+
const path = join$1(root, id), externalize = pathToFileURL(path).toString();
|
|
35
|
+
return externalizeMap.set(id, externalize), {
|
|
43
36
|
externalize,
|
|
44
37
|
type: "module"
|
|
45
38
|
};
|
|
46
39
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
type: "module"
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
return null;
|
|
40
|
+
return bareVitestRegexp.test(id) ? (externalizeMap.set(id, id), {
|
|
41
|
+
externalize: id,
|
|
42
|
+
type: "module"
|
|
43
|
+
}) : null;
|
|
55
44
|
}
|
|
56
45
|
|
|
57
46
|
const dispose = [];
|
|
58
47
|
function listenForErrors(state) {
|
|
59
|
-
dispose.forEach((fn) => fn());
|
|
60
|
-
dispose.length = 0;
|
|
48
|
+
dispose.forEach((fn) => fn()), dispose.length = 0;
|
|
61
49
|
function catchError(err, type, event) {
|
|
62
|
-
const worker = state();
|
|
63
|
-
const listeners = process.listeners(event);
|
|
50
|
+
const worker = state(), listeners = process.listeners(event);
|
|
64
51
|
// if there is another listener, assume that it's handled by user code
|
|
65
52
|
// one is Vitest's own listener
|
|
66
53
|
if (listeners.length > 1) return;
|
|
67
54
|
const error = processError(err);
|
|
68
55
|
if (typeof error === "object" && error != null) {
|
|
69
|
-
error.VITEST_TEST_NAME = worker.current?.type === "test" ? worker.current.name : void 0;
|
|
70
|
-
if (worker.filepath) error.VITEST_TEST_PATH = worker.filepath;
|
|
56
|
+
if (error.VITEST_TEST_NAME = worker.current?.type === "test" ? worker.current.name : void 0, worker.filepath) error.VITEST_TEST_PATH = worker.filepath;
|
|
71
57
|
error.VITEST_AFTER_ENV_TEARDOWN = worker.environmentTeardownRun;
|
|
72
58
|
}
|
|
73
59
|
state().rpc.onUnhandledError(error, type);
|
|
74
60
|
}
|
|
75
|
-
const uncaughtException = (e) => catchError(e, "Uncaught Exception", "uncaughtException");
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
process.on("unhandledRejection", unhandledRejection);
|
|
79
|
-
dispose.push(() => {
|
|
80
|
-
process.off("uncaughtException", uncaughtException);
|
|
81
|
-
process.off("unhandledRejection", unhandledRejection);
|
|
61
|
+
const uncaughtException = (e) => catchError(e, "Uncaught Exception", "uncaughtException"), unhandledRejection = (e) => catchError(e, "Unhandled Rejection", "unhandledRejection");
|
|
62
|
+
process.on("uncaughtException", uncaughtException), process.on("unhandledRejection", unhandledRejection), dispose.push(() => {
|
|
63
|
+
process.off("uncaughtException", uncaughtException), process.off("unhandledRejection", unhandledRejection);
|
|
82
64
|
});
|
|
83
65
|
}
|
|
84
66
|
|
|
85
67
|
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
86
68
|
function normalizeWindowsPath(input = "") {
|
|
87
|
-
|
|
88
|
-
return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
|
69
|
+
return input && input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
|
89
70
|
}
|
|
90
|
-
const _UNC_REGEX = /^[/\\]{2}
|
|
91
|
-
const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
92
|
-
const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
|
|
93
|
-
const _EXTNAME_RE = /.(\.[^./]+|\.)$/;
|
|
94
|
-
const normalize = function(path) {
|
|
71
|
+
const _UNC_REGEX = /^[/\\]{2}/, _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/, _DRIVE_LETTER_RE = /^[A-Za-z]:$/, _EXTNAME_RE = /.(\.[^./]+|\.)$/, normalize = function(path) {
|
|
95
72
|
if (path.length === 0) return ".";
|
|
96
73
|
path = normalizeWindowsPath(path);
|
|
97
|
-
const isUNCPath = path.match(_UNC_REGEX);
|
|
98
|
-
|
|
99
|
-
const trailingSeparator = path[path.length - 1] === "/";
|
|
100
|
-
path = normalizeString(path, !isPathAbsolute);
|
|
101
|
-
if (path.length === 0) {
|
|
102
|
-
if (isPathAbsolute) return "/";
|
|
103
|
-
return trailingSeparator ? "./" : ".";
|
|
104
|
-
}
|
|
74
|
+
const isUNCPath = path.match(_UNC_REGEX), isPathAbsolute = isAbsolute(path), trailingSeparator = path[path.length - 1] === "/";
|
|
75
|
+
if (path = normalizeString(path, !isPathAbsolute), path.length === 0) return isPathAbsolute ? "/" : trailingSeparator ? "./" : ".";
|
|
105
76
|
if (trailingSeparator) path += "/";
|
|
106
77
|
if (_DRIVE_LETTER_RE.test(path)) path += "/";
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return `//${path}`;
|
|
110
|
-
}
|
|
111
|
-
return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
|
|
112
|
-
};
|
|
113
|
-
const join = function(...segments) {
|
|
78
|
+
return isUNCPath ? isPathAbsolute ? `//${path}` : `//./${path}` : isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
|
|
79
|
+
}, join = function(...segments) {
|
|
114
80
|
let path = "";
|
|
115
81
|
for (const seg of segments) {
|
|
116
82
|
if (!seg) continue;
|
|
117
83
|
if (path.length > 0) {
|
|
118
|
-
const pathTrailing = path[path.length - 1] === "/";
|
|
119
|
-
const segLeading = seg[0] === "/";
|
|
120
|
-
const both = pathTrailing && segLeading;
|
|
84
|
+
const pathTrailing = path[path.length - 1] === "/", segLeading = seg[0] === "/", both = pathTrailing && segLeading;
|
|
121
85
|
if (both) path += seg.slice(1);
|
|
122
86
|
else path += pathTrailing || segLeading ? seg : `/${seg}`;
|
|
123
87
|
} else path += seg;
|
|
@@ -125,29 +89,19 @@ const join = function(...segments) {
|
|
|
125
89
|
return normalize(path);
|
|
126
90
|
};
|
|
127
91
|
function cwd$1() {
|
|
128
|
-
|
|
129
|
-
return "/";
|
|
92
|
+
return typeof process !== "undefined" && typeof process.cwd === "function" ? process.cwd().replace(/\\/g, "/") : "/";
|
|
130
93
|
}
|
|
131
94
|
const resolve = function(...arguments_) {
|
|
132
95
|
arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
|
|
133
|
-
let resolvedPath = "";
|
|
134
|
-
let resolvedAbsolute = false;
|
|
96
|
+
let resolvedPath = "", resolvedAbsolute = false;
|
|
135
97
|
for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
|
|
136
98
|
const path = index >= 0 ? arguments_[index] : cwd$1();
|
|
137
|
-
|
|
138
|
-
resolvedPath = `${path}/${resolvedPath}`;
|
|
139
|
-
resolvedAbsolute = isAbsolute(path);
|
|
99
|
+
!path || path.length === 0 || (resolvedPath = `${path}/${resolvedPath}`, resolvedAbsolute = isAbsolute(path));
|
|
140
100
|
}
|
|
141
|
-
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
|
142
|
-
if (resolvedAbsolute && !isAbsolute(resolvedPath)) return `/${resolvedPath}`;
|
|
143
|
-
return resolvedPath.length > 0 ? resolvedPath : ".";
|
|
101
|
+
return resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute), resolvedAbsolute && !isAbsolute(resolvedPath) ? `/${resolvedPath}` : resolvedPath.length > 0 ? resolvedPath : ".";
|
|
144
102
|
};
|
|
145
103
|
function normalizeString(path, allowAboveRoot) {
|
|
146
|
-
let res = "";
|
|
147
|
-
let lastSegmentLength = 0;
|
|
148
|
-
let lastSlash = -1;
|
|
149
|
-
let dots = 0;
|
|
150
|
-
let char = null;
|
|
104
|
+
let res = "", lastSegmentLength = 0, lastSlash = -1, dots = 0, char = null;
|
|
151
105
|
for (let index = 0; index <= path.length; ++index) {
|
|
152
106
|
if (index < path.length) char = path[index];
|
|
153
107
|
else if (char === "/") break;
|
|
@@ -158,35 +112,22 @@ function normalizeString(path, allowAboveRoot) {
|
|
|
158
112
|
if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
|
|
159
113
|
if (res.length > 2) {
|
|
160
114
|
const lastSlashIndex = res.lastIndexOf("/");
|
|
161
|
-
if (lastSlashIndex === -1)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
} else {
|
|
165
|
-
res = res.slice(0, lastSlashIndex);
|
|
166
|
-
lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
|
|
167
|
-
}
|
|
168
|
-
lastSlash = index;
|
|
169
|
-
dots = 0;
|
|
115
|
+
if (lastSlashIndex === -1) res = "", lastSegmentLength = 0;
|
|
116
|
+
else res = res.slice(0, lastSlashIndex), lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
|
|
117
|
+
lastSlash = index, dots = 0;
|
|
170
118
|
continue;
|
|
171
119
|
} else if (res.length > 0) {
|
|
172
|
-
res = "";
|
|
173
|
-
lastSegmentLength = 0;
|
|
174
|
-
lastSlash = index;
|
|
175
|
-
dots = 0;
|
|
120
|
+
res = "", lastSegmentLength = 0, lastSlash = index, dots = 0;
|
|
176
121
|
continue;
|
|
177
122
|
}
|
|
178
123
|
}
|
|
179
|
-
if (allowAboveRoot)
|
|
180
|
-
res += res.length > 0 ? "/.." : "..";
|
|
181
|
-
lastSegmentLength = 2;
|
|
182
|
-
}
|
|
124
|
+
if (allowAboveRoot) res += res.length > 0 ? "/.." : "..", lastSegmentLength = 2;
|
|
183
125
|
} else {
|
|
184
126
|
if (res.length > 0) res += `/${path.slice(lastSlash + 1, index)}`;
|
|
185
127
|
else res = path.slice(lastSlash + 1, index);
|
|
186
128
|
lastSegmentLength = index - lastSlash - 1;
|
|
187
129
|
}
|
|
188
|
-
lastSlash = index;
|
|
189
|
-
dots = 0;
|
|
130
|
+
lastSlash = index, dots = 0;
|
|
190
131
|
} else if (char === "." && dots !== -1) ++dots;
|
|
191
132
|
else dots = -1;
|
|
192
133
|
}
|
|
@@ -194,18 +135,15 @@ function normalizeString(path, allowAboveRoot) {
|
|
|
194
135
|
}
|
|
195
136
|
const isAbsolute = function(p) {
|
|
196
137
|
return _IS_ABSOLUTE_RE.test(p);
|
|
197
|
-
}
|
|
198
|
-
const extname = function(p) {
|
|
138
|
+
}, extname = function(p) {
|
|
199
139
|
if (p === "..") return "";
|
|
200
140
|
const match = _EXTNAME_RE.exec(normalizeWindowsPath(p));
|
|
201
141
|
return match && match[1] || "";
|
|
202
|
-
}
|
|
203
|
-
const dirname = function(p) {
|
|
142
|
+
}, dirname = function(p) {
|
|
204
143
|
const segments = normalizeWindowsPath(p).replace(/\/$/, "").split("/").slice(0, -1);
|
|
205
144
|
if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) segments[0] += "/";
|
|
206
145
|
return segments.join("/") || (isAbsolute(p) ? "/" : ".");
|
|
207
|
-
}
|
|
208
|
-
const basename = function(p, extension) {
|
|
146
|
+
}, basename = function(p, extension) {
|
|
209
147
|
const segments = normalizeWindowsPath(p).split("/");
|
|
210
148
|
let lastSegment = "";
|
|
211
149
|
for (let i = segments.length - 1; i >= 0; i--) {
|
|
@@ -224,8 +162,7 @@ function findMockRedirect(root, mockPath, external) {
|
|
|
224
162
|
// it's a node_module alias
|
|
225
163
|
// all mocks should be inside <root>/__mocks__
|
|
226
164
|
if (external || isNodeBuiltin(mockPath) || !existsSync(mockPath)) {
|
|
227
|
-
const mockDirname = dirname(path);
|
|
228
|
-
const mockFolder = join(root, "__mocks__", mockDirname);
|
|
165
|
+
const mockDirname = dirname(path), mockFolder = join(root, "__mocks__", mockDirname);
|
|
229
166
|
if (!existsSync(mockFolder)) return null;
|
|
230
167
|
const baseOriginal = basename(path);
|
|
231
168
|
function findFile(mockFolder, baseOriginal) {
|
|
@@ -236,7 +173,7 @@ function findMockRedirect(root, mockPath, external) {
|
|
|
236
173
|
const path = resolve(mockFolder, file);
|
|
237
174
|
// if the same name, return the file
|
|
238
175
|
if (statSync(path).isFile()) return path;
|
|
239
|
-
|
|
176
|
+
{
|
|
240
177
|
// find folder/index.{js,ts}
|
|
241
178
|
const indexFile = findFile(path, "index");
|
|
242
179
|
if (indexFile) return indexFile;
|
|
@@ -247,9 +184,7 @@ function findMockRedirect(root, mockPath, external) {
|
|
|
247
184
|
}
|
|
248
185
|
return findFile(mockFolder, baseOriginal);
|
|
249
186
|
}
|
|
250
|
-
const dir = dirname(path);
|
|
251
|
-
const baseId = basename(path);
|
|
252
|
-
const fullPath = resolve(dir, "__mocks__", baseId);
|
|
187
|
+
const dir = dirname(path), baseId = basename(path), fullPath = resolve(dir, "__mocks__", baseId);
|
|
253
188
|
return existsSync(fullPath) ? fullPath : null;
|
|
254
189
|
}
|
|
255
190
|
const builtins = new Set([
|
|
@@ -267,18 +202,14 @@ const builtins = new Set([
|
|
|
267
202
|
"timers/promises",
|
|
268
203
|
"util/types",
|
|
269
204
|
"wasi"
|
|
270
|
-
])
|
|
271
|
-
// https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix
|
|
272
|
-
const prefixedBuiltins$1 = new Set([
|
|
205
|
+
]), prefixedBuiltins$1 = new Set([
|
|
273
206
|
"node:sea",
|
|
274
207
|
"node:sqlite",
|
|
275
208
|
"node:test",
|
|
276
209
|
"node:test/reporters"
|
|
277
|
-
]);
|
|
278
|
-
const NODE_BUILTIN_NAMESPACE = "node:";
|
|
210
|
+
]), NODE_BUILTIN_NAMESPACE = "node:";
|
|
279
211
|
function isNodeBuiltin(id) {
|
|
280
|
-
|
|
281
|
-
return builtins.has(id.startsWith(NODE_BUILTIN_NAMESPACE) ? id.slice(5) : id);
|
|
212
|
+
return prefixedBuiltins$1.has(id) ? true : builtins.has(id.startsWith(NODE_BUILTIN_NAMESPACE) ? id.slice(5) : id);
|
|
282
213
|
}
|
|
283
214
|
|
|
284
215
|
const spyModulePath = resolve$1(distDir, "spy.js");
|
|
@@ -290,8 +221,7 @@ class VitestMocker {
|
|
|
290
221
|
registries = /* @__PURE__ */ new Map();
|
|
291
222
|
mockContext = { callstack: null };
|
|
292
223
|
constructor(moduleRunner, options) {
|
|
293
|
-
this.moduleRunner = moduleRunner;
|
|
294
|
-
this.options = options;
|
|
224
|
+
this.moduleRunner = moduleRunner, this.options = options;
|
|
295
225
|
const context = this.options.context;
|
|
296
226
|
if (context) this.primitives = vm.runInContext("({ Object, Error, Function, RegExp, Symbol, Array, Map })", context);
|
|
297
227
|
else this.primitives = {
|
|
@@ -331,8 +261,7 @@ class VitestMocker {
|
|
|
331
261
|
return this.options.moduleDirectories || [];
|
|
332
262
|
}
|
|
333
263
|
async initializeSpyModule() {
|
|
334
|
-
|
|
335
|
-
this.spyModule = await this.moduleRunner.import(spyModulePath);
|
|
264
|
+
this.spyModule ||= await this.moduleRunner.import(spyModulePath);
|
|
336
265
|
}
|
|
337
266
|
getMockerRegistry() {
|
|
338
267
|
const suite = this.getSuiteFilepath();
|
|
@@ -343,12 +272,8 @@ class VitestMocker {
|
|
|
343
272
|
this.registries.clear();
|
|
344
273
|
}
|
|
345
274
|
invalidateModuleById(id) {
|
|
346
|
-
const mockId = this.getMockPath(id);
|
|
347
|
-
|
|
348
|
-
if (node) {
|
|
349
|
-
this.evaluatedModules.invalidateModule(node);
|
|
350
|
-
node.mockedExports = void 0;
|
|
351
|
-
}
|
|
275
|
+
const mockId = this.getMockPath(id), node = this.evaluatedModules.getModuleById(mockId);
|
|
276
|
+
if (node) this.evaluatedModules.invalidateModule(node), node.mockedExports = void 0;
|
|
352
277
|
}
|
|
353
278
|
isModuleDirectory(path) {
|
|
354
279
|
return this.moduleDirectories.some((dir) => path.includes(dir));
|
|
@@ -357,10 +282,8 @@ class VitestMocker {
|
|
|
357
282
|
return this.options.getCurrentTestFilepath() || "global";
|
|
358
283
|
}
|
|
359
284
|
createError(message, codeFrame) {
|
|
360
|
-
const Error = this.primitives.Error;
|
|
361
|
-
|
|
362
|
-
Object.assign(error, { codeFrame });
|
|
363
|
-
return error;
|
|
285
|
+
const Error = this.primitives.Error, error = new Error(message);
|
|
286
|
+
return Object.assign(error, { codeFrame }), error;
|
|
364
287
|
}
|
|
365
288
|
async resolveId(rawId, importer) {
|
|
366
289
|
const result = await this.options.resolveId(rawId, importer);
|
|
@@ -382,31 +305,26 @@ class VitestMocker {
|
|
|
382
305
|
};
|
|
383
306
|
}
|
|
384
307
|
async resolveMocks() {
|
|
385
|
-
|
|
386
|
-
await Promise.all(VitestMocker.pendingIds.map(async (mock) => {
|
|
308
|
+
VitestMocker.pendingIds.length && (await Promise.all(VitestMocker.pendingIds.map(async (mock) => {
|
|
387
309
|
const { id, url, external } = await this.resolveId(mock.id, mock.importer);
|
|
388
310
|
if (mock.action === "unmock") this.unmockPath(id);
|
|
389
311
|
if (mock.action === "mock") this.mockPath(mock.id, id, url, external, mock.type, mock.factory);
|
|
390
|
-
}));
|
|
391
|
-
VitestMocker.pendingIds = [];
|
|
312
|
+
})), VitestMocker.pendingIds = []);
|
|
392
313
|
}
|
|
393
314
|
ensureModule(id, url) {
|
|
394
315
|
const node = this.evaluatedModules.ensureModule(id, url);
|
|
395
|
-
|
|
396
|
-
node.meta = {
|
|
316
|
+
return node.meta = {
|
|
397
317
|
id,
|
|
398
318
|
url,
|
|
399
319
|
code: "",
|
|
400
320
|
file: null,
|
|
401
321
|
invalidate: false
|
|
402
|
-
};
|
|
403
|
-
return node;
|
|
322
|
+
}, node;
|
|
404
323
|
}
|
|
405
324
|
async callFunctionMock(id, url, mock) {
|
|
406
325
|
const node = this.ensureModule(id, url);
|
|
407
326
|
if (node.exports) return node.exports;
|
|
408
|
-
const exports = await mock.resolve()
|
|
409
|
-
const moduleExports = new Proxy(exports, { get: (target, prop) => {
|
|
327
|
+
const exports = await mock.resolve(), moduleExports = new Proxy(exports, { get: (target, prop) => {
|
|
410
328
|
const val = target[prop];
|
|
411
329
|
// 'then' can exist on non-Promise objects, need nested instanceof check for logic to work
|
|
412
330
|
if (prop === "then") {
|
|
@@ -425,8 +343,7 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
|
|
|
425
343
|
}
|
|
426
344
|
return val;
|
|
427
345
|
} });
|
|
428
|
-
node.exports = moduleExports;
|
|
429
|
-
return moduleExports;
|
|
346
|
+
return node.exports = moduleExports, moduleExports;
|
|
430
347
|
}
|
|
431
348
|
// public method to avoid circular dependency
|
|
432
349
|
getMockContext() {
|
|
@@ -444,18 +361,17 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
|
|
|
444
361
|
return findMockRedirect(this.root, mockPath, external);
|
|
445
362
|
}
|
|
446
363
|
mockObject(object, mockExports = {}, behavior = "automock") {
|
|
447
|
-
const
|
|
448
|
-
if (!
|
|
364
|
+
const createMockInstance = this.spyModule?.createMockInstance;
|
|
365
|
+
if (!createMockInstance) throw this.createError("[vitest] `spyModule` is not defined. This is a Vitest error. Please open a new issue with reproduction.");
|
|
449
366
|
return mockObject({
|
|
450
367
|
globalConstructors: this.primitives,
|
|
451
|
-
|
|
368
|
+
createMockInstance,
|
|
452
369
|
type: behavior
|
|
453
370
|
}, object, mockExports);
|
|
454
371
|
}
|
|
455
372
|
unmockPath(id) {
|
|
456
373
|
const registry = this.getMockerRegistry();
|
|
457
|
-
registry.deleteById(id);
|
|
458
|
-
this.invalidateModuleById(id);
|
|
374
|
+
registry.deleteById(id), this.invalidateModuleById(id);
|
|
459
375
|
}
|
|
460
376
|
mockPath(originalId, id, url, external, mockType, factory) {
|
|
461
377
|
const registry = this.getMockerRegistry();
|
|
@@ -470,9 +386,7 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
|
|
|
470
386
|
this.invalidateModuleById(id);
|
|
471
387
|
}
|
|
472
388
|
async importActual(rawId, importer, callstack) {
|
|
473
|
-
const { url } = await this.resolveId(rawId, importer);
|
|
474
|
-
const node = await this.moduleRunner.fetchModule(url, importer);
|
|
475
|
-
const result = await this.moduleRunner.cachedRequest(node.url, node, callstack || [importer], void 0, true);
|
|
389
|
+
const { url } = await this.resolveId(rawId, importer), node = await this.moduleRunner.fetchModule(url, importer), result = await this.moduleRunner.cachedRequest(node.url, node, callstack || [importer], void 0, true);
|
|
476
390
|
return result;
|
|
477
391
|
}
|
|
478
392
|
async importMock(rawId, importer) {
|
|
@@ -484,9 +398,7 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
|
|
|
484
398
|
else mock = new AutomockedModule(rawId, id, rawId);
|
|
485
399
|
}
|
|
486
400
|
if (mock.type === "automock" || mock.type === "autospy") {
|
|
487
|
-
const node = await this.moduleRunner.fetchModule(url, importer);
|
|
488
|
-
const mod = await this.moduleRunner.cachedRequest(url, node, [importer], void 0, true);
|
|
489
|
-
const Object = this.primitives.Object;
|
|
401
|
+
const node = await this.moduleRunner.fetchModule(url, importer), mod = await this.moduleRunner.cachedRequest(url, node, [importer], void 0, true), Object = this.primitives.Object;
|
|
490
402
|
return this.mockObject(mod, Object.create(Object.prototype), mock.type);
|
|
491
403
|
}
|
|
492
404
|
if (mock.type === "manual") return this.callFunctionMock(id, url, mock);
|
|
@@ -498,30 +410,19 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
|
|
|
498
410
|
if (mock.type === "automock" || mock.type === "autospy") {
|
|
499
411
|
const cache = this.evaluatedModules.getModuleById(mockId);
|
|
500
412
|
if (cache && cache.mockedExports) return cache.mockedExports;
|
|
501
|
-
const Object = this.primitives.Object;
|
|
502
|
-
// we have to define a separate object that will copy all properties into itself
|
|
503
|
-
// and can't just use the same `exports` define automatically by Vite before the evaluator
|
|
504
|
-
const exports = Object.create(null);
|
|
413
|
+
const Object = this.primitives.Object, exports = Object.create(null);
|
|
505
414
|
Object.defineProperty(exports, Symbol.toStringTag, {
|
|
506
415
|
value: "Module",
|
|
507
416
|
configurable: true,
|
|
508
417
|
writable: true
|
|
509
418
|
});
|
|
510
419
|
const node = this.ensureModule(mockId, this.getMockPath(evaluatedNode.url));
|
|
511
|
-
node.meta = evaluatedNode.meta;
|
|
512
|
-
node.file = evaluatedNode.file;
|
|
513
|
-
node.mockedExports = exports;
|
|
420
|
+
node.meta = evaluatedNode.meta, node.file = evaluatedNode.file, node.mockedExports = exports;
|
|
514
421
|
const mod = await this.moduleRunner.cachedRequest(url, node, callstack, void 0, true);
|
|
515
|
-
this.mockObject(mod, exports, mock.type);
|
|
516
|
-
return exports;
|
|
422
|
+
return this.mockObject(mod, exports, mock.type), exports;
|
|
517
423
|
}
|
|
518
424
|
if (mock.type === "manual" && !callstack.includes(mockId) && !callstack.includes(url)) try {
|
|
519
|
-
callstack.push(mockId);
|
|
520
|
-
// this will not work if user does Promise.all(import(), import())
|
|
521
|
-
// we can also use AsyncLocalStorage to store callstack, but this won't work in the browser
|
|
522
|
-
// maybe we should improve mock API in the future?
|
|
523
|
-
this.mockContext.callstack = callstack;
|
|
524
|
-
return await this.callFunctionMock(mockId, this.getMockPath(url), mock);
|
|
425
|
+
return callstack.push(mockId), this.mockContext.callstack = callstack, await this.callFunctionMock(mockId, this.getMockPath(url), mock);
|
|
525
426
|
} finally {
|
|
526
427
|
this.mockContext.callstack = null;
|
|
527
428
|
const indexMock = callstack.indexOf(mockId);
|
|
@@ -531,8 +432,7 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
|
|
|
531
432
|
}
|
|
532
433
|
async mockedRequest(url, evaluatedNode, callstack) {
|
|
533
434
|
const mock = this.getDependencyMock(evaluatedNode.id);
|
|
534
|
-
if (
|
|
535
|
-
return this.requestWithMockedModule(url, evaluatedNode, callstack, mock);
|
|
435
|
+
if (mock) return this.requestWithMockedModule(url, evaluatedNode, callstack, mock);
|
|
536
436
|
}
|
|
537
437
|
queueMock(id, importer, factoryOrOptions) {
|
|
538
438
|
const mockType = getMockType(factoryOrOptions);
|
|
@@ -553,9 +453,7 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
|
|
|
553
453
|
}
|
|
554
454
|
}
|
|
555
455
|
function getMockType(factoryOrOptions) {
|
|
556
|
-
|
|
557
|
-
if (typeof factoryOrOptions === "function") return "manual";
|
|
558
|
-
return factoryOrOptions.spy ? "autospy" : "automock";
|
|
456
|
+
return factoryOrOptions ? typeof factoryOrOptions === "function" ? "manual" : factoryOrOptions.spy ? "autospy" : "automock" : "automock";
|
|
559
457
|
}
|
|
560
458
|
// unique id that is not available as "$bare_import" like "test"
|
|
561
459
|
// https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix
|
|
@@ -564,8 +462,7 @@ const prefixedBuiltins = new Set([
|
|
|
564
462
|
"node:sqlite",
|
|
565
463
|
"node:test",
|
|
566
464
|
"node:test/reporters"
|
|
567
|
-
]);
|
|
568
|
-
const isWindows$1 = process.platform === "win32";
|
|
465
|
+
]), isWindows$1 = process.platform === "win32";
|
|
569
466
|
// transform file url to id
|
|
570
467
|
// virtual:custom -> virtual:custom
|
|
571
468
|
// \0custom -> \0custom
|
|
@@ -588,8 +485,7 @@ function slash(p) {
|
|
|
588
485
|
const multipleSlashRe = /^\/+/;
|
|
589
486
|
// module-runner incorrectly replaces file:///path with `///path`
|
|
590
487
|
function fixLeadingSlashes(id) {
|
|
591
|
-
|
|
592
|
-
return id;
|
|
488
|
+
return id.startsWith("//") ? id.replace(multipleSlashRe, "/") : id;
|
|
593
489
|
}
|
|
594
490
|
|
|
595
491
|
// @ts-expect-error overriding private method
|
|
@@ -597,17 +493,13 @@ class VitestModuleRunner extends ModuleRunner {
|
|
|
597
493
|
mocker;
|
|
598
494
|
moduleExecutionInfo;
|
|
599
495
|
constructor(options) {
|
|
600
|
-
const transport = new VitestTransport(options.transport);
|
|
601
|
-
|
|
602
|
-
super({
|
|
496
|
+
const transport = new VitestTransport(options.transport), evaluatedModules = options.evaluatedModules;
|
|
497
|
+
if (super({
|
|
603
498
|
transport,
|
|
604
499
|
hmr: false,
|
|
605
500
|
evaluatedModules,
|
|
606
501
|
sourcemapInterceptor: "prepareStackTrace"
|
|
607
|
-
}, options.evaluator)
|
|
608
|
-
this.options = options;
|
|
609
|
-
this.moduleExecutionInfo = options.getWorkerState().moduleExecutionInfo;
|
|
610
|
-
this.mocker = options.mocker || new VitestMocker(this, {
|
|
502
|
+
}, options.evaluator), this.options = options, this.moduleExecutionInfo = options.getWorkerState().moduleExecutionInfo, this.mocker = options.mocker || new VitestMocker(this, {
|
|
611
503
|
context: options.vm?.context,
|
|
612
504
|
resolveId: options.transport.resolveId,
|
|
613
505
|
get root() {
|
|
@@ -619,8 +511,7 @@ class VitestModuleRunner extends ModuleRunner {
|
|
|
619
511
|
getCurrentTestFilepath() {
|
|
620
512
|
return options.getWorkerState().filepath;
|
|
621
513
|
}
|
|
622
|
-
});
|
|
623
|
-
if (options.vm) options.vm.context.__vitest_mocker__ = this.mocker;
|
|
514
|
+
}), options.vm) options.vm.context.__vitest_mocker__ = this.mocker;
|
|
624
515
|
else Object.defineProperty(globalThis, "__vitest_mocker__", {
|
|
625
516
|
configurable: true,
|
|
626
517
|
writable: true,
|
|
@@ -629,8 +520,7 @@ class VitestModuleRunner extends ModuleRunner {
|
|
|
629
520
|
}
|
|
630
521
|
async import(rawId) {
|
|
631
522
|
const resolved = await this.options.transport.resolveId(rawId);
|
|
632
|
-
|
|
633
|
-
return super.import(resolved.url);
|
|
523
|
+
return resolved ? super.import(resolved.url) : super.import(rawId);
|
|
634
524
|
}
|
|
635
525
|
async fetchModule(url, importer) {
|
|
636
526
|
const module = await this.cachedModule(url, importer);
|
|
@@ -652,8 +542,7 @@ class VitestModuleRunner extends ModuleRunner {
|
|
|
652
542
|
const node = await this.fetchModule(mocked);
|
|
653
543
|
return this._cachedRequest(mocked, node, callstack, metadata);
|
|
654
544
|
}
|
|
655
|
-
|
|
656
|
-
return this._cachedRequest(url, mod, callstack, metadata);
|
|
545
|
+
return mocked != null && typeof mocked === "object" ? mocked : this._cachedRequest(url, mod, callstack, metadata);
|
|
657
546
|
}
|
|
658
547
|
/** @internal */
|
|
659
548
|
_invalidateSubTreeById(ids, invalidated = /* @__PURE__ */ new Set()) {
|
|
@@ -669,28 +558,21 @@ class VitestModuleRunner extends ModuleRunner {
|
|
|
669
558
|
}
|
|
670
559
|
}
|
|
671
560
|
|
|
672
|
-
const { readFileSync } = fs;
|
|
673
|
-
const browserExternalId = "__vite-browser-external";
|
|
674
|
-
const browserExternalLength = 24;
|
|
561
|
+
const { readFileSync } = fs, browserExternalId = "__vite-browser-external", browserExternalLength = 24;
|
|
675
562
|
const VITEST_VM_CONTEXT_SYMBOL = "__vitest_vm_context__";
|
|
676
|
-
const cwd = process.cwd();
|
|
677
|
-
const isWindows = process.platform === "win32";
|
|
563
|
+
const cwd = process.cwd(), isWindows = process.platform === "win32";
|
|
678
564
|
async function startVitestModuleRunner(options) {
|
|
679
|
-
const state = () => globalThis.__vitest_worker__ || options.state;
|
|
680
|
-
const rpc = () => state().rpc;
|
|
565
|
+
const state = () => globalThis.__vitest_worker__ || options.state, rpc = () => state().rpc;
|
|
681
566
|
process.exit = (code = process.exitCode || 0) => {
|
|
682
567
|
throw new Error(`process.exit unexpectedly called with "${code}"`);
|
|
683
|
-
};
|
|
684
|
-
listenForErrors(state);
|
|
568
|
+
}, listenForErrors(state);
|
|
685
569
|
const environment = () => {
|
|
686
570
|
const environment = state().environment;
|
|
687
571
|
return environment.viteEnvironment || environment.name;
|
|
688
|
-
}
|
|
689
|
-
const vm = options.context && options.externalModulesExecutor ? {
|
|
572
|
+
}, vm = options.context && options.externalModulesExecutor ? {
|
|
690
573
|
context: options.context,
|
|
691
574
|
externalModulesExecutor: options.externalModulesExecutor
|
|
692
|
-
} : void 0
|
|
693
|
-
const evaluator = options.evaluator || new VitestModuleEvaluator(vm, {
|
|
575
|
+
} : void 0, evaluator = options.evaluator || new VitestModuleEvaluator(vm, {
|
|
694
576
|
get moduleExecutionInfo() {
|
|
695
577
|
return state().moduleExecutionInfo;
|
|
696
578
|
},
|
|
@@ -698,8 +580,7 @@ async function startVitestModuleRunner(options) {
|
|
|
698
580
|
return state().config.deps.interopDefault;
|
|
699
581
|
},
|
|
700
582
|
getCurrentTestFilepath: () => state().filepath
|
|
701
|
-
})
|
|
702
|
-
const moduleRunner = new VitestModuleRunner({
|
|
583
|
+
}), moduleRunner = new VitestModuleRunner({
|
|
703
584
|
evaluatedModules: options.evaluatedModules,
|
|
704
585
|
evaluator,
|
|
705
586
|
mocker: options.mocker,
|
|
@@ -749,8 +630,7 @@ async function startVitestModuleRunner(options) {
|
|
|
749
630
|
// rethrow vite error if it cannot load the module because it's not resolved
|
|
750
631
|
if (typeof cause === "object" && cause != null && cause.code === "ERR_LOAD_URL" || typeof cause?.message === "string" && cause.message.includes("Failed to load url") || typeof cause?.message === "string" && cause.message.startsWith("Cannot find module '")) {
|
|
751
632
|
const error = new Error(`Cannot find ${isBareImport(id) ? "package" : "module"} '${id}'${importer ? ` imported from '${importer}'` : ""}`, { cause });
|
|
752
|
-
error.code = "ERR_MODULE_NOT_FOUND";
|
|
753
|
-
throw error;
|
|
633
|
+
throw error.code = "ERR_MODULE_NOT_FOUND", error;
|
|
754
634
|
}
|
|
755
635
|
throw cause;
|
|
756
636
|
} finally {
|
|
@@ -764,9 +644,7 @@ async function startVitestModuleRunner(options) {
|
|
|
764
644
|
getWorkerState: state,
|
|
765
645
|
vm
|
|
766
646
|
});
|
|
767
|
-
await moduleRunner.import("/@vite/env");
|
|
768
|
-
await moduleRunner.mocker.initializeSpyModule();
|
|
769
|
-
return moduleRunner;
|
|
647
|
+
return await moduleRunner.import("/@vite/env"), await moduleRunner.mocker.initializeSpyModule(), moduleRunner;
|
|
770
648
|
}
|
|
771
649
|
function toBuiltin(id) {
|
|
772
650
|
if (id.startsWith(browserExternalId)) id = id.slice(browserExternalLength);
|