@vitest/browser 2.0.0-beta.10 → 2.0.0-beta.11
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/context.d.ts +129 -12
- package/context.js +2 -0
- package/dist/client/.vite/manifest.json +8 -8
- package/dist/client/__vitest__/assets/index-BfnqOMHY.js +51 -0
- package/dist/client/__vitest__/assets/{index-BcFb8Rbc.css → index-qZYZB8Y3.css} +1 -1
- package/dist/client/__vitest__/index.html +16 -11
- package/dist/client/__vitest_browser__/{orchestrator-BCpOi5ot.js → orchestrator-DQ4hbmZ_.js} +141 -104
- package/dist/client/__vitest_browser__/{rpc-CImfI7bO.js → rpc-D6HtJ5Rb.js} +75 -55
- package/dist/client/__vitest_browser__/{tester-e70VCOgC.js → tester-IF8AbWCS.js} +256 -199
- package/dist/client/esm-client-injector.js +19 -18
- package/dist/client/orchestrator.html +2 -2
- package/dist/client/{tester.html → tester/tester.html} +12 -3
- package/dist/context.js +104 -16
- package/dist/index.d.ts +101 -5
- package/dist/index.js +1745 -270
- package/dist/providers.js +10 -6
- package/dist/state.js +1 -0
- package/dist/{webdriver-CXn0ag9T.js → webdriver-BRud6NtS.js} +22 -12
- package/package.json +9 -7
- package/providers/playwright.d.ts +27 -5
- package/dist/client/__vitest__/assets/index-BMAciMM5.js +0 -51
|
@@ -10,7 +10,10 @@ var __publicField = (obj, key, value) => {
|
|
|
10
10
|
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
11
11
|
return value;
|
|
12
12
|
};
|
|
13
|
-
import {
|
|
13
|
+
import { b as getConfig, e as rpc$1, i as importId, _ as __vitePreload, c as channel, f as extname, g as getBrowserState, w as waitForChannel, j as join, a as client, h as createSafeRpc, o as onCancel, k as getWorkerState } from "./rpc-D6HtJ5Rb.js";
|
|
14
|
+
import { processError, loadDiffConfig, loadSnapshotSerializers, takeCoverageInsideWorker, SpyModule, setupCommonEnv, startTests } from "/__virtual_vitest__?id=vitest%2Fbrowser";
|
|
15
|
+
import { stringify, format, TraceMap, originalPositionFor } from "/__virtual_vitest__?id=vitest%2Futils";
|
|
16
|
+
import { VitestTestRunner, NodeBenchmarkRunner } from "/__virtual_vitest__?id=vitest%2Frunners";
|
|
14
17
|
function getType(value) {
|
|
15
18
|
return Object.prototype.toString.apply(value).slice(8, -1);
|
|
16
19
|
}
|
|
@@ -35,20 +38,88 @@ function setupDialogsSpy() {
|
|
|
35
38
|
globalThis.confirm = showPopupWarning("confirm", false, true);
|
|
36
39
|
globalThis.prompt = showPopupWarning("prompt", null, "your value");
|
|
37
40
|
}
|
|
41
|
+
function on(event, listener) {
|
|
42
|
+
window.addEventListener(event, listener);
|
|
43
|
+
return () => window.removeEventListener(event, listener);
|
|
44
|
+
}
|
|
45
|
+
function serializeError(unhandledError) {
|
|
46
|
+
return {
|
|
47
|
+
...unhandledError,
|
|
48
|
+
name: unhandledError.name,
|
|
49
|
+
message: unhandledError.message,
|
|
50
|
+
stack: String(unhandledError.stack)
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function catchWindowErrors(cb) {
|
|
54
|
+
let userErrorListenerCount = 0;
|
|
55
|
+
function throwUnhandlerError(e) {
|
|
56
|
+
if (userErrorListenerCount === 0 && e.error != null) {
|
|
57
|
+
cb(e);
|
|
58
|
+
} else {
|
|
59
|
+
console.error(e.error);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const addEventListener = window.addEventListener.bind(window);
|
|
63
|
+
const removeEventListener = window.removeEventListener.bind(window);
|
|
64
|
+
window.addEventListener("error", throwUnhandlerError);
|
|
65
|
+
window.addEventListener = function(...args) {
|
|
66
|
+
if (args[0] === "error") {
|
|
67
|
+
userErrorListenerCount++;
|
|
68
|
+
}
|
|
69
|
+
return addEventListener.apply(this, args);
|
|
70
|
+
};
|
|
71
|
+
window.removeEventListener = function(...args) {
|
|
72
|
+
if (args[0] === "error" && userErrorListenerCount) {
|
|
73
|
+
userErrorListenerCount--;
|
|
74
|
+
}
|
|
75
|
+
return removeEventListener.apply(this, args);
|
|
76
|
+
};
|
|
77
|
+
return function clearErrorHandlers() {
|
|
78
|
+
window.removeEventListener("error", throwUnhandlerError);
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function registerUnexpectedErrors(rpc2) {
|
|
82
|
+
catchWindowErrors(
|
|
83
|
+
(event) => reportUnexpectedError(rpc2, "Error", event.error)
|
|
84
|
+
);
|
|
85
|
+
on("unhandledrejection", (event) => reportUnexpectedError(rpc2, "Unhandled Rejection", event.reason));
|
|
86
|
+
}
|
|
87
|
+
async function reportUnexpectedError(rpc2, type, error) {
|
|
88
|
+
const processedError = processError(error);
|
|
89
|
+
await rpc2.onUnhandledError(processedError, type);
|
|
90
|
+
}
|
|
38
91
|
const { Date: Date$1, console: console$1 } = globalThis;
|
|
39
|
-
|
|
40
|
-
const {
|
|
41
|
-
|
|
92
|
+
function setupConsoleLogSpy() {
|
|
93
|
+
const {
|
|
94
|
+
log,
|
|
95
|
+
info,
|
|
96
|
+
error,
|
|
97
|
+
dir,
|
|
98
|
+
dirxml,
|
|
99
|
+
trace,
|
|
100
|
+
time,
|
|
101
|
+
timeEnd,
|
|
102
|
+
timeLog,
|
|
103
|
+
warn,
|
|
104
|
+
debug: debug2,
|
|
105
|
+
count,
|
|
106
|
+
countReset
|
|
107
|
+
} = console$1;
|
|
42
108
|
const formatInput = (input) => {
|
|
43
|
-
if (input
|
|
44
|
-
return stringify(input
|
|
109
|
+
if (typeof input === "object") {
|
|
110
|
+
return stringify(input, void 0, {
|
|
111
|
+
printBasicPrototype: false,
|
|
112
|
+
escapeString: false
|
|
113
|
+
});
|
|
114
|
+
}
|
|
45
115
|
return format(input);
|
|
46
116
|
};
|
|
47
117
|
const processLog = (args) => args.map(formatInput).join(" ");
|
|
48
118
|
const sendLog = (type, content, disableStack) => {
|
|
49
119
|
var _a, _b, _c;
|
|
50
|
-
if (content.startsWith("[vite]"))
|
|
120
|
+
if (content.startsWith("[vite]")) {
|
|
51
121
|
return;
|
|
122
|
+
}
|
|
52
123
|
const unknownTestId = "__vitest__unknown_test__";
|
|
53
124
|
const taskId = ((_b = (_a = globalThis.__vitest_worker__) == null ? void 0 : _a.current) == null ? void 0 : _b.id) ?? unknownTestId;
|
|
54
125
|
const origin = getConfig().printConsoleTrace && !disableStack ? (_c = new Error("STACK_TRACE").stack) == null ? void 0 : _c.split("\n").slice(1).join("\n") : void 0;
|
|
@@ -63,12 +134,12 @@ async function setupConsoleLogSpy() {
|
|
|
63
134
|
});
|
|
64
135
|
};
|
|
65
136
|
const stdout = (base) => (...args) => {
|
|
137
|
+
base(...args);
|
|
66
138
|
sendLog("stdout", processLog(args));
|
|
67
|
-
return base(...args);
|
|
68
139
|
};
|
|
69
140
|
const stderr = (base) => (...args) => {
|
|
141
|
+
base(...args);
|
|
70
142
|
sendLog("stderr", processLog(args));
|
|
71
|
-
return base(...args);
|
|
72
143
|
};
|
|
73
144
|
console$1.log = stdout(log);
|
|
74
145
|
console$1.debug = stdout(debug2);
|
|
@@ -76,38 +147,39 @@ async function setupConsoleLogSpy() {
|
|
|
76
147
|
console$1.error = stderr(error);
|
|
77
148
|
console$1.warn = stderr(warn);
|
|
78
149
|
console$1.dir = (item, options) => {
|
|
79
|
-
|
|
80
|
-
|
|
150
|
+
dir(item, options);
|
|
151
|
+
sendLog("stdout", formatInput(item));
|
|
81
152
|
};
|
|
82
153
|
console$1.dirxml = (...args) => {
|
|
154
|
+
dirxml(...args);
|
|
83
155
|
sendLog("stdout", processLog(args));
|
|
84
|
-
return dirxml(...args);
|
|
85
156
|
};
|
|
86
157
|
console$1.trace = (...args) => {
|
|
87
158
|
var _a;
|
|
159
|
+
trace(...args);
|
|
88
160
|
const content = processLog(args);
|
|
89
161
|
const error2 = new Error("$$Trace");
|
|
90
162
|
const stack = (error2.stack || "").split("\n").slice(((_a = error2.stack) == null ? void 0 : _a.includes("$$Trace")) ? 2 : 1).join("\n");
|
|
91
163
|
sendLog("stderr", `${content}
|
|
92
164
|
${stack}`, true);
|
|
93
|
-
return trace(...args);
|
|
94
165
|
};
|
|
95
166
|
const timeLabels = {};
|
|
96
167
|
console$1.time = (label = "default") => {
|
|
97
|
-
const now2 = performance.now();
|
|
98
168
|
time(label);
|
|
169
|
+
const now2 = performance.now();
|
|
99
170
|
timeLabels[label] = now2;
|
|
100
171
|
};
|
|
101
172
|
console$1.timeLog = (label = "default") => {
|
|
102
173
|
timeLog(label);
|
|
103
|
-
if (!(label in timeLabels))
|
|
174
|
+
if (!(label in timeLabels)) {
|
|
104
175
|
sendLog("stderr", `Timer "${label}" does not exist`);
|
|
105
|
-
else
|
|
176
|
+
} else {
|
|
106
177
|
sendLog("stdout", `${label}: ${timeLabels[label]} ms`);
|
|
178
|
+
}
|
|
107
179
|
};
|
|
108
180
|
console$1.timeEnd = (label = "default") => {
|
|
109
|
-
const end = performance.now();
|
|
110
181
|
timeEnd(label);
|
|
182
|
+
const end = performance.now();
|
|
111
183
|
const start = timeLabels[label];
|
|
112
184
|
if (!(label in timeLabels)) {
|
|
113
185
|
sendLog("stderr", `Timer "${label}" does not exist`);
|
|
@@ -118,17 +190,24 @@ ${stack}`, true);
|
|
|
118
190
|
};
|
|
119
191
|
const countLabels = {};
|
|
120
192
|
console$1.count = (label = "default") => {
|
|
193
|
+
count(label);
|
|
121
194
|
const counter = (countLabels[label] ?? 0) + 1;
|
|
122
195
|
countLabels[label] = counter;
|
|
123
196
|
sendLog("stdout", `${label}: ${counter}`);
|
|
124
|
-
return count(label);
|
|
125
197
|
};
|
|
126
198
|
console$1.countReset = (label = "default") => {
|
|
199
|
+
countReset(label);
|
|
127
200
|
countLabels[label] = 0;
|
|
128
|
-
return countReset(label);
|
|
129
201
|
};
|
|
130
202
|
}
|
|
131
203
|
class VitestBrowserSnapshotEnvironment {
|
|
204
|
+
constructor() {
|
|
205
|
+
__publicField(this, "sourceMaps", /* @__PURE__ */ new Map());
|
|
206
|
+
__publicField(this, "traceMaps", /* @__PURE__ */ new Map());
|
|
207
|
+
}
|
|
208
|
+
addSourceMap(filepath, map) {
|
|
209
|
+
this.sourceMaps.set(filepath, map);
|
|
210
|
+
}
|
|
132
211
|
getVersion() {
|
|
133
212
|
return "1";
|
|
134
213
|
}
|
|
@@ -150,6 +229,22 @@ class VitestBrowserSnapshotEnvironment {
|
|
|
150
229
|
removeSnapshotFile(filepath) {
|
|
151
230
|
return rpc().removeSnapshotFile(filepath);
|
|
152
231
|
}
|
|
232
|
+
processStackTrace(stack) {
|
|
233
|
+
const map = this.sourceMaps.get(stack.file);
|
|
234
|
+
if (!map) {
|
|
235
|
+
return stack;
|
|
236
|
+
}
|
|
237
|
+
let traceMap = this.traceMaps.get(stack.file);
|
|
238
|
+
if (!traceMap) {
|
|
239
|
+
traceMap = new TraceMap(map);
|
|
240
|
+
this.traceMaps.set(stack.file, traceMap);
|
|
241
|
+
}
|
|
242
|
+
const { line, column } = originalPositionFor(traceMap, stack);
|
|
243
|
+
if (line != null && column != null) {
|
|
244
|
+
return { ...stack, line, column };
|
|
245
|
+
}
|
|
246
|
+
return stack;
|
|
247
|
+
}
|
|
153
248
|
}
|
|
154
249
|
function rpc() {
|
|
155
250
|
return globalThis.__vitest_worker__.rpc;
|
|
@@ -161,6 +256,7 @@ function createBrowserRunner(runnerClass, mocker, state, coverageModule) {
|
|
|
161
256
|
super(options.config);
|
|
162
257
|
__publicField(this, "config");
|
|
163
258
|
__publicField(this, "hashMap", browserHashMap);
|
|
259
|
+
__publicField(this, "sourceMapCache", /* @__PURE__ */ new Map());
|
|
164
260
|
__publicField(this, "onAfterRunTask", async (task) => {
|
|
165
261
|
var _a, _b, _c;
|
|
166
262
|
await ((_a = super.onAfterRunTask) == null ? void 0 : _a.call(this, task));
|
|
@@ -173,6 +269,22 @@ function createBrowserRunner(runnerClass, mocker, state, coverageModule) {
|
|
|
173
269
|
}
|
|
174
270
|
}
|
|
175
271
|
});
|
|
272
|
+
__publicField(this, "onBeforeRunSuite", async (suite) => {
|
|
273
|
+
var _a;
|
|
274
|
+
await Promise.all([
|
|
275
|
+
(_a = super.onBeforeRunSuite) == null ? void 0 : _a.call(this, suite),
|
|
276
|
+
(async () => {
|
|
277
|
+
if ("filepath" in suite) {
|
|
278
|
+
const map = await rpc$1().getBrowserFileSourceMap(suite.filepath);
|
|
279
|
+
this.sourceMapCache.set(suite.filepath, map);
|
|
280
|
+
const snapshotEnvironment = this.config.snapshotOptions.snapshotEnvironment;
|
|
281
|
+
if (snapshotEnvironment instanceof VitestBrowserSnapshotEnvironment) {
|
|
282
|
+
snapshotEnvironment.addSourceMap(suite.filepath, map);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
})()
|
|
286
|
+
]);
|
|
287
|
+
});
|
|
176
288
|
__publicField(this, "onAfterRunFiles", async (files) => {
|
|
177
289
|
var _a, _b;
|
|
178
290
|
const [coverage] = await Promise.all([
|
|
@@ -197,7 +309,7 @@ function createBrowserRunner(runnerClass, mocker, state, coverageModule) {
|
|
|
197
309
|
});
|
|
198
310
|
if (this.config.includeTaskLocation) {
|
|
199
311
|
try {
|
|
200
|
-
await updateFilesLocations(files);
|
|
312
|
+
await updateFilesLocations(files, this.sourceMapCache);
|
|
201
313
|
} catch (_) {
|
|
202
314
|
}
|
|
203
315
|
}
|
|
@@ -223,21 +335,16 @@ function createBrowserRunner(runnerClass, mocker, state, coverageModule) {
|
|
|
223
335
|
}
|
|
224
336
|
let cachedRunner = null;
|
|
225
337
|
async function initiateRunner(state, mocker, config) {
|
|
226
|
-
if (cachedRunner)
|
|
338
|
+
if (cachedRunner) {
|
|
227
339
|
return cachedRunner;
|
|
228
|
-
|
|
229
|
-
{ VitestTestRunner, NodeBenchmarkRunner },
|
|
230
|
-
{ takeCoverageInsideWorker, loadDiffConfig, loadSnapshotSerializers }
|
|
231
|
-
] = await Promise.all([
|
|
232
|
-
importId("vitest/runners"),
|
|
233
|
-
importId("vitest/browser")
|
|
234
|
-
]);
|
|
340
|
+
}
|
|
235
341
|
const runnerClass = config.mode === "test" ? VitestTestRunner : NodeBenchmarkRunner;
|
|
236
342
|
const BrowserRunner = createBrowserRunner(runnerClass, mocker, state, {
|
|
237
343
|
takeCoverage: () => takeCoverageInsideWorker(config.coverage, { executeId: importId })
|
|
238
344
|
});
|
|
239
|
-
if (!config.snapshotOptions.snapshotEnvironment)
|
|
345
|
+
if (!config.snapshotOptions.snapshotEnvironment) {
|
|
240
346
|
config.snapshotOptions.snapshotEnvironment = new VitestBrowserSnapshotEnvironment();
|
|
347
|
+
}
|
|
241
348
|
const runner = new BrowserRunner({
|
|
242
349
|
config
|
|
243
350
|
});
|
|
@@ -250,22 +357,23 @@ async function initiateRunner(state, mocker, config) {
|
|
|
250
357
|
cachedRunner = runner;
|
|
251
358
|
return runner;
|
|
252
359
|
}
|
|
253
|
-
async function updateFilesLocations(files) {
|
|
254
|
-
const { loadSourceMapUtils } = await importId("vitest/utils");
|
|
255
|
-
const { TraceMap, originalPositionFor } = await loadSourceMapUtils();
|
|
360
|
+
async function updateFilesLocations(files, sourceMaps) {
|
|
256
361
|
const promises = files.map(async (file) => {
|
|
257
|
-
const result = await rpc$1().getBrowserFileSourceMap(file.filepath);
|
|
258
|
-
if (!result)
|
|
362
|
+
const result = sourceMaps.get(file.filepath) || await rpc$1().getBrowserFileSourceMap(file.filepath);
|
|
363
|
+
if (!result) {
|
|
259
364
|
return null;
|
|
365
|
+
}
|
|
260
366
|
const traceMap = new TraceMap(result);
|
|
261
367
|
function updateLocation(task) {
|
|
262
368
|
if (task.location) {
|
|
263
369
|
const { line, column } = originalPositionFor(traceMap, task.location);
|
|
264
|
-
if (line != null && column != null)
|
|
370
|
+
if (line != null && column != null) {
|
|
265
371
|
task.location = { line, column: task.each ? column : column + 1 };
|
|
372
|
+
}
|
|
266
373
|
}
|
|
267
|
-
if ("tasks" in task)
|
|
374
|
+
if ("tasks" in task) {
|
|
268
375
|
task.tasks.forEach(updateLocation);
|
|
376
|
+
}
|
|
269
377
|
}
|
|
270
378
|
file.tasks.forEach(updateLocation);
|
|
271
379
|
return null;
|
|
@@ -283,32 +391,40 @@ class VitestBrowserClientMocker {
|
|
|
283
391
|
__publicField(this, "spyModule");
|
|
284
392
|
}
|
|
285
393
|
setupWorker() {
|
|
286
|
-
channel.addEventListener(
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
394
|
+
channel.addEventListener(
|
|
395
|
+
"message",
|
|
396
|
+
async (e) => {
|
|
397
|
+
if (e.data.type === "mock-factory:request") {
|
|
398
|
+
try {
|
|
399
|
+
const module = await this.resolve(e.data.id);
|
|
400
|
+
const exports = Object.keys(module);
|
|
401
|
+
channel.postMessage({
|
|
402
|
+
type: "mock-factory:response",
|
|
403
|
+
exports
|
|
404
|
+
});
|
|
405
|
+
} catch (err) {
|
|
406
|
+
const { processError: processError2 } = await importId(
|
|
407
|
+
"vitest/browser"
|
|
408
|
+
);
|
|
409
|
+
channel.postMessage({
|
|
410
|
+
type: "mock-factory:error",
|
|
411
|
+
error: processError2(err)
|
|
412
|
+
});
|
|
413
|
+
}
|
|
301
414
|
}
|
|
302
415
|
}
|
|
303
|
-
|
|
416
|
+
);
|
|
304
417
|
}
|
|
305
418
|
setSpyModule(mod) {
|
|
306
419
|
this.spyModule = mod;
|
|
307
420
|
}
|
|
308
421
|
async importActual(id, importer) {
|
|
309
422
|
const resolved = await rpc$1().resolveId(id, importer);
|
|
310
|
-
if (resolved == null)
|
|
311
|
-
throw new Error(
|
|
423
|
+
if (resolved == null) {
|
|
424
|
+
throw new Error(
|
|
425
|
+
`[vitest] Cannot resolve ${id} imported from ${importer}`
|
|
426
|
+
);
|
|
427
|
+
}
|
|
312
428
|
const ext = extname(resolved.id);
|
|
313
429
|
const url2 = new URL(`/@id/${resolved.id}`, location.href);
|
|
314
430
|
const query = `_vitest_original&ext.${ext}`;
|
|
@@ -317,12 +433,18 @@ class VitestBrowserClientMocker {
|
|
|
317
433
|
}
|
|
318
434
|
async importMock(rawId, importer) {
|
|
319
435
|
await this.prepare();
|
|
320
|
-
const { resolvedId, type, mockPath } = await rpc$1().resolveMock(
|
|
436
|
+
const { resolvedId, type, mockPath } = await rpc$1().resolveMock(
|
|
437
|
+
rawId,
|
|
438
|
+
importer,
|
|
439
|
+
false
|
|
440
|
+
);
|
|
321
441
|
const factoryReturn = this.get(resolvedId);
|
|
322
|
-
if (factoryReturn)
|
|
442
|
+
if (factoryReturn) {
|
|
323
443
|
return factoryReturn;
|
|
324
|
-
|
|
444
|
+
}
|
|
445
|
+
if (this.factories[resolvedId]) {
|
|
325
446
|
return await this.resolve(resolvedId);
|
|
447
|
+
}
|
|
326
448
|
if (type === "redirect") {
|
|
327
449
|
const url22 = new URL(`/@id/${mockPath}`, location.href);
|
|
328
450
|
return __vitePreload(() => import(url22.toString()), true ? __vite__mapDeps([]) : void 0);
|
|
@@ -340,8 +462,9 @@ class VitestBrowserClientMocker {
|
|
|
340
462
|
}
|
|
341
463
|
async invalidate() {
|
|
342
464
|
const ids = Array.from(this.ids);
|
|
343
|
-
if (!ids.length)
|
|
465
|
+
if (!ids.length) {
|
|
344
466
|
return;
|
|
467
|
+
}
|
|
345
468
|
await rpc$1().invalidate(ids);
|
|
346
469
|
channel.postMessage({ type: "mock:invalidate" });
|
|
347
470
|
this.ids.clear();
|
|
@@ -351,8 +474,9 @@ class VitestBrowserClientMocker {
|
|
|
351
474
|
}
|
|
352
475
|
async resolve(id) {
|
|
353
476
|
const factory = this.factories[id];
|
|
354
|
-
if (!factory)
|
|
477
|
+
if (!factory) {
|
|
355
478
|
throw new Error(`Cannot resolve ${id} mock: no factory provided`);
|
|
479
|
+
}
|
|
356
480
|
try {
|
|
357
481
|
this.mockObjects[id] = await factory();
|
|
358
482
|
return this.mockObjects[id];
|
|
@@ -386,8 +510,9 @@ class VitestBrowserClientMocker {
|
|
|
386
510
|
}
|
|
387
511
|
queueUnmock(id, importer) {
|
|
388
512
|
const promise = rpc$1().resolveId(id, importer).then(async (resolved) => {
|
|
389
|
-
if (!resolved)
|
|
513
|
+
if (!resolved) {
|
|
390
514
|
return;
|
|
515
|
+
}
|
|
391
516
|
this.ids.delete(resolved.id);
|
|
392
517
|
const urlPaths = resolveMockPaths(resolved.id);
|
|
393
518
|
urlPaths.forEach((url2) => {
|
|
@@ -406,11 +531,10 @@ class VitestBrowserClientMocker {
|
|
|
406
531
|
this.queue.add(promise);
|
|
407
532
|
}
|
|
408
533
|
async prepare() {
|
|
409
|
-
if (!this.queue.size)
|
|
534
|
+
if (!this.queue.size) {
|
|
410
535
|
return;
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
]);
|
|
536
|
+
}
|
|
537
|
+
await Promise.all([...this.queue.values()]);
|
|
414
538
|
}
|
|
415
539
|
// TODO: move this logic into a util(?)
|
|
416
540
|
mockObject(object, mockExports = {}) {
|
|
@@ -427,7 +551,10 @@ class VitestBrowserClientMocker {
|
|
|
427
551
|
const mockPropertiesOf = (container, newContainer) => {
|
|
428
552
|
const containerType = /* @__PURE__ */ getType(container);
|
|
429
553
|
const isModule = containerType === "Module" || !!container.__esModule;
|
|
430
|
-
for (const { key: property, descriptor } of getAllMockableProperties(
|
|
554
|
+
for (const { key: property, descriptor } of getAllMockableProperties(
|
|
555
|
+
container,
|
|
556
|
+
isModule
|
|
557
|
+
)) {
|
|
431
558
|
if (!isModule && descriptor.get) {
|
|
432
559
|
try {
|
|
433
560
|
Object.defineProperty(newContainer, property, descriptor);
|
|
@@ -435,12 +562,15 @@ class VitestBrowserClientMocker {
|
|
|
435
562
|
}
|
|
436
563
|
continue;
|
|
437
564
|
}
|
|
438
|
-
if (isSpecialProp(property, containerType))
|
|
565
|
+
if (isSpecialProp(property, containerType)) {
|
|
439
566
|
continue;
|
|
567
|
+
}
|
|
440
568
|
const value = container[property];
|
|
441
569
|
const refId = refs.getId(value);
|
|
442
570
|
if (refId !== void 0) {
|
|
443
|
-
finalizers.push(
|
|
571
|
+
finalizers.push(
|
|
572
|
+
() => define(newContainer, property, refs.getMockedValue(refId))
|
|
573
|
+
);
|
|
444
574
|
continue;
|
|
445
575
|
}
|
|
446
576
|
const type = /* @__PURE__ */ getType(value);
|
|
@@ -453,14 +583,19 @@ class VitestBrowserClientMocker {
|
|
|
453
583
|
define(newContainer, property, value);
|
|
454
584
|
continue;
|
|
455
585
|
}
|
|
456
|
-
if (!define(newContainer, property, isFunction ? value : {}))
|
|
586
|
+
if (!define(newContainer, property, isFunction ? value : {})) {
|
|
457
587
|
continue;
|
|
588
|
+
}
|
|
458
589
|
if (isFunction) {
|
|
459
590
|
let mockFunction = function() {
|
|
460
591
|
if (this instanceof newContainer[property]) {
|
|
461
|
-
for (const { key, descriptor: descriptor2 } of getAllMockableProperties(
|
|
462
|
-
|
|
592
|
+
for (const { key, descriptor: descriptor2 } of getAllMockableProperties(
|
|
593
|
+
this,
|
|
594
|
+
false
|
|
595
|
+
)) {
|
|
596
|
+
if (descriptor2.get) {
|
|
463
597
|
continue;
|
|
598
|
+
}
|
|
464
599
|
const value2 = this[key];
|
|
465
600
|
const type2 = /* @__PURE__ */ getType(value2);
|
|
466
601
|
const isFunction2 = type2.includes("Function") && typeof value2 === "function";
|
|
@@ -477,8 +612,11 @@ class VitestBrowserClientMocker {
|
|
|
477
612
|
}
|
|
478
613
|
};
|
|
479
614
|
const spyModule = this.spyModule;
|
|
480
|
-
if (!spyModule)
|
|
481
|
-
throw new Error(
|
|
615
|
+
if (!spyModule) {
|
|
616
|
+
throw new Error(
|
|
617
|
+
"[vitest] `spyModule` is not defined. This is Vitest error. Please open a new issue with reproduction."
|
|
618
|
+
);
|
|
619
|
+
}
|
|
482
620
|
const mock = spyModule.spyOn(newContainer, property).mockImplementation(mockFunction);
|
|
483
621
|
mock.mockRestore = () => {
|
|
484
622
|
mock.mockReset();
|
|
@@ -493,8 +631,9 @@ class VitestBrowserClientMocker {
|
|
|
493
631
|
};
|
|
494
632
|
const mockedObject = mockExports;
|
|
495
633
|
mockPropertiesOf(object, mockedObject);
|
|
496
|
-
for (const finalizer of finalizers)
|
|
634
|
+
for (const finalizer of finalizers) {
|
|
497
635
|
finalizer();
|
|
636
|
+
}
|
|
498
637
|
return mockedObject;
|
|
499
638
|
}
|
|
500
639
|
}
|
|
@@ -523,18 +662,21 @@ function getAllMockableProperties(obj, isModule) {
|
|
|
523
662
|
const allProps = /* @__PURE__ */ new Map();
|
|
524
663
|
let curr = obj;
|
|
525
664
|
do {
|
|
526
|
-
if (curr === Object.prototype || curr === Function.prototype || curr === RegExp.prototype)
|
|
665
|
+
if (curr === Object.prototype || curr === Function.prototype || curr === RegExp.prototype) {
|
|
527
666
|
break;
|
|
667
|
+
}
|
|
528
668
|
collectOwnProperties(curr, (key) => {
|
|
529
669
|
const descriptor = Object.getOwnPropertyDescriptor(curr, key);
|
|
530
|
-
if (descriptor)
|
|
670
|
+
if (descriptor) {
|
|
531
671
|
allProps.set(key, { key, descriptor });
|
|
672
|
+
}
|
|
532
673
|
});
|
|
533
674
|
} while (curr = Object.getPrototypeOf(curr));
|
|
534
675
|
if (isModule && !allProps.has("default") && "default" in obj) {
|
|
535
676
|
const descriptor = Object.getOwnPropertyDescriptor(obj, "default");
|
|
536
|
-
if (descriptor)
|
|
677
|
+
if (descriptor) {
|
|
537
678
|
allProps.set("default", { key: "default", descriptor });
|
|
679
|
+
}
|
|
538
680
|
}
|
|
539
681
|
return Array.from(allProps.values());
|
|
540
682
|
}
|
|
@@ -545,91 +687,30 @@ function collectOwnProperties(obj, collector) {
|
|
|
545
687
|
}
|
|
546
688
|
function resolvedMockedPath(path) {
|
|
547
689
|
const config = getBrowserState().viteConfig;
|
|
548
|
-
if (path.startsWith(config.root))
|
|
690
|
+
if (path.startsWith(config.root)) {
|
|
549
691
|
return path.slice(config.root.length);
|
|
692
|
+
}
|
|
550
693
|
return path;
|
|
551
694
|
}
|
|
552
695
|
function resolveMockPaths(path) {
|
|
553
696
|
const config = getBrowserState().viteConfig;
|
|
554
697
|
const fsRoot = join("/@fs/", config.root);
|
|
555
698
|
const paths = [path, join("/@fs/", path)];
|
|
556
|
-
if (path.startsWith(config.root))
|
|
699
|
+
if (path.startsWith(config.root)) {
|
|
557
700
|
paths.push(path.slice(config.root.length));
|
|
558
|
-
|
|
701
|
+
}
|
|
702
|
+
if (path.startsWith(fsRoot)) {
|
|
559
703
|
paths.push(path.slice(fsRoot.length));
|
|
560
|
-
return paths;
|
|
561
|
-
}
|
|
562
|
-
function on(event, listener) {
|
|
563
|
-
window.addEventListener(event, listener);
|
|
564
|
-
return () => window.removeEventListener(event, listener);
|
|
565
|
-
}
|
|
566
|
-
function serializeError(unhandledError) {
|
|
567
|
-
return {
|
|
568
|
-
...unhandledError,
|
|
569
|
-
name: unhandledError.name,
|
|
570
|
-
message: unhandledError.message,
|
|
571
|
-
stack: String(unhandledError.stack)
|
|
572
|
-
};
|
|
573
|
-
}
|
|
574
|
-
async function defaultErrorReport(type, unhandledError) {
|
|
575
|
-
const error = serializeError(unhandledError);
|
|
576
|
-
channel.postMessage({
|
|
577
|
-
type: "error",
|
|
578
|
-
files: getBrowserState().runningFiles,
|
|
579
|
-
error,
|
|
580
|
-
errorType: type,
|
|
581
|
-
id: getBrowserState().iframeId
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
function catchWindowErrors(cb) {
|
|
585
|
-
let userErrorListenerCount = 0;
|
|
586
|
-
function throwUnhandlerError(e) {
|
|
587
|
-
if (userErrorListenerCount === 0 && e.error != null)
|
|
588
|
-
cb(e);
|
|
589
|
-
else
|
|
590
|
-
console.error(e.error);
|
|
591
704
|
}
|
|
592
|
-
|
|
593
|
-
const removeEventListener = window.removeEventListener.bind(window);
|
|
594
|
-
window.addEventListener("error", throwUnhandlerError);
|
|
595
|
-
window.addEventListener = function(...args) {
|
|
596
|
-
if (args[0] === "error")
|
|
597
|
-
userErrorListenerCount++;
|
|
598
|
-
return addEventListener.apply(this, args);
|
|
599
|
-
};
|
|
600
|
-
window.removeEventListener = function(...args) {
|
|
601
|
-
if (args[0] === "error" && userErrorListenerCount)
|
|
602
|
-
userErrorListenerCount--;
|
|
603
|
-
return removeEventListener.apply(this, args);
|
|
604
|
-
};
|
|
605
|
-
return function clearErrorHandlers() {
|
|
606
|
-
window.removeEventListener("error", throwUnhandlerError);
|
|
607
|
-
};
|
|
608
|
-
}
|
|
609
|
-
function registerUnhandledErrors() {
|
|
610
|
-
const stopErrorHandler2 = catchWindowErrors((e) => defaultErrorReport("Error", e.error));
|
|
611
|
-
const stopRejectionHandler = on("unhandledrejection", (e) => defaultErrorReport("Unhandled Rejection", e.reason));
|
|
612
|
-
return () => {
|
|
613
|
-
stopErrorHandler2();
|
|
614
|
-
stopRejectionHandler();
|
|
615
|
-
};
|
|
616
|
-
}
|
|
617
|
-
function registerUnexpectedErrors(rpc2) {
|
|
618
|
-
catchWindowErrors((event) => reportUnexpectedError(rpc2, "Error", event.error));
|
|
619
|
-
on("unhandledrejection", (event) => reportUnexpectedError(rpc2, "Unhandled Rejection", event.reason));
|
|
620
|
-
}
|
|
621
|
-
async function reportUnexpectedError(rpc2, type, error) {
|
|
622
|
-
const { processError } = await importId("vitest/browser");
|
|
623
|
-
const processedError = processError(error);
|
|
624
|
-
await rpc2.onUnhandledError(processedError, type);
|
|
705
|
+
return paths;
|
|
625
706
|
}
|
|
626
|
-
const stopErrorHandler = registerUnhandledErrors();
|
|
627
707
|
const url = new URL(location.href);
|
|
628
708
|
const reloadStart = url.searchParams.get("__reloadStart");
|
|
629
709
|
function debug(...args) {
|
|
630
710
|
const debug2 = getConfig().env.VITEST_BROWSER_DEBUG;
|
|
631
|
-
if (debug2 && debug2 !== "false")
|
|
711
|
+
if (debug2 && debug2 !== "false") {
|
|
632
712
|
client.rpc.debug(...args.map(String));
|
|
713
|
+
}
|
|
633
714
|
}
|
|
634
715
|
async function tryCall(fn) {
|
|
635
716
|
try {
|
|
@@ -639,14 +720,27 @@ async function tryCall(fn) {
|
|
|
639
720
|
const canTry = !reloadStart || now2 - Number(reloadStart) < 3e4;
|
|
640
721
|
const errorStack = (() => {
|
|
641
722
|
var _a;
|
|
642
|
-
if (!err)
|
|
723
|
+
if (!err) {
|
|
643
724
|
return null;
|
|
725
|
+
}
|
|
644
726
|
return ((_a = err.stack) == null ? void 0 : _a.includes(err.message)) ? err.stack : `${err.message}
|
|
645
727
|
${err.stack}`;
|
|
646
728
|
})();
|
|
647
|
-
debug(
|
|
729
|
+
debug(
|
|
730
|
+
"failed to resolve runner",
|
|
731
|
+
"trying again:",
|
|
732
|
+
canTry,
|
|
733
|
+
"time is",
|
|
734
|
+
now2,
|
|
735
|
+
"reloadStart is",
|
|
736
|
+
reloadStart,
|
|
737
|
+
":\n",
|
|
738
|
+
errorStack
|
|
739
|
+
);
|
|
648
740
|
if (!canTry) {
|
|
649
|
-
const error = serializeError(
|
|
741
|
+
const error = serializeError(
|
|
742
|
+
new Error("Vitest failed to load its runner after 30 seconds.")
|
|
743
|
+
);
|
|
650
744
|
error.cause = serializeError(err);
|
|
651
745
|
await client.rpc.onUnhandledError(error, "Preload Error");
|
|
652
746
|
return false;
|
|
@@ -662,70 +756,32 @@ ${err.stack}`;
|
|
|
662
756
|
}
|
|
663
757
|
}
|
|
664
758
|
}
|
|
665
|
-
const startTime = performance.now();
|
|
666
759
|
async function prepareTestEnvironment(files) {
|
|
667
760
|
debug("trying to resolve runner", `${reloadStart}`);
|
|
668
761
|
const config = getConfig();
|
|
669
|
-
const
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
ctx: {
|
|
675
|
-
pool: "browser",
|
|
676
|
-
worker: "./browser.js",
|
|
677
|
-
workerId: 1,
|
|
678
|
-
config,
|
|
679
|
-
projectName: config.name || "",
|
|
680
|
-
files,
|
|
681
|
-
environment: {
|
|
682
|
-
name: "browser",
|
|
683
|
-
options: null
|
|
684
|
-
},
|
|
685
|
-
providedContext,
|
|
686
|
-
invalidates: []
|
|
687
|
-
},
|
|
688
|
-
onCancel,
|
|
689
|
-
mockMap: /* @__PURE__ */ new Map(),
|
|
690
|
-
config,
|
|
691
|
-
environment: {
|
|
692
|
-
name: "browser",
|
|
693
|
-
transformMode: "web",
|
|
694
|
-
setup() {
|
|
695
|
-
throw new Error("Not called in the browser");
|
|
696
|
-
}
|
|
697
|
-
},
|
|
698
|
-
moduleCache: getBrowserState().moduleCache,
|
|
699
|
-
rpc: rpc2,
|
|
700
|
-
durations: {
|
|
701
|
-
environment: 0,
|
|
702
|
-
prepare: startTime
|
|
703
|
-
},
|
|
704
|
-
providedContext
|
|
705
|
-
};
|
|
706
|
-
globalThis.__vitest_browser__ = true;
|
|
707
|
-
globalThis.__vitest_worker__ = state;
|
|
762
|
+
const rpc2 = createSafeRpc(client);
|
|
763
|
+
const state = getWorkerState();
|
|
764
|
+
state.ctx.files = files;
|
|
765
|
+
state.onCancel = onCancel;
|
|
766
|
+
state.rpc = rpc2;
|
|
708
767
|
const mocker = new VitestBrowserClientMocker();
|
|
709
768
|
globalThis.__vitest_mocker__ = mocker;
|
|
710
|
-
|
|
769
|
+
setupConsoleLogSpy();
|
|
711
770
|
setupDialogsSpy();
|
|
771
|
+
const runner = await initiateRunner(state, mocker, config);
|
|
712
772
|
const version = url.searchParams.get("browserv") || "";
|
|
713
773
|
files.forEach((filename) => {
|
|
714
774
|
const currentVersion = browserHashMap.get(filename);
|
|
715
|
-
if (!currentVersion || currentVersion[1] !== version)
|
|
775
|
+
if (!currentVersion || currentVersion[1] !== version) {
|
|
716
776
|
browserHashMap.set(filename, [true, version]);
|
|
777
|
+
}
|
|
717
778
|
});
|
|
718
|
-
const [runner, { startTests, setupCommonEnv, SpyModule }] = await Promise.all([
|
|
719
|
-
initiateRunner(state, mocker, config),
|
|
720
|
-
importId("vitest/browser")
|
|
721
|
-
]);
|
|
722
779
|
mocker.setSpyModule(SpyModule);
|
|
723
780
|
mocker.setupWorker();
|
|
724
781
|
onCancel.then((reason) => {
|
|
725
782
|
var _a;
|
|
726
783
|
(_a = runner.onCancel) == null ? void 0 : _a.call(runner, reason);
|
|
727
784
|
});
|
|
728
|
-
stopErrorHandler();
|
|
729
785
|
registerUnexpectedErrors(rpc2);
|
|
730
786
|
return {
|
|
731
787
|
runner,
|
|
@@ -764,13 +820,14 @@ async function runTests(files) {
|
|
|
764
820
|
return;
|
|
765
821
|
}
|
|
766
822
|
debug("runner resolved successfully");
|
|
767
|
-
const { config, runner, state, setupCommonEnv, startTests } = preparedData;
|
|
823
|
+
const { config, runner, state, setupCommonEnv: setupCommonEnv2, startTests: startTests2 } = preparedData;
|
|
768
824
|
state.durations.prepare = performance.now() - state.durations.prepare;
|
|
769
825
|
debug("prepare time", state.durations.prepare, "ms");
|
|
770
826
|
try {
|
|
771
|
-
await
|
|
772
|
-
for (const file of files)
|
|
773
|
-
await
|
|
827
|
+
await setupCommonEnv2(config);
|
|
828
|
+
for (const file of files) {
|
|
829
|
+
await startTests2([file], runner);
|
|
830
|
+
}
|
|
774
831
|
} finally {
|
|
775
832
|
state.environmentTeardownRun = true;
|
|
776
833
|
debug("finished running tests");
|