@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.
@@ -1,10 +1,12 @@
1
- import { c as client, a as channel, g as getBrowserState, b as getConfig, r as relative, d as rpcDone } from "./rpc-CImfI7bO.js";
2
- import { http } from "/__virtual_vitest__:msw/core/http";
3
- import { setupWorker } from "/__virtual_vitest__:msw/browser";
1
+ import { c as channel, g as getBrowserState, a as client, b as getConfig, r as relative, d as rpcDone } from "./rpc-D6HtJ5Rb.js";
2
+ import { http } from "/__virtual_vitest__?id=msw%2Fcore%2Fhttp";
3
+ import { setupWorker } from "/__virtual_vitest__?id=msw%2Fbrowser";
4
+ import "/__virtual_vitest__?id=vitest%2Futils";
4
5
  function generateHash(str) {
5
6
  let hash = 0;
6
- if (str.length === 0)
7
+ if (str.length === 0) {
7
8
  return `${hash}`;
9
+ }
8
10
  for (let i = 0; i < str.length; i++) {
9
11
  const char = str.charCodeAt(i);
10
12
  hash = (hash << 5) - hash + char;
@@ -20,15 +22,17 @@ function createModuleMocker() {
20
22
  const worker = setupWorker(
21
23
  http.get(/.+/, async ({ request }) => {
22
24
  const path = removeTimestamp(request.url.slice(location.origin.length));
23
- if (!mocks.has(path))
25
+ if (!mocks.has(path)) {
24
26
  return passthrough();
27
+ }
25
28
  const mock = mocks.get(path);
26
29
  if (mock === void 0) {
27
30
  const exports = await getFactoryExports(path);
28
31
  const module = `const module = __vitest_mocker__.get('${path}');`;
29
32
  const keys = exports.map((name) => {
30
- if (name === "default")
33
+ if (name === "default") {
31
34
  return `export default module['default'];`;
35
+ }
32
36
  return `export const ${name} = module['${name}'];`;
33
37
  }).join("\n");
34
38
  const text = `${module}
@@ -39,26 +43,24 @@ ${keys}`;
39
43
  }
40
44
  });
41
45
  }
42
- if (typeof mock === "string")
46
+ if (typeof mock === "string") {
43
47
  return Response.redirect(mock);
44
- const content = await client.rpc.automock(path);
45
- return new Response(content, {
46
- headers: {
47
- "Content-Type": "application/javascript"
48
- }
49
- });
48
+ }
49
+ return Response.redirect(injectQuery(path, "mock=auto"));
50
50
  })
51
51
  );
52
52
  let started = false;
53
53
  let startPromise;
54
54
  async function init() {
55
- if (started)
55
+ if (started) {
56
56
  return;
57
- if (startPromise)
57
+ }
58
+ if (startPromise) {
58
59
  return startPromise;
60
+ }
59
61
  startPromise = worker.start({
60
62
  serviceWorker: {
61
- url: "/__virtual_vitest__:mocker-worker.js"
63
+ url: "/__vitest_msw__"
62
64
  },
63
65
  quiet: true
64
66
  }).finally(() => {
@@ -89,16 +91,19 @@ function getFactoryExports(id) {
89
91
  id
90
92
  });
91
93
  return new Promise((resolve, reject) => {
92
- channel.addEventListener("message", function onMessage(e) {
93
- if (e.data.type === "mock-factory:response") {
94
- resolve(e.data.exports);
95
- channel.removeEventListener("message", onMessage);
96
- }
97
- if (e.data.type === "mock-factory:error") {
98
- reject(e.data.error);
99
- channel.removeEventListener("message", onMessage);
94
+ channel.addEventListener(
95
+ "message",
96
+ function onMessage(e) {
97
+ if (e.data.type === "mock-factory:response") {
98
+ resolve(e.data.exports);
99
+ channel.removeEventListener("message", onMessage);
100
+ }
101
+ if (e.data.type === "mock-factory:error") {
102
+ reject(e.data.error);
103
+ channel.removeEventListener("message", onMessage);
104
+ }
100
105
  }
101
- });
106
+ );
102
107
  });
103
108
  }
104
109
  const timestampRegexp = /(\?|&)t=\d{13}/;
@@ -114,6 +119,20 @@ function passthrough() {
114
119
  }
115
120
  });
116
121
  }
122
+ const postfixRE = /[?#].*$/;
123
+ function cleanUrl(url2) {
124
+ return url2.replace(postfixRE, "");
125
+ }
126
+ const replacePercentageRE = /%/g;
127
+ function injectQuery(url2, queryToInject) {
128
+ const resolvedUrl = new URL(
129
+ url2.replace(replacePercentageRE, "%25"),
130
+ location.href
131
+ );
132
+ const { search, hash } = resolvedUrl;
133
+ const pathname = cleanUrl(url2);
134
+ return `${pathname}?${queryToInject}${search ? `&${search.slice(1)}` : ""}${hash ?? ""}`;
135
+ }
117
136
  const url = new URL(location.href);
118
137
  const ID_ALL = "__vitest_all__";
119
138
  const iframes = /* @__PURE__ */ new Map();
@@ -127,8 +146,9 @@ getBrowserState().createTesters = async (files) => {
127
146
  };
128
147
  function debug(...args) {
129
148
  const debug2 = getConfig().env.VITEST_BROWSER_DEBUG;
130
- if (debug2 && debug2 !== "false")
149
+ if (debug2 && debug2 !== "false") {
131
150
  client.rpc.debug(...args.map(String));
151
+ }
132
152
  }
133
153
  function createIframe(container, file) {
134
154
  if (iframes.has(file)) {
@@ -137,7 +157,10 @@ function createIframe(container, file) {
137
157
  }
138
158
  const iframe = document.createElement("iframe");
139
159
  iframe.setAttribute("loading", "eager");
140
- iframe.setAttribute("src", `${url.pathname}__vitest_test__/__test__/${getBrowserState().contextId}/${encodeURIComponent(file)}`);
160
+ iframe.setAttribute(
161
+ "src",
162
+ `${url.pathname}__vitest_test__/__test__/${getBrowserState().contextId}/${encodeURIComponent(file)}`
163
+ );
141
164
  iframe.setAttribute("data-vitest", "true");
142
165
  iframe.style.display = "block";
143
166
  iframe.style.border = "none";
@@ -145,6 +168,7 @@ function createIframe(container, file) {
145
168
  iframe.style.position = "relative";
146
169
  iframe.setAttribute("allowfullscreen", "true");
147
170
  iframe.setAttribute("allow", "clipboard-write;");
171
+ iframe.setAttribute("name", "vitest-iframe");
148
172
  iframes.set(file, iframe);
149
173
  container.appendChild(iframe);
150
174
  return iframe;
@@ -174,79 +198,95 @@ client.ws.addEventListener("open", async () => {
174
198
  runningFiles.clear();
175
199
  testFiles.forEach((file) => runningFiles.add(file));
176
200
  const mocker = createModuleMocker();
177
- channel.addEventListener("message", async (e) => {
178
- var _a;
179
- debug("channel event", JSON.stringify(e.data));
180
- switch (e.data.type) {
181
- case "viewport": {
182
- const { width, height, id } = e.data;
183
- const iframe = iframes.get(id);
184
- if (!iframe) {
185
- const error = new Error(`Cannot find iframe with id ${id}`);
186
- channel.postMessage({ type: "viewport:fail", id, error: error.message });
187
- await client.rpc.onUnhandledError({
188
- name: "Teardown Error",
189
- message: error.message
190
- }, "Teardown Error");
191
- return;
201
+ channel.addEventListener(
202
+ "message",
203
+ async (e) => {
204
+ var _a;
205
+ debug("channel event", JSON.stringify(e.data));
206
+ switch (e.data.type) {
207
+ case "viewport": {
208
+ const { width, height, id } = e.data;
209
+ const iframe = iframes.get(id);
210
+ if (!iframe) {
211
+ const error = new Error(`Cannot find iframe with id ${id}`);
212
+ channel.postMessage({
213
+ type: "viewport:fail",
214
+ id,
215
+ error: error.message
216
+ });
217
+ await client.rpc.onUnhandledError(
218
+ {
219
+ name: "Teardown Error",
220
+ message: error.message
221
+ },
222
+ "Teardown Error"
223
+ );
224
+ return;
225
+ }
226
+ await setIframeViewport(iframe, width, height);
227
+ channel.postMessage({ type: "viewport:done", id });
228
+ break;
192
229
  }
193
- await setIframeViewport(iframe, width, height);
194
- channel.postMessage({ type: "viewport:done", id });
195
- break;
196
- }
197
- case "done": {
198
- const filenames = e.data.filenames;
199
- filenames.forEach((filename) => runningFiles.delete(filename));
200
- if (!runningFiles.size) {
201
- const ui = getUiAPI();
202
- if (ui && filenames.length > 1) {
203
- const id = generateFileId(filenames[filenames.length - 1]);
204
- ui.setCurrentFileId(id);
230
+ case "done": {
231
+ const filenames = e.data.filenames;
232
+ filenames.forEach((filename) => runningFiles.delete(filename));
233
+ if (!runningFiles.size) {
234
+ const ui = getUiAPI();
235
+ if (ui && filenames.length > 1) {
236
+ const id = generateFileId(filenames[filenames.length - 1]);
237
+ ui.setCurrentFileId(id);
238
+ }
239
+ await done();
240
+ } else {
241
+ const iframeId = e.data.id;
242
+ (_a = iframes.get(iframeId)) == null ? void 0 : _a.remove();
243
+ iframes.delete(iframeId);
205
244
  }
206
- await done();
207
- } else {
245
+ break;
246
+ }
247
+ case "error": {
208
248
  const iframeId = e.data.id;
209
- (_a = iframes.get(iframeId)) == null ? void 0 : _a.remove();
210
249
  iframes.delete(iframeId);
250
+ await client.rpc.onUnhandledError(e.data.error, e.data.errorType);
251
+ if (iframeId === ID_ALL) {
252
+ runningFiles.clear();
253
+ } else {
254
+ runningFiles.delete(iframeId);
255
+ }
256
+ if (!runningFiles.size) {
257
+ await done();
258
+ }
259
+ break;
211
260
  }
212
- break;
213
- }
214
- case "error": {
215
- const iframeId = e.data.id;
216
- iframes.delete(iframeId);
217
- await client.rpc.onUnhandledError(e.data.error, e.data.errorType);
218
- if (iframeId === ID_ALL)
219
- runningFiles.clear();
220
- else
221
- runningFiles.delete(iframeId);
222
- if (!runningFiles.size)
261
+ case "mock:invalidate":
262
+ mocker.invalidate();
263
+ break;
264
+ case "unmock":
265
+ await mocker.unmock(e.data);
266
+ break;
267
+ case "mock":
268
+ await mocker.mock(e.data);
269
+ break;
270
+ case "mock-factory:error":
271
+ case "mock-factory:response":
272
+ break;
273
+ default: {
274
+ e.data;
275
+ await client.rpc.onUnhandledError(
276
+ {
277
+ name: "Unexpected Event",
278
+ message: `Unexpected event: ${e.data.type}`
279
+ },
280
+ "Unexpected Event"
281
+ );
223
282
  await done();
224
- break;
225
- }
226
- case "mock:invalidate":
227
- mocker.invalidate();
228
- break;
229
- case "unmock":
230
- await mocker.unmock(e.data);
231
- break;
232
- case "mock":
233
- await mocker.mock(e.data);
234
- break;
235
- case "mock-factory:error":
236
- case "mock-factory:response":
237
- break;
238
- default: {
239
- e.data;
240
- await client.rpc.onUnhandledError({
241
- name: "Unexpected Event",
242
- message: `Unexpected event: ${e.data.type}`
243
- }, "Unexpected Event");
244
- await done();
283
+ }
245
284
  }
246
285
  }
247
- });
248
- if (testFiles.length)
286
+ );
287
+ if (testFiles.length) {
249
288
  await createTesters(testFiles);
289
+ }
250
290
  });
251
291
  async function createTesters(testFiles) {
252
292
  runningFiles.clear();
@@ -261,25 +301,22 @@ async function createTesters(testFiles) {
261
301
  iframes.forEach((iframe) => iframe.remove());
262
302
  iframes.clear();
263
303
  if (config.isolate === false) {
264
- const iframe = createIframe(
265
- container,
266
- ID_ALL
267
- );
304
+ const iframe = createIframe(container, ID_ALL);
268
305
  await setIframeViewport(iframe, width, height);
269
306
  } else {
270
307
  for (const file of testFiles) {
271
- const iframe = createIframe(
272
- container,
273
- file
274
- );
308
+ const iframe = createIframe(container, file);
275
309
  await setIframeViewport(iframe, width, height);
276
310
  await new Promise((resolve) => {
277
- channel.addEventListener("message", function handler(e) {
278
- if (e.data.type === "done" || e.data.type === "error") {
279
- channel.removeEventListener("message", handler);
280
- resolve();
311
+ channel.addEventListener(
312
+ "message",
313
+ function handler(e) {
314
+ if (e.data.type === "done" || e.data.type === "error") {
315
+ channel.removeEventListener("message", handler);
316
+ resolve();
317
+ }
281
318
  }
282
- });
319
+ );
283
320
  });
284
321
  }
285
322
  }
@@ -4,6 +4,7 @@ function __vite__mapDeps(indexes) {
4
4
  }
5
5
  return indexes.map((i) => __vite__mapDeps.viteFileDeps[i])
6
6
  }
7
+ import { getSafeTimers } from "/__virtual_vitest__?id=vitest%2Futils";
7
8
  (function polyfill() {
8
9
  const relList = document.createElement("link").relList;
9
10
  if (relList && relList.supports && relList.supports("modulepreload")) {
@@ -438,28 +439,44 @@ const __vitePreload = function preload(baseModule, deps, importerUrl) {
438
439
  };
439
440
  async function importId(id) {
440
441
  const name = `/@id/${id}`;
441
- return getBrowserState().wrapModule(() => __vitePreload(() => import(name), true ? __vite__mapDeps([]) : void 0));
442
+ return (/* @__PURE__ */ getBrowserState()).wrapModule(() => __vitePreload(() => import(name), true ? __vite__mapDeps([]) : void 0));
442
443
  }
443
444
  function getConfig() {
444
- return getBrowserState().config;
445
+ return (/* @__PURE__ */ getBrowserState()).config;
445
446
  }
447
+ // @__NO_SIDE_EFFECTS__
446
448
  function getBrowserState() {
447
449
  return window.__vitest_browser_runner__;
448
450
  }
449
- const channel = new BroadcastChannel(`vitest:${getBrowserState().contextId}`);
451
+ // @__NO_SIDE_EFFECTS__
452
+ function getWorkerState() {
453
+ const state = window.__vitest_worker__;
454
+ if (!state) {
455
+ throw new Error("Worker state is not found. This is an issue with Vitest. Please, open an issue.");
456
+ }
457
+ return state;
458
+ }
459
+ const channel = new BroadcastChannel(
460
+ `vitest:${(/* @__PURE__ */ getBrowserState()).contextId}`
461
+ );
450
462
  function waitForChannel(event) {
451
463
  return new Promise((resolve2) => {
452
- channel.addEventListener("message", (e) => {
453
- var _a;
454
- if (((_a = e.data) == null ? void 0 : _a.type) === event)
455
- resolve2();
456
- }, { once: true });
464
+ channel.addEventListener(
465
+ "message",
466
+ (e) => {
467
+ var _a;
468
+ if (((_a = e.data) == null ? void 0 : _a.type) === event) {
469
+ resolve2();
470
+ }
471
+ },
472
+ { once: true }
473
+ );
457
474
  });
458
475
  }
459
- const PAGE_TYPE = getBrowserState().type;
476
+ const PAGE_TYPE = (/* @__PURE__ */ getBrowserState()).type;
460
477
  const PORT = location.port;
461
478
  const HOST = [location.hostname, PORT].filter(Boolean).join(":");
462
- const SESSION_ID = PAGE_TYPE === "orchestrator" ? getBrowserState().contextId : crypto.randomUUID();
479
+ const SESSION_ID = PAGE_TYPE === "orchestrator" ? (/* @__PURE__ */ getBrowserState()).contextId : crypto.randomUUID();
463
480
  const ENTRY_URL = `${location.protocol === "https:" ? "wss:" : "ws:"}//${HOST}/__vitest_browser_api__?type=${PAGE_TYPE}&sessionId=${SESSION_ID}`;
464
481
  let setCancel = (_) => {
465
482
  };
@@ -476,43 +493,41 @@ function createClient() {
476
493
  waitForConnection
477
494
  };
478
495
  let onMessage;
479
- ctx.rpc = createBirpc({
480
- onCancel: setCancel,
481
- async startMocking(id) {
482
- if (typeof __vitest_mocker__ === "undefined")
483
- throw new Error(`Cannot mock modules in the orchestrator process`);
484
- const mocker = __vitest_mocker__;
485
- const exports = await mocker.resolve(id);
486
- return Object.keys(exports);
496
+ ctx.rpc = createBirpc(
497
+ {
498
+ onCancel: setCancel,
499
+ async createTesters(files) {
500
+ var _a, _b;
501
+ if (PAGE_TYPE !== "orchestrator") {
502
+ return;
503
+ }
504
+ (_b = (_a = /* @__PURE__ */ getBrowserState()).createTesters) == null ? void 0 : _b.call(_a, files);
505
+ }
487
506
  },
488
- async createTesters(files) {
489
- var _a, _b;
490
- if (PAGE_TYPE !== "orchestrator")
491
- return;
492
- (_b = (_a = getBrowserState()).createTesters) == null ? void 0 : _b.call(_a, files);
493
- }
494
- }, {
495
- post: (msg) => ctx.ws.send(msg),
496
- on: (fn) => onMessage = fn,
497
- serialize: (e) => stringify(e, (_, v) => {
498
- if (v instanceof Error) {
499
- return {
500
- name: v.name,
501
- message: v.message,
502
- stack: v.stack
503
- };
507
+ {
508
+ post: (msg) => ctx.ws.send(msg),
509
+ on: (fn) => onMessage = fn,
510
+ serialize: (e) => stringify(e, (_, v) => {
511
+ if (v instanceof Error) {
512
+ return {
513
+ name: v.name,
514
+ message: v.message,
515
+ stack: v.stack
516
+ };
517
+ }
518
+ return v;
519
+ }),
520
+ deserialize: parse,
521
+ onTimeoutError(functionName) {
522
+ throw new Error(`[vitest-browser]: Timeout calling "${functionName}"`);
504
523
  }
505
- return v;
506
- }),
507
- deserialize: parse,
508
- onTimeoutError(functionName) {
509
- throw new Error(`[vitest-browser]: Timeout calling "${functionName}"`);
510
524
  }
511
- });
525
+ );
512
526
  let openPromise;
513
527
  function reconnect(reset = false) {
514
- if (reset)
528
+ if (reset) {
515
529
  tries = reconnectTries;
530
+ }
516
531
  ctx.ws = new WebSocket(ENTRY_URL);
517
532
  registerWS();
518
533
  }
@@ -520,10 +535,15 @@ function createClient() {
520
535
  openPromise = new Promise((resolve2, reject) => {
521
536
  var _a, _b;
522
537
  const timeout = (_b = (_a = setTimeout(() => {
523
- reject(new Error(`Cannot connect to the server in ${connectTimeout / 1e3} seconds`));
538
+ reject(
539
+ new Error(
540
+ `Cannot connect to the server in ${connectTimeout / 1e3} seconds`
541
+ )
542
+ );
524
543
  }, connectTimeout)) == null ? void 0 : _a.unref) == null ? void 0 : _b.call(_a);
525
- if (ctx.ws.OPEN === ctx.ws.readyState)
544
+ if (ctx.ws.OPEN === ctx.ws.readyState) {
526
545
  resolve2();
546
+ }
527
547
  ctx.ws.addEventListener("open", () => {
528
548
  tries = reconnectTries;
529
549
  resolve2();
@@ -535,8 +555,9 @@ function createClient() {
535
555
  });
536
556
  ctx.ws.addEventListener("close", () => {
537
557
  tries -= 1;
538
- if (tries > 0)
558
+ if (tries > 0) {
539
559
  setTimeout(reconnect, reconnectInterval);
560
+ }
540
561
  });
541
562
  }
542
563
  registerWS();
@@ -569,18 +590,20 @@ function withSafeTimers(getTimers, fn) {
569
590
  }
570
591
  const promises = /* @__PURE__ */ new Set();
571
592
  async function rpcDone() {
572
- if (!promises.size)
593
+ if (!promises.size) {
573
594
  return;
595
+ }
574
596
  const awaitable = Array.from(promises);
575
597
  return Promise.all(awaitable);
576
598
  }
577
- function createSafeRpc(client2, getTimers) {
599
+ function createSafeRpc(client2) {
578
600
  return new Proxy(client2.rpc, {
579
601
  get(target, p, handler) {
580
- if (p === "then")
602
+ if (p === "then") {
581
603
  return;
604
+ }
582
605
  const sendCall = get(target, p, handler);
583
- const safeSendCall = (...args) => withSafeTimers(getTimers, async () => {
606
+ const safeSendCall = (...args) => withSafeTimers(getSafeTimers, async () => {
584
607
  const result = sendCall(...args);
585
608
  promises.add(result);
586
609
  try {
@@ -594,25 +617,22 @@ function createSafeRpc(client2, getTimers) {
594
617
  }
595
618
  });
596
619
  }
597
- async function loadSafeRpc(client2) {
598
- const { getSafeTimers } = await importId("vitest/utils");
599
- return createSafeRpc(client2, getSafeTimers);
600
- }
601
620
  function rpc() {
602
621
  return globalThis.__vitest_worker__.rpc;
603
622
  }
604
623
  export {
605
624
  __vitePreload as _,
606
- channel as a,
625
+ client as a,
607
626
  getConfig as b,
608
- client as c,
627
+ channel as c,
609
628
  rpcDone as d,
610
629
  rpc as e,
611
630
  extname as f,
612
631
  getBrowserState as g,
632
+ createSafeRpc as h,
613
633
  importId as i,
614
634
  join as j,
615
- loadSafeRpc as l,
635
+ getWorkerState as k,
616
636
  onCancel as o,
617
637
  relative as r,
618
638
  waitForChannel as w