@vitest/browser 2.0.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/.vite/manifest.json +7 -7
- package/dist/client/__vitest__/assets/{index-DEM1IsBG.css → index-Ct7j6Tgf.css} +1 -1
- package/dist/client/__vitest__/assets/index-gyhe06Cm.js +52 -0
- package/dist/client/__vitest__/index.html +2 -2
- package/dist/client/__vitest_browser__/{orchestrator-x0A1t8rC.js → orchestrator-CNOAigTE.js} +59 -39
- package/dist/client/__vitest_browser__/preload-helper-Btt6SgIy.js +299 -0
- package/dist/client/__vitest_browser__/{tester-BdcP5piS.js → tester-DoK-7PCe.js} +29 -130
- package/dist/client/error-catcher.js +81 -0
- package/dist/client/esm-client-injector.js +1 -0
- package/dist/client/orchestrator.html +4 -3
- package/dist/client/tester/tester.html +4 -3
- package/dist/client.js +333 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +23 -36
- package/package.json +10 -7
- package/dist/client/__vitest__/assets/index-CAY_OcEp.js +0 -52
- package/dist/client/__vitest_browser__/client-dLyjuL0K.js +0 -540
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { channel, client } from '@vitest/browser/client'
|
|
2
|
+
|
|
3
|
+
function on(event, listener) {
|
|
4
|
+
window.addEventListener(event, listener)
|
|
5
|
+
return () => window.removeEventListener(event, listener)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function serializeError(unhandledError) {
|
|
9
|
+
if (typeof unhandledError !== 'object' || !unhandledError) {
|
|
10
|
+
return {
|
|
11
|
+
message: String(unhandledError),
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
name: unhandledError.name,
|
|
17
|
+
message: unhandledError.message,
|
|
18
|
+
stack: String(unhandledError.stack),
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function catchWindowErrors(cb) {
|
|
23
|
+
let userErrorListenerCount = 0
|
|
24
|
+
function throwUnhandlerError(e) {
|
|
25
|
+
if (userErrorListenerCount === 0 && e.error != null) {
|
|
26
|
+
cb(e)
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
console.error(e.error)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const addEventListener = window.addEventListener.bind(window)
|
|
33
|
+
const removeEventListener = window.removeEventListener.bind(window)
|
|
34
|
+
window.addEventListener('error', throwUnhandlerError)
|
|
35
|
+
window.addEventListener = function (...args) {
|
|
36
|
+
if (args[0] === 'error') {
|
|
37
|
+
userErrorListenerCount++
|
|
38
|
+
}
|
|
39
|
+
return addEventListener.apply(this, args)
|
|
40
|
+
}
|
|
41
|
+
window.removeEventListener = function (...args) {
|
|
42
|
+
if (args[0] === 'error' && userErrorListenerCount) {
|
|
43
|
+
userErrorListenerCount--
|
|
44
|
+
}
|
|
45
|
+
return removeEventListener.apply(this, args)
|
|
46
|
+
}
|
|
47
|
+
return function clearErrorHandlers() {
|
|
48
|
+
window.removeEventListener('error', throwUnhandlerError)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function registerUnexpectedErrors() {
|
|
53
|
+
catchWindowErrors(event =>
|
|
54
|
+
reportUnexpectedError('Error', event.error),
|
|
55
|
+
)
|
|
56
|
+
on('unhandledrejection', event =>
|
|
57
|
+
reportUnexpectedError('Unhandled Rejection', event.reason))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function reportUnexpectedError(
|
|
61
|
+
type,
|
|
62
|
+
error,
|
|
63
|
+
) {
|
|
64
|
+
const processedError = serializeError(error)
|
|
65
|
+
await client.rpc.onUnhandledError(processedError, type)
|
|
66
|
+
const state = __vitest_browser_runner__
|
|
67
|
+
|
|
68
|
+
if (state.type === 'orchestrator') {
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!state.runTests || !__vitest_worker__.current) {
|
|
73
|
+
channel.postMessage({
|
|
74
|
+
type: 'done',
|
|
75
|
+
filenames: state.files,
|
|
76
|
+
id: state.iframeId,
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
registerUnexpectedErrors()
|
|
@@ -23,6 +23,7 @@ window.__vitest_browser_runner__ = {
|
|
|
23
23
|
files: { __VITEST_FILES__ },
|
|
24
24
|
type: { __VITEST_TYPE__ },
|
|
25
25
|
contextId: { __VITEST_CONTEXT_ID__ },
|
|
26
|
+
testerId: { __VITEST_TESTER_ID__ },
|
|
26
27
|
provider: { __VITEST_PROVIDER__ },
|
|
27
28
|
providedContext: { __VITEST_PROVIDED_CONTEXT__ },
|
|
28
29
|
};
|
|
@@ -23,10 +23,11 @@
|
|
|
23
23
|
height: 100%;
|
|
24
24
|
}
|
|
25
25
|
</style>
|
|
26
|
-
|
|
26
|
+
{__VITEST_INJECTOR__}
|
|
27
|
+
{__VITEST_ERROR_CATCHER__}
|
|
27
28
|
{__VITEST_SCRIPTS__}
|
|
28
|
-
<script type="module" crossorigin src="/__vitest_browser__/orchestrator-
|
|
29
|
-
<link rel="modulepreload" crossorigin href="/__vitest_browser__/
|
|
29
|
+
<script type="module" crossorigin src="/__vitest_browser__/orchestrator-CNOAigTE.js"></script>
|
|
30
|
+
<link rel="modulepreload" crossorigin href="/__vitest_browser__/preload-helper-Btt6SgIy.js">
|
|
30
31
|
</head>
|
|
31
32
|
<body>
|
|
32
33
|
<div id="vitest-tester"></div>
|
|
@@ -16,11 +16,12 @@
|
|
|
16
16
|
min-height: 100vh;
|
|
17
17
|
}
|
|
18
18
|
</style>
|
|
19
|
-
|
|
19
|
+
{__VITEST_INJECTOR__}
|
|
20
20
|
<script>{__VITEST_STATE__}</script>
|
|
21
|
+
{__VITEST_ERROR_CATCHER__}
|
|
21
22
|
{__VITEST_SCRIPTS__}
|
|
22
|
-
<script type="module" crossorigin src="/__vitest_browser__/tester-
|
|
23
|
-
<link rel="modulepreload" crossorigin href="/__vitest_browser__/
|
|
23
|
+
<script type="module" crossorigin src="/__vitest_browser__/tester-DoK-7PCe.js"></script>
|
|
24
|
+
<link rel="modulepreload" crossorigin href="/__vitest_browser__/preload-helper-Btt6SgIy.js">
|
|
24
25
|
</head>
|
|
25
26
|
<body
|
|
26
27
|
data-vitest-body
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
const DEFAULT_TIMEOUT = 6e4;
|
|
2
|
+
function defaultSerialize(i) {
|
|
3
|
+
return i;
|
|
4
|
+
}
|
|
5
|
+
const defaultDeserialize = defaultSerialize;
|
|
6
|
+
const { clearTimeout: clearTimeout$1, setTimeout: setTimeout$1 } = globalThis;
|
|
7
|
+
const random = Math.random.bind(Math);
|
|
8
|
+
function createBirpc(functions, options) {
|
|
9
|
+
const {
|
|
10
|
+
post,
|
|
11
|
+
on,
|
|
12
|
+
eventNames = [],
|
|
13
|
+
serialize = defaultSerialize,
|
|
14
|
+
deserialize = defaultDeserialize,
|
|
15
|
+
resolver,
|
|
16
|
+
timeout = DEFAULT_TIMEOUT
|
|
17
|
+
} = options;
|
|
18
|
+
const rpcPromiseMap = /* @__PURE__ */ new Map();
|
|
19
|
+
let _promise;
|
|
20
|
+
const rpc = new Proxy({}, {
|
|
21
|
+
get(_, method) {
|
|
22
|
+
if (method === "$functions")
|
|
23
|
+
return functions;
|
|
24
|
+
if (method === "then" && !eventNames.includes("then") && !("then" in functions))
|
|
25
|
+
return void 0;
|
|
26
|
+
const sendEvent = (...args) => {
|
|
27
|
+
post(serialize({ m: method, a: args, t: "q" }));
|
|
28
|
+
};
|
|
29
|
+
if (eventNames.includes(method)) {
|
|
30
|
+
sendEvent.asEvent = sendEvent;
|
|
31
|
+
return sendEvent;
|
|
32
|
+
}
|
|
33
|
+
const sendCall = async (...args) => {
|
|
34
|
+
await _promise;
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const id = nanoid();
|
|
37
|
+
let timeoutId;
|
|
38
|
+
if (timeout >= 0) {
|
|
39
|
+
timeoutId = setTimeout$1(() => {
|
|
40
|
+
try {
|
|
41
|
+
options.onTimeoutError?.(method, args);
|
|
42
|
+
throw new Error(`[birpc] timeout on calling "${method}"`);
|
|
43
|
+
} catch (e) {
|
|
44
|
+
reject(e);
|
|
45
|
+
}
|
|
46
|
+
rpcPromiseMap.delete(id);
|
|
47
|
+
}, timeout);
|
|
48
|
+
if (typeof timeoutId === "object")
|
|
49
|
+
timeoutId = timeoutId.unref?.();
|
|
50
|
+
}
|
|
51
|
+
rpcPromiseMap.set(id, { resolve, reject, timeoutId });
|
|
52
|
+
post(serialize({ m: method, a: args, i: id, t: "q" }));
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
sendCall.asEvent = sendEvent;
|
|
56
|
+
return sendCall;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
_promise = on(async (data, ...extra) => {
|
|
60
|
+
const msg = deserialize(data);
|
|
61
|
+
if (msg.t === "q") {
|
|
62
|
+
const { m: method, a: args } = msg;
|
|
63
|
+
let result, error;
|
|
64
|
+
const fn = resolver ? resolver(method, functions[method]) : functions[method];
|
|
65
|
+
if (!fn) {
|
|
66
|
+
error = new Error(`[birpc] function "${method}" not found`);
|
|
67
|
+
} else {
|
|
68
|
+
try {
|
|
69
|
+
result = await fn.apply(rpc, args);
|
|
70
|
+
} catch (e) {
|
|
71
|
+
error = e;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (msg.i) {
|
|
75
|
+
if (error && options.onError)
|
|
76
|
+
options.onError(error, method, args);
|
|
77
|
+
post(serialize({ t: "s", i: msg.i, r: result, e: error }), ...extra);
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
const { i: ack, r: result, e: error } = msg;
|
|
81
|
+
const promise = rpcPromiseMap.get(ack);
|
|
82
|
+
if (promise) {
|
|
83
|
+
clearTimeout$1(promise.timeoutId);
|
|
84
|
+
if (error)
|
|
85
|
+
promise.reject(error);
|
|
86
|
+
else
|
|
87
|
+
promise.resolve(result);
|
|
88
|
+
}
|
|
89
|
+
rpcPromiseMap.delete(ack);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return rpc;
|
|
93
|
+
}
|
|
94
|
+
const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
|
|
95
|
+
function nanoid(size = 21) {
|
|
96
|
+
let id = "";
|
|
97
|
+
let i = size;
|
|
98
|
+
while (i--)
|
|
99
|
+
id += urlAlphabet[random() * 64 | 0];
|
|
100
|
+
return id;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/// <reference types="../types/index.d.ts" />
|
|
104
|
+
|
|
105
|
+
// (c) 2020-present Andrea Giammarchi
|
|
106
|
+
|
|
107
|
+
const {parse: $parse, stringify: $stringify} = JSON;
|
|
108
|
+
const {keys} = Object;
|
|
109
|
+
|
|
110
|
+
const Primitive = String; // it could be Number
|
|
111
|
+
const primitive = 'string'; // it could be 'number'
|
|
112
|
+
|
|
113
|
+
const ignore = {};
|
|
114
|
+
const object = 'object';
|
|
115
|
+
|
|
116
|
+
const noop = (_, value) => value;
|
|
117
|
+
|
|
118
|
+
const primitives = value => (
|
|
119
|
+
value instanceof Primitive ? Primitive(value) : value
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
const Primitives = (_, value) => (
|
|
123
|
+
typeof value === primitive ? new Primitive(value) : value
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const revive = (input, parsed, output, $) => {
|
|
127
|
+
const lazy = [];
|
|
128
|
+
for (let ke = keys(output), {length} = ke, y = 0; y < length; y++) {
|
|
129
|
+
const k = ke[y];
|
|
130
|
+
const value = output[k];
|
|
131
|
+
if (value instanceof Primitive) {
|
|
132
|
+
const tmp = input[value];
|
|
133
|
+
if (typeof tmp === object && !parsed.has(tmp)) {
|
|
134
|
+
parsed.add(tmp);
|
|
135
|
+
output[k] = ignore;
|
|
136
|
+
lazy.push({k, a: [input, parsed, tmp, $]});
|
|
137
|
+
}
|
|
138
|
+
else
|
|
139
|
+
output[k] = $.call(output, k, tmp);
|
|
140
|
+
}
|
|
141
|
+
else if (output[k] !== ignore)
|
|
142
|
+
output[k] = $.call(output, k, value);
|
|
143
|
+
}
|
|
144
|
+
for (let {length} = lazy, i = 0; i < length; i++) {
|
|
145
|
+
const {k, a} = lazy[i];
|
|
146
|
+
output[k] = $.call(output, k, revive.apply(null, a));
|
|
147
|
+
}
|
|
148
|
+
return output;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const set = (known, input, value) => {
|
|
152
|
+
const index = Primitive(input.push(value) - 1);
|
|
153
|
+
known.set(value, index);
|
|
154
|
+
return index;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Converts a specialized flatted string into a JS value.
|
|
159
|
+
* @param {string} text
|
|
160
|
+
* @param {(this: any, key: string, value: any) => any} [reviver]
|
|
161
|
+
* @returns {any}
|
|
162
|
+
*/
|
|
163
|
+
const parse = (text, reviver) => {
|
|
164
|
+
const input = $parse(text, Primitives).map(primitives);
|
|
165
|
+
const value = input[0];
|
|
166
|
+
const $ = reviver || noop;
|
|
167
|
+
const tmp = typeof value === object && value ?
|
|
168
|
+
revive(input, new Set, value, $) :
|
|
169
|
+
value;
|
|
170
|
+
return $.call({'': tmp}, '', tmp);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Converts a JS value into a specialized flatted string.
|
|
175
|
+
* @param {any} value
|
|
176
|
+
* @param {((this: any, key: string, value: any) => any) | (string | number)[] | null | undefined} [replacer]
|
|
177
|
+
* @param {string | number | undefined} [space]
|
|
178
|
+
* @returns {string}
|
|
179
|
+
*/
|
|
180
|
+
const stringify = (value, replacer, space) => {
|
|
181
|
+
const $ = replacer && typeof replacer === object ?
|
|
182
|
+
(k, v) => (k === '' || -1 < replacer.indexOf(k) ? v : void 0) :
|
|
183
|
+
(replacer || noop);
|
|
184
|
+
const known = new Map;
|
|
185
|
+
const input = [];
|
|
186
|
+
const output = [];
|
|
187
|
+
let i = +set(known, input, $.call({'': value}, '', value));
|
|
188
|
+
let firstRun = !i;
|
|
189
|
+
while (i < input.length) {
|
|
190
|
+
firstRun = true;
|
|
191
|
+
output[i] = $stringify(input[i++], replace, space);
|
|
192
|
+
}
|
|
193
|
+
return '[' + output.join(',') + ']';
|
|
194
|
+
function replace(key, value) {
|
|
195
|
+
if (firstRun) {
|
|
196
|
+
firstRun = !firstRun;
|
|
197
|
+
return value;
|
|
198
|
+
}
|
|
199
|
+
const after = $.call(this, key, value);
|
|
200
|
+
switch (typeof after) {
|
|
201
|
+
case object:
|
|
202
|
+
if (after === null) return after;
|
|
203
|
+
case primitive:
|
|
204
|
+
return known.get(after) || set(known, input, after);
|
|
205
|
+
}
|
|
206
|
+
return after;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
// @__NO_SIDE_EFFECTS__
|
|
211
|
+
function getBrowserState() {
|
|
212
|
+
return window.__vitest_browser_runner__;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const channel = new BroadcastChannel(
|
|
216
|
+
`vitest:${getBrowserState().contextId}`
|
|
217
|
+
);
|
|
218
|
+
const globalChannel = new BroadcastChannel("vitest:global");
|
|
219
|
+
function waitForChannel(event) {
|
|
220
|
+
return new Promise((resolve) => {
|
|
221
|
+
channel.addEventListener(
|
|
222
|
+
"message",
|
|
223
|
+
(e) => {
|
|
224
|
+
if (e.data?.type === event) {
|
|
225
|
+
resolve();
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
{ once: true }
|
|
229
|
+
);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const PAGE_TYPE = getBrowserState().type;
|
|
234
|
+
const PORT = location.port;
|
|
235
|
+
const HOST = [location.hostname, PORT].filter(Boolean).join(":");
|
|
236
|
+
const SESSION_ID = PAGE_TYPE === "orchestrator" ? getBrowserState().contextId : getBrowserState().testerId;
|
|
237
|
+
const ENTRY_URL = `${location.protocol === "https:" ? "wss:" : "ws:"}//${HOST}/__vitest_browser_api__?type=${PAGE_TYPE}&sessionId=${SESSION_ID}`;
|
|
238
|
+
let setCancel = (_) => {
|
|
239
|
+
};
|
|
240
|
+
const onCancel = new Promise((resolve) => {
|
|
241
|
+
setCancel = resolve;
|
|
242
|
+
});
|
|
243
|
+
function createClient() {
|
|
244
|
+
const reconnectInterval = 2e3;
|
|
245
|
+
const reconnectTries = 10;
|
|
246
|
+
const connectTimeout = 6e4;
|
|
247
|
+
let tries = reconnectTries;
|
|
248
|
+
const ctx = {
|
|
249
|
+
ws: new WebSocket(ENTRY_URL),
|
|
250
|
+
waitForConnection
|
|
251
|
+
};
|
|
252
|
+
let onMessage;
|
|
253
|
+
ctx.rpc = createBirpc(
|
|
254
|
+
{
|
|
255
|
+
onCancel: setCancel,
|
|
256
|
+
async createTesters(files) {
|
|
257
|
+
if (PAGE_TYPE !== "orchestrator") {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
getBrowserState().createTesters?.(files);
|
|
261
|
+
},
|
|
262
|
+
cdpEvent(event, payload) {
|
|
263
|
+
const cdp = getBrowserState().cdp;
|
|
264
|
+
if (!cdp) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
cdp.emit(event, payload);
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
post: (msg) => ctx.ws.send(msg),
|
|
272
|
+
on: (fn) => onMessage = fn,
|
|
273
|
+
serialize: (e) => stringify(e, (_, v) => {
|
|
274
|
+
if (v instanceof Error) {
|
|
275
|
+
return {
|
|
276
|
+
name: v.name,
|
|
277
|
+
message: v.message,
|
|
278
|
+
stack: v.stack
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
return v;
|
|
282
|
+
}),
|
|
283
|
+
deserialize: parse,
|
|
284
|
+
onTimeoutError(functionName) {
|
|
285
|
+
throw new Error(`[vitest-browser]: Timeout calling "${functionName}"`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
);
|
|
289
|
+
let openPromise;
|
|
290
|
+
function reconnect(reset = false) {
|
|
291
|
+
if (reset) {
|
|
292
|
+
tries = reconnectTries;
|
|
293
|
+
}
|
|
294
|
+
ctx.ws = new WebSocket(ENTRY_URL);
|
|
295
|
+
registerWS();
|
|
296
|
+
}
|
|
297
|
+
function registerWS() {
|
|
298
|
+
openPromise = new Promise((resolve, reject) => {
|
|
299
|
+
const timeout = setTimeout(() => {
|
|
300
|
+
reject(
|
|
301
|
+
new Error(
|
|
302
|
+
`Cannot connect to the server in ${connectTimeout / 1e3} seconds`
|
|
303
|
+
)
|
|
304
|
+
);
|
|
305
|
+
}, connectTimeout)?.unref?.();
|
|
306
|
+
if (ctx.ws.OPEN === ctx.ws.readyState) {
|
|
307
|
+
resolve();
|
|
308
|
+
}
|
|
309
|
+
ctx.ws.addEventListener("open", () => {
|
|
310
|
+
tries = reconnectTries;
|
|
311
|
+
resolve();
|
|
312
|
+
clearTimeout(timeout);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
ctx.ws.addEventListener("message", (v) => {
|
|
316
|
+
onMessage(v.data);
|
|
317
|
+
});
|
|
318
|
+
ctx.ws.addEventListener("close", () => {
|
|
319
|
+
tries -= 1;
|
|
320
|
+
if (tries > 0) {
|
|
321
|
+
setTimeout(reconnect, reconnectInterval);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
registerWS();
|
|
326
|
+
function waitForConnection() {
|
|
327
|
+
return openPromise;
|
|
328
|
+
}
|
|
329
|
+
return ctx;
|
|
330
|
+
}
|
|
331
|
+
const client = createClient();
|
|
332
|
+
|
|
333
|
+
export { ENTRY_URL, HOST, PORT, SESSION_ID, channel, client, globalChannel, onCancel, waitForChannel };
|
package/dist/index.d.ts
CHANGED
|
@@ -103,6 +103,7 @@ declare class BrowserServer implements BrowserServer$1 {
|
|
|
103
103
|
testerHtml: Promise<string> | string;
|
|
104
104
|
orchestratorHtml: Promise<string> | string;
|
|
105
105
|
injectorJs: Promise<string> | string;
|
|
106
|
+
errorCatcherPath: Promise<string> | string;
|
|
106
107
|
stateJs: Promise<string> | string;
|
|
107
108
|
state: BrowserServerState;
|
|
108
109
|
provider: BrowserProvider;
|
|
@@ -119,7 +120,7 @@ declare class BrowserServer implements BrowserServer$1 {
|
|
|
119
120
|
initBrowserProvider(): Promise<void>;
|
|
120
121
|
parseErrorStacktrace(e: ErrorWithDiff, options?: StackTraceParserOptions): vitest.ParsedStack[];
|
|
121
122
|
parseStacktrace(trace: string, options?: StackTraceParserOptions): vitest.ParsedStack[];
|
|
122
|
-
private
|
|
123
|
+
private cdpSessionsPromises;
|
|
123
124
|
ensureCDPHandler(contextId: string, sessionId: string): Promise<BrowserServerCDPHandler>;
|
|
124
125
|
close(): Promise<void>;
|
|
125
126
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { createDebugger, isFileServingAllowed
|
|
1
|
+
import { createDebugger, isFileServingAllowed, getFilePoolName, resolveApiServerConfig, resolveFsAllow, distDir, createServer } from 'vitest/node';
|
|
2
2
|
import fs, { existsSync, readdirSync, readFileSync, promises } from 'node:fs';
|
|
3
3
|
import { WebSocketServer } from 'ws';
|
|
4
|
-
import { isFileServingAllowed } from 'vite';
|
|
5
4
|
import { builtinModules, createRequire } from 'node:module';
|
|
6
5
|
import { readFile as readFile$1, mkdir } from 'node:fs/promises';
|
|
7
6
|
import { fileURLToPath } from 'node:url';
|
|
@@ -13,8 +12,8 @@ import { P as PlaywrightBrowserProvider, W as WebdriverBrowserProvider } from '.
|
|
|
13
12
|
import { resolve as resolve$1, dirname as dirname$1, normalize as normalize$1 } from 'node:path';
|
|
14
13
|
import MagicString from 'magic-string';
|
|
15
14
|
import { esmWalker } from '@vitest/utils/ast';
|
|
16
|
-
import * as nodeos from 'node:os';
|
|
17
15
|
import crypto from 'node:crypto';
|
|
16
|
+
import * as nodeos from 'node:os';
|
|
18
17
|
|
|
19
18
|
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
20
19
|
function normalizeWindowsPath(input = "") {
|
|
@@ -868,6 +867,7 @@ class BrowserServer {
|
|
|
868
867
|
resolve(distRoot, "client/esm-client-injector.js"),
|
|
869
868
|
"utf8"
|
|
870
869
|
).then((js) => this.injectorJs = js);
|
|
870
|
+
this.errorCatcherPath = resolve(distRoot, "client/error-catcher.js");
|
|
871
871
|
this.stateJs = readFile$1(
|
|
872
872
|
resolve(distRoot, "state.js"),
|
|
873
873
|
"utf-8"
|
|
@@ -881,6 +881,7 @@ class BrowserServer {
|
|
|
881
881
|
testerHtml;
|
|
882
882
|
orchestratorHtml;
|
|
883
883
|
injectorJs;
|
|
884
|
+
errorCatcherPath;
|
|
884
885
|
stateJs;
|
|
885
886
|
state;
|
|
886
887
|
provider;
|
|
@@ -952,7 +953,7 @@ class BrowserServer {
|
|
|
952
953
|
...options
|
|
953
954
|
});
|
|
954
955
|
}
|
|
955
|
-
|
|
956
|
+
cdpSessionsPromises = /* @__PURE__ */ new Map();
|
|
956
957
|
async ensureCDPHandler(contextId, sessionId) {
|
|
957
958
|
const cachedHandler = this.state.cdps.get(sessionId);
|
|
958
959
|
if (cachedHandler) {
|
|
@@ -962,11 +963,11 @@ class BrowserServer {
|
|
|
962
963
|
if (!provider.getCDPSession) {
|
|
963
964
|
throw new Error(`CDP is not supported by the provider "${provider.name}".`);
|
|
964
965
|
}
|
|
965
|
-
const promise = this.
|
|
966
|
+
const promise = this.cdpSessionsPromises.get(sessionId) ?? await (async () => {
|
|
966
967
|
const promise2 = provider.getCDPSession(contextId).finally(() => {
|
|
967
|
-
this.
|
|
968
|
+
this.cdpSessionsPromises.delete(sessionId);
|
|
968
969
|
});
|
|
969
|
-
this.
|
|
970
|
+
this.cdpSessionsPromises.set(sessionId, promise2);
|
|
970
971
|
return promise2;
|
|
971
972
|
})();
|
|
972
973
|
const session = await promise;
|
|
@@ -1433,7 +1434,7 @@ const keyboard = async (context, text) => {
|
|
|
1433
1434
|
throw new TypeError(`Provider "${context.provider.name}" does not support selecting all text`);
|
|
1434
1435
|
}
|
|
1435
1436
|
},
|
|
1436
|
-
|
|
1437
|
+
true
|
|
1437
1438
|
);
|
|
1438
1439
|
};
|
|
1439
1440
|
async function keyboardImplementation(provider, contextId, text, selectAll, skipRelease) {
|
|
@@ -1662,7 +1663,7 @@ const hover = async (context, selector, options = {}) => {
|
|
|
1662
1663
|
};
|
|
1663
1664
|
|
|
1664
1665
|
function assertFileAccess(path, project) {
|
|
1665
|
-
if (!isFileServingAllowed
|
|
1666
|
+
if (!isFileServingAllowed(path, project.server) && !isFileServingAllowed(path, project.ctx.server)) {
|
|
1666
1667
|
throw new Error(
|
|
1667
1668
|
`Access denied to "${path}". See Vite config documentation for "server.fs": https://vitejs.dev/config/server-options.html#server-fs-strict.`
|
|
1668
1669
|
);
|
|
@@ -1930,6 +1931,7 @@ async function resolveOrchestrator(server, url, res) {
|
|
|
1930
1931
|
__VITEST_FILES__: JSON.stringify(files),
|
|
1931
1932
|
__VITEST_TYPE__: '"orchestrator"',
|
|
1932
1933
|
__VITEST_CONTEXT_ID__: JSON.stringify(contextId),
|
|
1934
|
+
__VITEST_TESTER_ID__: '"none"',
|
|
1933
1935
|
__VITEST_PROVIDED_CONTEXT__: "{}"
|
|
1934
1936
|
});
|
|
1935
1937
|
res.removeHeader("Content-Security-Policy");
|
|
@@ -1946,7 +1948,8 @@ async function resolveOrchestrator(server, url, res) {
|
|
|
1946
1948
|
baseHtml = baseHtml.replaceAll("./assets/", `${base}__vitest__/assets/`).replace(
|
|
1947
1949
|
"<!-- !LOAD_METADATA! -->",
|
|
1948
1950
|
[
|
|
1949
|
-
"
|
|
1951
|
+
"{__VITEST_INJECTOR__}",
|
|
1952
|
+
"{__VITEST_ERROR_CATCHER__}",
|
|
1950
1953
|
"{__VITEST_SCRIPTS__}",
|
|
1951
1954
|
`<script type="module" crossorigin src="${base}${jsEntry}"><\/script>`
|
|
1952
1955
|
].join("\n")
|
|
@@ -1956,7 +1959,8 @@ async function resolveOrchestrator(server, url, res) {
|
|
|
1956
1959
|
__VITEST_FAVICON__: server.faviconUrl,
|
|
1957
1960
|
__VITEST_TITLE__: "Vitest Browser Runner",
|
|
1958
1961
|
__VITEST_SCRIPTS__: server.orchestratorScripts,
|
|
1959
|
-
__VITEST_INJECTOR__: injector
|
|
1962
|
+
__VITEST_INJECTOR__: `<script type="module">${injector}<\/script>`,
|
|
1963
|
+
__VITEST_ERROR_CATCHER__: `<script type="module" src="${server.errorCatcherPath}"><\/script>`,
|
|
1960
1964
|
__VITEST_CONTEXT_ID__: JSON.stringify(contextId)
|
|
1961
1965
|
});
|
|
1962
1966
|
}
|
|
@@ -1989,6 +1993,7 @@ async function resolveTester(server, url, res) {
|
|
|
1989
1993
|
}),
|
|
1990
1994
|
__VITEST_TYPE__: '"tester"',
|
|
1991
1995
|
__VITEST_CONTEXT_ID__: JSON.stringify(contextId),
|
|
1996
|
+
__VITEST_TESTER_ID__: JSON.stringify(crypto.randomUUID()),
|
|
1992
1997
|
__VITEST_PROVIDED_CONTEXT__: JSON.stringify(stringify(project.getProvidedContext()))
|
|
1993
1998
|
});
|
|
1994
1999
|
if (!server.testerScripts) {
|
|
@@ -2005,7 +2010,8 @@ async function resolveTester(server, url, res) {
|
|
|
2005
2010
|
__VITEST_FAVICON__: server.faviconUrl,
|
|
2006
2011
|
__VITEST_TITLE__: "Vitest Browser Tester",
|
|
2007
2012
|
__VITEST_SCRIPTS__: server.testerScripts,
|
|
2008
|
-
__VITEST_INJECTOR__: injector
|
|
2013
|
+
__VITEST_INJECTOR__: `<script type="module">${injector}<\/script>`,
|
|
2014
|
+
__VITEST_ERROR_CATCHER__: `<script type="module" src="${server.errorCatcherPath}"><\/script>`,
|
|
2009
2015
|
__VITEST_APPEND__: `<script type="module">
|
|
2010
2016
|
__vitest_browser_runner__.runningFiles = ${tests}
|
|
2011
2017
|
__vitest_browser_runner__.iframeId = ${iframeId}
|
|
@@ -2018,7 +2024,6 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2018
2024
|
const pkgRoot = resolve(fileURLToPath(import.meta.url), "../..");
|
|
2019
2025
|
const distRoot = resolve(pkgRoot, "dist");
|
|
2020
2026
|
const project = browserServer.project;
|
|
2021
|
-
let loupePath;
|
|
2022
2027
|
return [
|
|
2023
2028
|
{
|
|
2024
2029
|
enforce: "pre",
|
|
@@ -2035,7 +2040,7 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2035
2040
|
next();
|
|
2036
2041
|
});
|
|
2037
2042
|
server.middlewares.use(async function vitestBrowserMode(req, res, next) {
|
|
2038
|
-
if (!req.url) {
|
|
2043
|
+
if (!req.url || !browserServer.provider) {
|
|
2039
2044
|
return next();
|
|
2040
2045
|
}
|
|
2041
2046
|
const url = new URL(req.url, "http://localhost");
|
|
@@ -2144,6 +2149,8 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2144
2149
|
"vitest/utils",
|
|
2145
2150
|
"vitest/browser",
|
|
2146
2151
|
"vitest/runners",
|
|
2152
|
+
"@vitest/browser",
|
|
2153
|
+
"@vitest/browser/client",
|
|
2147
2154
|
"@vitest/utils",
|
|
2148
2155
|
"@vitest/utils/source-map",
|
|
2149
2156
|
"@vitest/runner",
|
|
@@ -2154,21 +2161,15 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2154
2161
|
"std-env",
|
|
2155
2162
|
"tinybench",
|
|
2156
2163
|
"tinyspy",
|
|
2164
|
+
"tinyrainbow",
|
|
2157
2165
|
"pathe",
|
|
2158
2166
|
"msw",
|
|
2159
2167
|
"msw/browser"
|
|
2160
2168
|
],
|
|
2161
2169
|
include: [
|
|
2162
|
-
"vitest > @vitest/utils > pretty-format",
|
|
2163
|
-
"vitest > @vitest/snapshot > pretty-format",
|
|
2164
2170
|
"vitest > @vitest/snapshot > magic-string",
|
|
2165
|
-
"vitest > pretty-format",
|
|
2166
|
-
"vitest > pretty-format > ansi-styles",
|
|
2167
|
-
"vitest > pretty-format > ansi-regex",
|
|
2168
2171
|
"vitest > chai",
|
|
2169
2172
|
"vitest > chai > loupe",
|
|
2170
|
-
"vitest > @vitest/runner > pretty-format",
|
|
2171
|
-
"vitest > @vitest/utils > diff-sequences",
|
|
2172
2173
|
"vitest > @vitest/utils > loupe",
|
|
2173
2174
|
"@vitest/browser > @testing-library/user-event",
|
|
2174
2175
|
"@vitest/browser > @testing-library/dom"
|
|
@@ -2193,17 +2194,6 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2193
2194
|
{
|
|
2194
2195
|
name: "vitest:browser:resolve-virtual",
|
|
2195
2196
|
async resolveId(rawId) {
|
|
2196
|
-
if (rawId.startsWith("/__virtual_vitest__")) {
|
|
2197
|
-
const url = new URL(rawId, "http://localhost");
|
|
2198
|
-
if (!url.searchParams.has("id")) {
|
|
2199
|
-
return;
|
|
2200
|
-
}
|
|
2201
|
-
const id = decodeURIComponent(url.searchParams.get("id"));
|
|
2202
|
-
const resolved = await this.resolve(id, distRoot, {
|
|
2203
|
-
skipSelf: true
|
|
2204
|
-
});
|
|
2205
|
-
return resolved;
|
|
2206
|
-
}
|
|
2207
2197
|
if (rawId === "/__vitest_msw__") {
|
|
2208
2198
|
return this.resolve("msw/mockServiceWorker.js", distRoot, {
|
|
2209
2199
|
skipSelf: true
|
|
@@ -2218,11 +2208,8 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2218
2208
|
return resolve(distRoot, "client", id.slice(1));
|
|
2219
2209
|
}
|
|
2220
2210
|
},
|
|
2221
|
-
configResolved(config) {
|
|
2222
|
-
loupePath = resolve(config.cacheDir, "deps/loupe.js");
|
|
2223
|
-
},
|
|
2224
2211
|
transform(code, id) {
|
|
2225
|
-
if (id.
|
|
2212
|
+
if (id.includes(browserServer.vite.config.cacheDir) && id.includes("loupe.js")) {
|
|
2226
2213
|
const utilRequire = "nodeUtil = require_util();";
|
|
2227
2214
|
return code.replace(utilRequire, " ".repeat(utilRequire.length));
|
|
2228
2215
|
}
|