@vitest/browser 2.1.1 → 2.1.2
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.js +17 -1
- package/dist/client/.vite/manifest.json +2 -2
- package/dist/client/__vitest__/assets/{index-DsWp6aFQ.js → index-CADIw8eX.js} +5 -5
- package/dist/client/__vitest__/index.html +1 -1
- package/dist/client/__vitest_browser__/orchestrator-N9hisloQ.js +1096 -0
- package/dist/client/__vitest_browser__/{tester-Bm6k0JOu.js → tester-iPUw4msx.js} +3 -0
- package/dist/client/orchestrator.html +1 -1
- package/dist/client/tester/tester.html +1 -1
- package/dist/index.js +22 -3
- package/dist/locators/preview.js +1 -1
- package/package.json +9 -9
- package/dist/client/__vitest_browser__/orchestrator-qtq9EW1J.js +0 -541
|
@@ -782,6 +782,7 @@ function createBrowserRunner(runnerClass, mocker, state, coverageModule) {
|
|
|
782
782
|
if (coverage) {
|
|
783
783
|
await rpc$1().onAfterSuiteRun({
|
|
784
784
|
coverage,
|
|
785
|
+
testFiles: files.map((file) => file.name),
|
|
785
786
|
transformMode: "browser",
|
|
786
787
|
projectName: this.config.name
|
|
787
788
|
});
|
|
@@ -880,11 +881,13 @@ class VitestBrowserClientMocker extends ModuleMocker {
|
|
|
880
881
|
const exports = Object.keys(module);
|
|
881
882
|
channel.postMessage({
|
|
882
883
|
type: "mock-factory:response",
|
|
884
|
+
eventId: e.data.eventId,
|
|
883
885
|
exports
|
|
884
886
|
});
|
|
885
887
|
} catch (err) {
|
|
886
888
|
channel.postMessage({
|
|
887
889
|
type: "mock-factory:error",
|
|
890
|
+
eventId: e.data.eventId,
|
|
888
891
|
error: {
|
|
889
892
|
name: err.name,
|
|
890
893
|
message: err.message,
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
{__VITEST_INJECTOR__}
|
|
27
27
|
{__VITEST_ERROR_CATCHER__}
|
|
28
28
|
{__VITEST_SCRIPTS__}
|
|
29
|
-
<script type="module" crossorigin src="/__vitest_browser__/orchestrator-
|
|
29
|
+
<script type="module" crossorigin src="/__vitest_browser__/orchestrator-N9hisloQ.js"></script>
|
|
30
30
|
<link rel="modulepreload" crossorigin href="/__vitest_browser__/preload-helper-D-WYp1PK.js">
|
|
31
31
|
</head>
|
|
32
32
|
<body>
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
<script>{__VITEST_STATE__}</script>
|
|
21
21
|
{__VITEST_INTERNAL_SCRIPTS__}
|
|
22
22
|
{__VITEST_SCRIPTS__}
|
|
23
|
-
<script type="module" crossorigin src="/__vitest_browser__/tester-
|
|
23
|
+
<script type="module" crossorigin src="/__vitest_browser__/tester-iPUw4msx.js"></script>
|
|
24
24
|
<link rel="modulepreload" crossorigin href="/__vitest_browser__/preload-helper-D-WYp1PK.js">
|
|
25
25
|
</head>
|
|
26
26
|
<body>
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import { resolve as resolve$1, dirname as dirname$1, basename as basename$1, nor
|
|
|
16
16
|
import crypto from 'node:crypto';
|
|
17
17
|
import * as nodeos from 'node:os';
|
|
18
18
|
|
|
19
|
-
var version = "2.1.
|
|
19
|
+
var version = "2.1.2";
|
|
20
20
|
|
|
21
21
|
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
22
22
|
function normalizeWindowsPath(input = "") {
|
|
@@ -1949,7 +1949,7 @@ async function resolveTester(server, url, res) {
|
|
|
1949
1949
|
const testerScripts = await server.formatScripts(
|
|
1950
1950
|
project.config.browser.testerScripts
|
|
1951
1951
|
);
|
|
1952
|
-
const clientScript = `<script type="module" src="${server.
|
|
1952
|
+
const clientScript = `<script type="module" src="${server.base}@vite/client"><\/script>`;
|
|
1953
1953
|
const stateJs = typeof server.stateJs === "string" ? server.stateJs : await server.stateJs;
|
|
1954
1954
|
const stateScript = `<script type="module">${stateJs}<\/script>`;
|
|
1955
1955
|
server.testerScripts = `${stateScript}${clientScript}${testerScripts}`;
|
|
@@ -2210,8 +2210,14 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2210
2210
|
},
|
|
2211
2211
|
{
|
|
2212
2212
|
name: "vitest:browser:assets",
|
|
2213
|
+
configureServer(server) {
|
|
2214
|
+
server.middlewares.use(
|
|
2215
|
+
"/__vitest__",
|
|
2216
|
+
sirv(resolve(distRoot, "client/__vitest__"))
|
|
2217
|
+
);
|
|
2218
|
+
},
|
|
2213
2219
|
resolveId(id) {
|
|
2214
|
-
if (id.startsWith("/__vitest_browser__/")
|
|
2220
|
+
if (id.startsWith("/__vitest_browser__/")) {
|
|
2215
2221
|
return resolve(distRoot, "client", id.slice(1));
|
|
2216
2222
|
}
|
|
2217
2223
|
},
|
|
@@ -2278,6 +2284,19 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2278
2284
|
};
|
|
2279
2285
|
}
|
|
2280
2286
|
},
|
|
2287
|
+
{
|
|
2288
|
+
name: "vitest:browser:worker",
|
|
2289
|
+
transform(code, id, _options) {
|
|
2290
|
+
if (/(?:\?|&)worker_file&type=\w+(?:&|$)/.test(id)) {
|
|
2291
|
+
const s = new MagicString(code);
|
|
2292
|
+
s.prepend("globalThis.__vitest_browser_runner__ = { wrapDynamicImport: f => f() };\n");
|
|
2293
|
+
return {
|
|
2294
|
+
code: s.toString(),
|
|
2295
|
+
map: s.generateMap({ hires: "boundary" })
|
|
2296
|
+
};
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
},
|
|
2281
2300
|
// TODO: remove this when @testing-library/vue supports ESM
|
|
2282
2301
|
{
|
|
2283
2302
|
name: "vitest:browser:support-testing-library",
|
package/dist/locators/preview.js
CHANGED
|
@@ -71,7 +71,7 @@ class PreviewLocator extends Locator {
|
|
|
71
71
|
return file2;
|
|
72
72
|
}
|
|
73
73
|
const { content: base64, basename, mime } = await this.triggerCommand("__vitest_fileInfo", file2, "base64");
|
|
74
|
-
const fileInstance = fetch(base64).then((r) => r.blob()).then((blob) => new File([blob], basename, { type: mime }));
|
|
74
|
+
const fileInstance = fetch(`data:${mime};base64,${base64}`).then((r) => r.blob()).then((blob) => new File([blob], basename, { type: mime }));
|
|
75
75
|
return fileInstance;
|
|
76
76
|
});
|
|
77
77
|
const uploadFiles = await Promise.all(uploadPromise);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitest/browser",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.1.
|
|
4
|
+
"version": "2.1.2",
|
|
5
5
|
"description": "Browser running for Vitest",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": "https://opencollective.com/vitest",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"peerDependencies": {
|
|
63
63
|
"playwright": "*",
|
|
64
64
|
"webdriverio": "*",
|
|
65
|
-
"vitest": "2.1.
|
|
65
|
+
"vitest": "2.1.2"
|
|
66
66
|
},
|
|
67
67
|
"peerDependenciesMeta": {
|
|
68
68
|
"playwright": {
|
|
@@ -83,8 +83,8 @@
|
|
|
83
83
|
"sirv": "^2.0.4",
|
|
84
84
|
"tinyrainbow": "^1.2.0",
|
|
85
85
|
"ws": "^8.18.0",
|
|
86
|
-
"@vitest/
|
|
87
|
-
"@vitest/
|
|
86
|
+
"@vitest/mocker": "2.1.2",
|
|
87
|
+
"@vitest/utils": "2.1.2"
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
90
|
"@testing-library/jest-dom": "^6.4.8",
|
|
@@ -100,17 +100,17 @@
|
|
|
100
100
|
"playwright-core": "^1.46.0",
|
|
101
101
|
"safaridriver": "^0.1.2",
|
|
102
102
|
"webdriverio": "^8.40.2",
|
|
103
|
-
"@vitest/runner": "2.1.
|
|
104
|
-
"@vitest/
|
|
105
|
-
"@vitest/
|
|
106
|
-
"vitest": "2.1.
|
|
103
|
+
"@vitest/runner": "2.1.2",
|
|
104
|
+
"@vitest/ui": "2.1.2",
|
|
105
|
+
"@vitest/ws-client": "2.1.2",
|
|
106
|
+
"vitest": "2.1.2"
|
|
107
107
|
},
|
|
108
108
|
"scripts": {
|
|
109
109
|
"build": "rimraf dist && pnpm build:node && pnpm build:client",
|
|
110
110
|
"build:client": "vite build src/client",
|
|
111
111
|
"build:node": "rollup -c",
|
|
112
112
|
"dev:client": "vite build src/client --watch",
|
|
113
|
-
"dev:node": "rollup -c --watch --watch.include 'src
|
|
113
|
+
"dev:node": "rollup -c --watch --watch.include 'src/**'",
|
|
114
114
|
"dev": "rimraf dist && pnpm run --stream '/^dev:/'"
|
|
115
115
|
}
|
|
116
116
|
}
|
|
@@ -1,541 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import { M as MockerRegistry, _ as __vitePreload, a as ManualMockedModule, g as getBrowserState, b as getConfig } from "./preload-helper-D-WYp1PK.js";
|
|
5
|
-
import { channel, client, globalChannel } from "@vitest/browser/client";
|
|
6
|
-
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
7
|
-
function normalizeWindowsPath(input = "") {
|
|
8
|
-
if (!input) {
|
|
9
|
-
return input;
|
|
10
|
-
}
|
|
11
|
-
return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
|
12
|
-
}
|
|
13
|
-
const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
14
|
-
const _ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/;
|
|
15
|
-
function cwd() {
|
|
16
|
-
if (typeof process !== "undefined" && typeof process.cwd === "function") {
|
|
17
|
-
return process.cwd().replace(/\\/g, "/");
|
|
18
|
-
}
|
|
19
|
-
return "/";
|
|
20
|
-
}
|
|
21
|
-
const resolve = function(...arguments_) {
|
|
22
|
-
arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
|
|
23
|
-
let resolvedPath = "";
|
|
24
|
-
let resolvedAbsolute = false;
|
|
25
|
-
for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
|
|
26
|
-
const path = index >= 0 ? arguments_[index] : cwd();
|
|
27
|
-
if (!path || path.length === 0) {
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
resolvedPath = `${path}/${resolvedPath}`;
|
|
31
|
-
resolvedAbsolute = isAbsolute(path);
|
|
32
|
-
}
|
|
33
|
-
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
|
34
|
-
if (resolvedAbsolute && !isAbsolute(resolvedPath)) {
|
|
35
|
-
return `/${resolvedPath}`;
|
|
36
|
-
}
|
|
37
|
-
return resolvedPath.length > 0 ? resolvedPath : ".";
|
|
38
|
-
};
|
|
39
|
-
function normalizeString(path, allowAboveRoot) {
|
|
40
|
-
let res = "";
|
|
41
|
-
let lastSegmentLength = 0;
|
|
42
|
-
let lastSlash = -1;
|
|
43
|
-
let dots = 0;
|
|
44
|
-
let char = null;
|
|
45
|
-
for (let index = 0; index <= path.length; ++index) {
|
|
46
|
-
if (index < path.length) {
|
|
47
|
-
char = path[index];
|
|
48
|
-
} else if (char === "/") {
|
|
49
|
-
break;
|
|
50
|
-
} else {
|
|
51
|
-
char = "/";
|
|
52
|
-
}
|
|
53
|
-
if (char === "/") {
|
|
54
|
-
if (lastSlash === index - 1 || dots === 1) ;
|
|
55
|
-
else if (dots === 2) {
|
|
56
|
-
if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
|
|
57
|
-
if (res.length > 2) {
|
|
58
|
-
const lastSlashIndex = res.lastIndexOf("/");
|
|
59
|
-
if (lastSlashIndex === -1) {
|
|
60
|
-
res = "";
|
|
61
|
-
lastSegmentLength = 0;
|
|
62
|
-
} else {
|
|
63
|
-
res = res.slice(0, lastSlashIndex);
|
|
64
|
-
lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
|
|
65
|
-
}
|
|
66
|
-
lastSlash = index;
|
|
67
|
-
dots = 0;
|
|
68
|
-
continue;
|
|
69
|
-
} else if (res.length > 0) {
|
|
70
|
-
res = "";
|
|
71
|
-
lastSegmentLength = 0;
|
|
72
|
-
lastSlash = index;
|
|
73
|
-
dots = 0;
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if (allowAboveRoot) {
|
|
78
|
-
res += res.length > 0 ? "/.." : "..";
|
|
79
|
-
lastSegmentLength = 2;
|
|
80
|
-
}
|
|
81
|
-
} else {
|
|
82
|
-
if (res.length > 0) {
|
|
83
|
-
res += `/${path.slice(lastSlash + 1, index)}`;
|
|
84
|
-
} else {
|
|
85
|
-
res = path.slice(lastSlash + 1, index);
|
|
86
|
-
}
|
|
87
|
-
lastSegmentLength = index - lastSlash - 1;
|
|
88
|
-
}
|
|
89
|
-
lastSlash = index;
|
|
90
|
-
dots = 0;
|
|
91
|
-
} else if (char === "." && dots !== -1) {
|
|
92
|
-
++dots;
|
|
93
|
-
} else {
|
|
94
|
-
dots = -1;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return res;
|
|
98
|
-
}
|
|
99
|
-
const isAbsolute = function(p) {
|
|
100
|
-
return _IS_ABSOLUTE_RE.test(p);
|
|
101
|
-
};
|
|
102
|
-
const relative = function(from, to) {
|
|
103
|
-
const _from = resolve(from).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
104
|
-
const _to = resolve(to).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
105
|
-
if (_to[0][1] === ":" && _from[0][1] === ":" && _from[0] !== _to[0]) {
|
|
106
|
-
return _to.join("/");
|
|
107
|
-
}
|
|
108
|
-
const _fromCopy = [..._from];
|
|
109
|
-
for (const segment of _fromCopy) {
|
|
110
|
-
if (_to[0] !== segment) {
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
113
|
-
_from.shift();
|
|
114
|
-
_to.shift();
|
|
115
|
-
}
|
|
116
|
-
return [..._from.map(() => ".."), ..._to].join("/");
|
|
117
|
-
};
|
|
118
|
-
function generateHash(str) {
|
|
119
|
-
let hash = 0;
|
|
120
|
-
if (str.length === 0) {
|
|
121
|
-
return `${hash}`;
|
|
122
|
-
}
|
|
123
|
-
for (let i = 0; i < str.length; i++) {
|
|
124
|
-
const char = str.charCodeAt(i);
|
|
125
|
-
hash = (hash << 5) - hash + char;
|
|
126
|
-
hash = hash & hash;
|
|
127
|
-
}
|
|
128
|
-
return `${hash}`;
|
|
129
|
-
}
|
|
130
|
-
function getUiAPI() {
|
|
131
|
-
return window.__vitest_ui_api__;
|
|
132
|
-
}
|
|
133
|
-
const postfixRE = /[?#].*$/;
|
|
134
|
-
function cleanUrl(url2) {
|
|
135
|
-
return url2.replace(postfixRE, "");
|
|
136
|
-
}
|
|
137
|
-
class ModuleMockerMSWInterceptor {
|
|
138
|
-
constructor(options = {}) {
|
|
139
|
-
__publicField(this, "mocks", new MockerRegistry());
|
|
140
|
-
__publicField(this, "started", false);
|
|
141
|
-
__publicField(this, "startPromise");
|
|
142
|
-
this.options = options;
|
|
143
|
-
if (!options.globalThisAccessor) {
|
|
144
|
-
options.globalThisAccessor = '"__vitest_mocker__"';
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
async register(module) {
|
|
148
|
-
await this.init();
|
|
149
|
-
this.mocks.add(module);
|
|
150
|
-
}
|
|
151
|
-
async delete(url2) {
|
|
152
|
-
await this.init();
|
|
153
|
-
this.mocks.delete(url2);
|
|
154
|
-
}
|
|
155
|
-
invalidate() {
|
|
156
|
-
this.mocks.clear();
|
|
157
|
-
}
|
|
158
|
-
async resolveManualMock(mock) {
|
|
159
|
-
const exports = Object.keys(await mock.resolve());
|
|
160
|
-
const module = `const module = globalThis[${this.options.globalThisAccessor}].getFactoryModule("${mock.url}");`;
|
|
161
|
-
const keys = exports.map((name) => {
|
|
162
|
-
if (name === "default") {
|
|
163
|
-
return `export default module["default"];`;
|
|
164
|
-
}
|
|
165
|
-
return `export const ${name} = module["${name}"];`;
|
|
166
|
-
}).join("\n");
|
|
167
|
-
const text = `${module}
|
|
168
|
-
${keys}`;
|
|
169
|
-
return new Response(text, {
|
|
170
|
-
headers: {
|
|
171
|
-
"Content-Type": "application/javascript"
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
async init() {
|
|
176
|
-
if (this.started) {
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
if (this.startPromise) {
|
|
180
|
-
return this.startPromise;
|
|
181
|
-
}
|
|
182
|
-
const worker = this.options.mswWorker;
|
|
183
|
-
this.startPromise = Promise.all([
|
|
184
|
-
worker ? {
|
|
185
|
-
setupWorker(handler) {
|
|
186
|
-
worker.use(handler);
|
|
187
|
-
return worker;
|
|
188
|
-
}
|
|
189
|
-
} : __vitePreload(() => import("msw/browser"), true ? [] : void 0),
|
|
190
|
-
__vitePreload(() => import("msw/core/http"), true ? [] : void 0)
|
|
191
|
-
]).then(([{ setupWorker }, { http }]) => {
|
|
192
|
-
const worker2 = setupWorker(
|
|
193
|
-
http.get(/.+/, async ({ request }) => {
|
|
194
|
-
const path = cleanQuery(request.url.slice(location.origin.length));
|
|
195
|
-
if (!this.mocks.has(path)) {
|
|
196
|
-
if (path.includes("/deps/")) {
|
|
197
|
-
return fetch(bypass(request));
|
|
198
|
-
}
|
|
199
|
-
return passthrough();
|
|
200
|
-
}
|
|
201
|
-
const mock = this.mocks.get(path);
|
|
202
|
-
switch (mock.type) {
|
|
203
|
-
case "manual":
|
|
204
|
-
return this.resolveManualMock(mock);
|
|
205
|
-
case "automock":
|
|
206
|
-
case "autospy":
|
|
207
|
-
return Response.redirect(injectQuery(path, `mock=${mock.type}`));
|
|
208
|
-
case "redirect":
|
|
209
|
-
return Response.redirect(mock.redirect);
|
|
210
|
-
default:
|
|
211
|
-
throw new Error(`Unknown mock type: ${mock.type}`);
|
|
212
|
-
}
|
|
213
|
-
})
|
|
214
|
-
);
|
|
215
|
-
return worker2.start(this.options.mswOptions);
|
|
216
|
-
}).finally(() => {
|
|
217
|
-
this.started = true;
|
|
218
|
-
this.startPromise = void 0;
|
|
219
|
-
});
|
|
220
|
-
await this.startPromise;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
const timestampRegexp = /(\?|&)t=\d{13}/;
|
|
224
|
-
const versionRegexp = /(\?|&)v=\w{8}/;
|
|
225
|
-
function cleanQuery(url2) {
|
|
226
|
-
return url2.replace(timestampRegexp, "").replace(versionRegexp, "");
|
|
227
|
-
}
|
|
228
|
-
function passthrough() {
|
|
229
|
-
return new Response(null, {
|
|
230
|
-
status: 302,
|
|
231
|
-
statusText: "Passthrough",
|
|
232
|
-
headers: {
|
|
233
|
-
"x-msw-intention": "passthrough"
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
function bypass(request) {
|
|
238
|
-
const clonedRequest = request.clone();
|
|
239
|
-
clonedRequest.headers.set("x-msw-intention", "bypass");
|
|
240
|
-
const cacheControl = clonedRequest.headers.get("cache-control");
|
|
241
|
-
if (cacheControl) {
|
|
242
|
-
clonedRequest.headers.set(
|
|
243
|
-
"cache-control",
|
|
244
|
-
// allow reinvalidation of the cache so mocks can be updated
|
|
245
|
-
cacheControl.replace(", immutable", "")
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
return clonedRequest;
|
|
249
|
-
}
|
|
250
|
-
const replacePercentageRE = /%/g;
|
|
251
|
-
function injectQuery(url2, queryToInject) {
|
|
252
|
-
const resolvedUrl = new URL(
|
|
253
|
-
url2.replace(replacePercentageRE, "%25"),
|
|
254
|
-
location.href
|
|
255
|
-
);
|
|
256
|
-
const { search, hash } = resolvedUrl;
|
|
257
|
-
const pathname = cleanUrl(url2);
|
|
258
|
-
return `${pathname}?${queryToInject}${search ? `&${search.slice(1)}` : ""}${hash ?? ""}`;
|
|
259
|
-
}
|
|
260
|
-
class VitestBrowserModuleMockerInterceptor extends ModuleMockerMSWInterceptor {
|
|
261
|
-
async register(event) {
|
|
262
|
-
if (event.type === "manual") {
|
|
263
|
-
const module = ManualMockedModule.fromJSON(event, async () => {
|
|
264
|
-
const keys = await getFactoryExports(event.url);
|
|
265
|
-
return Object.fromEntries(keys.map((key) => [key, null]));
|
|
266
|
-
});
|
|
267
|
-
await super.register(module);
|
|
268
|
-
} else {
|
|
269
|
-
await this.init();
|
|
270
|
-
this.mocks.register(event);
|
|
271
|
-
}
|
|
272
|
-
channel.postMessage({ type: "mock:done" });
|
|
273
|
-
}
|
|
274
|
-
async delete(url2) {
|
|
275
|
-
await super.delete(url2);
|
|
276
|
-
channel.postMessage({ type: "unmock:done" });
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
function createModuleMockerInterceptor() {
|
|
280
|
-
return new VitestBrowserModuleMockerInterceptor({
|
|
281
|
-
globalThisAccessor: '"__vitest_mocker__"',
|
|
282
|
-
mswOptions: {
|
|
283
|
-
serviceWorker: {
|
|
284
|
-
url: "/__vitest_msw__"
|
|
285
|
-
},
|
|
286
|
-
quiet: true
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
function getFactoryExports(id) {
|
|
291
|
-
channel.postMessage({
|
|
292
|
-
type: "mock-factory:request",
|
|
293
|
-
id
|
|
294
|
-
});
|
|
295
|
-
return new Promise((resolve2, reject) => {
|
|
296
|
-
channel.addEventListener(
|
|
297
|
-
"message",
|
|
298
|
-
function onMessage(e) {
|
|
299
|
-
if (e.data.type === "mock-factory:response") {
|
|
300
|
-
resolve2(e.data.exports);
|
|
301
|
-
channel.removeEventListener("message", onMessage);
|
|
302
|
-
}
|
|
303
|
-
if (e.data.type === "mock-factory:error") {
|
|
304
|
-
reject(e.data.error);
|
|
305
|
-
channel.removeEventListener("message", onMessage);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
);
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
const url = new URL(location.href);
|
|
312
|
-
const ID_ALL = "__vitest_all__";
|
|
313
|
-
class IframeOrchestrator {
|
|
314
|
-
constructor() {
|
|
315
|
-
__publicField(this, "cancelled", false);
|
|
316
|
-
__publicField(this, "runningFiles", /* @__PURE__ */ new Set());
|
|
317
|
-
__publicField(this, "interceptor", createModuleMockerInterceptor());
|
|
318
|
-
__publicField(this, "iframes", /* @__PURE__ */ new Map());
|
|
319
|
-
}
|
|
320
|
-
async init() {
|
|
321
|
-
const testFiles = getBrowserState().files;
|
|
322
|
-
debug("test files", testFiles.join(", "));
|
|
323
|
-
this.runningFiles.clear();
|
|
324
|
-
testFiles.forEach((file) => this.runningFiles.add(file));
|
|
325
|
-
channel.addEventListener(
|
|
326
|
-
"message",
|
|
327
|
-
(e) => this.onIframeEvent(e)
|
|
328
|
-
);
|
|
329
|
-
globalChannel.addEventListener(
|
|
330
|
-
"message",
|
|
331
|
-
(e) => this.onGlobalChannelEvent(e)
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
async createTesters(testFiles) {
|
|
335
|
-
this.cancelled = false;
|
|
336
|
-
this.runningFiles.clear();
|
|
337
|
-
testFiles.forEach((file) => this.runningFiles.add(file));
|
|
338
|
-
const config = getConfig();
|
|
339
|
-
const container = await getContainer(config);
|
|
340
|
-
if (config.browser.ui) {
|
|
341
|
-
container.className = "absolute origin-top mt-[8px]";
|
|
342
|
-
container.parentElement.setAttribute("data-ready", "true");
|
|
343
|
-
container.textContent = "";
|
|
344
|
-
}
|
|
345
|
-
const { width, height } = config.browser.viewport;
|
|
346
|
-
this.iframes.forEach((iframe) => iframe.remove());
|
|
347
|
-
this.iframes.clear();
|
|
348
|
-
if (config.isolate === false) {
|
|
349
|
-
const iframe = this.createIframe(container, ID_ALL);
|
|
350
|
-
await setIframeViewport(iframe, width, height);
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
for (const file of testFiles) {
|
|
354
|
-
if (this.cancelled) {
|
|
355
|
-
done();
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
const iframe = this.createIframe(container, file);
|
|
359
|
-
await setIframeViewport(iframe, width, height);
|
|
360
|
-
await new Promise((resolve2) => {
|
|
361
|
-
channel.addEventListener(
|
|
362
|
-
"message",
|
|
363
|
-
function handler(e) {
|
|
364
|
-
if (e.data.type === "done" || e.data.type === "error") {
|
|
365
|
-
channel.removeEventListener("message", handler);
|
|
366
|
-
resolve2();
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
);
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
createIframe(container, file) {
|
|
374
|
-
if (this.iframes.has(file)) {
|
|
375
|
-
this.iframes.get(file).remove();
|
|
376
|
-
this.iframes.delete(file);
|
|
377
|
-
}
|
|
378
|
-
const iframe = document.createElement("iframe");
|
|
379
|
-
iframe.setAttribute("loading", "eager");
|
|
380
|
-
iframe.setAttribute(
|
|
381
|
-
"src",
|
|
382
|
-
`${url.pathname}__vitest_test__/__test__/${getBrowserState().contextId}/${encodeURIComponent(file)}`
|
|
383
|
-
);
|
|
384
|
-
iframe.setAttribute("data-vitest", "true");
|
|
385
|
-
iframe.style.border = "none";
|
|
386
|
-
iframe.style.width = "100%";
|
|
387
|
-
iframe.style.height = "100%";
|
|
388
|
-
iframe.setAttribute("allowfullscreen", "true");
|
|
389
|
-
iframe.setAttribute("allow", "clipboard-write;");
|
|
390
|
-
iframe.setAttribute("name", "vitest-iframe");
|
|
391
|
-
this.iframes.set(file, iframe);
|
|
392
|
-
container.appendChild(iframe);
|
|
393
|
-
return iframe;
|
|
394
|
-
}
|
|
395
|
-
async onGlobalChannelEvent(e) {
|
|
396
|
-
debug("global channel event", JSON.stringify(e.data));
|
|
397
|
-
switch (e.data.type) {
|
|
398
|
-
case "cancel": {
|
|
399
|
-
this.cancelled = true;
|
|
400
|
-
break;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
async onIframeEvent(e) {
|
|
405
|
-
var _a;
|
|
406
|
-
debug("iframe event", JSON.stringify(e.data));
|
|
407
|
-
switch (e.data.type) {
|
|
408
|
-
case "viewport": {
|
|
409
|
-
const { width, height, id } = e.data;
|
|
410
|
-
const iframe = this.iframes.get(id);
|
|
411
|
-
if (!iframe) {
|
|
412
|
-
const error = new Error(`Cannot find iframe with id ${id}`);
|
|
413
|
-
channel.postMessage({
|
|
414
|
-
type: "viewport:fail",
|
|
415
|
-
id,
|
|
416
|
-
error: error.message
|
|
417
|
-
});
|
|
418
|
-
await client.rpc.onUnhandledError(
|
|
419
|
-
{
|
|
420
|
-
name: "Teardown Error",
|
|
421
|
-
message: error.message
|
|
422
|
-
},
|
|
423
|
-
"Teardown Error"
|
|
424
|
-
);
|
|
425
|
-
return;
|
|
426
|
-
}
|
|
427
|
-
await setIframeViewport(iframe, width, height);
|
|
428
|
-
channel.postMessage({ type: "viewport:done", id });
|
|
429
|
-
break;
|
|
430
|
-
}
|
|
431
|
-
case "done": {
|
|
432
|
-
const filenames = e.data.filenames;
|
|
433
|
-
filenames.forEach((filename) => this.runningFiles.delete(filename));
|
|
434
|
-
if (!this.runningFiles.size) {
|
|
435
|
-
const ui = getUiAPI();
|
|
436
|
-
if (ui && filenames.length > 1) {
|
|
437
|
-
const id = generateFileId(filenames[filenames.length - 1]);
|
|
438
|
-
ui.setCurrentFileId(id);
|
|
439
|
-
}
|
|
440
|
-
await done();
|
|
441
|
-
} else {
|
|
442
|
-
const iframeId = e.data.id;
|
|
443
|
-
(_a = this.iframes.get(iframeId)) == null ? void 0 : _a.remove();
|
|
444
|
-
this.iframes.delete(iframeId);
|
|
445
|
-
}
|
|
446
|
-
break;
|
|
447
|
-
}
|
|
448
|
-
case "error": {
|
|
449
|
-
const iframeId = e.data.id;
|
|
450
|
-
this.iframes.delete(iframeId);
|
|
451
|
-
await client.rpc.onUnhandledError(e.data.error, e.data.errorType);
|
|
452
|
-
if (iframeId === ID_ALL) {
|
|
453
|
-
this.runningFiles.clear();
|
|
454
|
-
} else {
|
|
455
|
-
this.runningFiles.delete(iframeId);
|
|
456
|
-
}
|
|
457
|
-
if (!this.runningFiles.size) {
|
|
458
|
-
await done();
|
|
459
|
-
}
|
|
460
|
-
break;
|
|
461
|
-
}
|
|
462
|
-
case "mock:invalidate":
|
|
463
|
-
this.interceptor.invalidate();
|
|
464
|
-
break;
|
|
465
|
-
case "unmock":
|
|
466
|
-
await this.interceptor.delete(e.data.url);
|
|
467
|
-
break;
|
|
468
|
-
case "mock":
|
|
469
|
-
await this.interceptor.register(e.data.module);
|
|
470
|
-
break;
|
|
471
|
-
case "mock-factory:error":
|
|
472
|
-
case "mock-factory:response":
|
|
473
|
-
break;
|
|
474
|
-
default: {
|
|
475
|
-
e.data;
|
|
476
|
-
await client.rpc.onUnhandledError(
|
|
477
|
-
{
|
|
478
|
-
name: "Unexpected Event",
|
|
479
|
-
message: `Unexpected event: ${e.data.type}`
|
|
480
|
-
},
|
|
481
|
-
"Unexpected Event"
|
|
482
|
-
);
|
|
483
|
-
await done();
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
const orchestrator = new IframeOrchestrator();
|
|
489
|
-
let promiseTesters;
|
|
490
|
-
getBrowserState().createTesters = async (files) => {
|
|
491
|
-
await promiseTesters;
|
|
492
|
-
promiseTesters = orchestrator.createTesters(files).finally(() => {
|
|
493
|
-
promiseTesters = void 0;
|
|
494
|
-
});
|
|
495
|
-
await promiseTesters;
|
|
496
|
-
};
|
|
497
|
-
async function done() {
|
|
498
|
-
await client.rpc.finishBrowserTests(getBrowserState().contextId);
|
|
499
|
-
}
|
|
500
|
-
async function getContainer(config) {
|
|
501
|
-
if (config.browser.ui) {
|
|
502
|
-
const element = document.querySelector("#tester-ui");
|
|
503
|
-
if (!element) {
|
|
504
|
-
return new Promise((resolve2) => {
|
|
505
|
-
setTimeout(() => {
|
|
506
|
-
resolve2(getContainer(config));
|
|
507
|
-
}, 30);
|
|
508
|
-
});
|
|
509
|
-
}
|
|
510
|
-
return element;
|
|
511
|
-
}
|
|
512
|
-
return document.querySelector("#vitest-tester");
|
|
513
|
-
}
|
|
514
|
-
client.waitForConnection().then(async () => {
|
|
515
|
-
const testFiles = getBrowserState().files;
|
|
516
|
-
await orchestrator.init();
|
|
517
|
-
if (testFiles.length) {
|
|
518
|
-
await orchestrator.createTesters(testFiles);
|
|
519
|
-
}
|
|
520
|
-
});
|
|
521
|
-
function generateFileId(file) {
|
|
522
|
-
const config = getConfig();
|
|
523
|
-
const project = config.name || "";
|
|
524
|
-
const path = relative(config.root, file);
|
|
525
|
-
return generateHash(`${path}${project}`);
|
|
526
|
-
}
|
|
527
|
-
async function setIframeViewport(iframe, width, height) {
|
|
528
|
-
const ui = getUiAPI();
|
|
529
|
-
if (ui) {
|
|
530
|
-
await ui.setIframeViewport(width, height);
|
|
531
|
-
} else {
|
|
532
|
-
iframe.style.width = `${width}px`;
|
|
533
|
-
iframe.style.height = `${height}px`;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
function debug(...args) {
|
|
537
|
-
const debug2 = getConfig().env.VITEST_BROWSER_DEBUG;
|
|
538
|
-
if (debug2 && debug2 !== "false") {
|
|
539
|
-
client.rpc.debug(...args.map(String));
|
|
540
|
-
}
|
|
541
|
-
}
|