@vitest/browser 5.0.0-beta.3 → 5.0.0-beta.5

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.
@@ -5,26 +5,26 @@
5
5
  "src": "../../../../node_modules/.pnpm/rrweb-snapshot@2.0.0-alpha.20_patch_hash=d11ec9bd9b66247ba493ab5fd117fbf0b4cb6e5d0a6a7c600d1d844bfa3d3044/node_modules/rrweb-snapshot/dist/rrweb-snapshot.js",
6
6
  "isDynamicEntry": true
7
7
  },
8
- "_defineProperty-C3k2g8Sk.js": {
9
- "file": "__vitest_browser__/defineProperty-C3k2g8Sk.js",
8
+ "_defineProperty-WHpdAQXR.js": {
9
+ "file": "__vitest_browser__/defineProperty-WHpdAQXR.js",
10
10
  "name": "defineProperty"
11
11
  },
12
12
  "orchestrator.html": {
13
- "file": "__vitest_browser__/orchestrator-B44yH1M4.js",
13
+ "file": "__vitest_browser__/orchestrator-bDJB3Bid.js",
14
14
  "name": "orchestrator",
15
15
  "src": "orchestrator.html",
16
16
  "isEntry": true,
17
17
  "imports": [
18
- "_defineProperty-C3k2g8Sk.js"
18
+ "_defineProperty-WHpdAQXR.js"
19
19
  ]
20
20
  },
21
21
  "tester/tester.html": {
22
- "file": "__vitest_browser__/tester-Byk-s_d6.js",
22
+ "file": "__vitest_browser__/tester-C1kIlbPd.js",
23
23
  "name": "tester",
24
24
  "src": "tester/tester.html",
25
25
  "isEntry": true,
26
26
  "imports": [
27
- "_defineProperty-C3k2g8Sk.js"
27
+ "_defineProperty-WHpdAQXR.js"
28
28
  ],
29
29
  "dynamicImports": [
30
30
  "../../../../node_modules/.pnpm/rrweb-snapshot@2.0.0-alpha.20_patch_hash=d11ec9bd9b66247ba493ab5fd117fbf0b4cb6e5d0a6a7c600d1d844bfa3d3044/node_modules/rrweb-snapshot/dist/rrweb-snapshot.js"
@@ -122,6 +122,49 @@ var relative = function(from, to) {
122
122
  return [..._from.map(() => ".."), ..._to].join("/");
123
123
  };
124
124
 
125
+ //#endregion
126
+ //#region ../vitest/src/utils/tasks.ts
127
+ /* @__NO_SIDE_EFFECTS__ */
128
+ function getNames(task) {
129
+ const names = [task.name];
130
+ let current = task;
131
+ while (current === null || current === void 0 ? void 0 : current.suite) {
132
+ current = current.suite;
133
+ if (current === null || current === void 0 ? void 0 : current.name) names.unshift(current.name);
134
+ }
135
+ if (current !== task.file) names.unshift(task.file.name);
136
+ return names;
137
+ }
138
+ /* @__NO_SIDE_EFFECTS__ */
139
+ function getTestName(task, separator = " > ") {
140
+ return (/* @__PURE__ */ getNames(task)).slice(1).join(separator);
141
+ }
142
+ /**
143
+ * Generate a unique ID for a file based on its path and project name
144
+ * @param file File relative to the root of the project to keep ID the same between different machines
145
+ * @param projectName The name of the test project
146
+ */
147
+ /* @__NO_SIDE_EFFECTS__ */
148
+ function generateFileHash(file, projectName, meta) {
149
+ return /* @__PURE__ */ generateHash([
150
+ file,
151
+ projectName || "",
152
+ (meta === null || meta === void 0 ? void 0 : meta.typecheck) ? "__typecheck__" : "",
153
+ (meta === null || meta === void 0 ? void 0 : meta.__vitest_label__) || ""
154
+ ].join("\0"));
155
+ }
156
+ /* @__NO_SIDE_EFFECTS__ */
157
+ function generateHash(str) {
158
+ let hash = 0;
159
+ if (str.length === 0) return `${hash}`;
160
+ for (let i = 0; i < str.length; i++) {
161
+ const char = str.charCodeAt(i);
162
+ hash = (hash << 5) - hash + char;
163
+ hash = hash & hash;
164
+ }
165
+ return `${hash}`;
166
+ }
167
+
125
168
  //#endregion
126
169
  //#region \0vite/preload-helper.js
127
170
  var scriptRel = "modulepreload";
@@ -264,4 +307,4 @@ function _defineProperty(e, r, t) {
264
307
  }
265
308
 
266
309
  //#endregion
267
- export { moduleRunner as a, relative as c, getWorkerState as i, resolve as l, getBrowserState as n, now as o, getConfig as r, __vitePreload as s, _defineProperty as t };
310
+ export { moduleRunner as a, generateFileHash as c, resolve as d, getWorkerState as i, getTestName as l, getBrowserState as n, now as o, getConfig as r, __vitePreload as s, _defineProperty as t, relative as u };
@@ -1,4 +1,4 @@
1
- import { c as relative, n as getBrowserState, r as getConfig, t as _defineProperty } from "./defineProperty-C3k2g8Sk.js";
1
+ import { c as generateFileHash, n as getBrowserState, r as getConfig, t as _defineProperty, u as relative } from "./defineProperty-WHpdAQXR.js";
2
2
  import { channel, client, globalChannel } from "@vitest/browser/client";
3
3
  import { Traces } from "vitest/internal/traces";
4
4
 
@@ -16,6 +16,8 @@ var IframeOrchestrator = class {
16
16
  _defineProperty(this, "cancelled", false);
17
17
  _defineProperty(this, "recreateNonIsolatedIframe", false);
18
18
  _defineProperty(this, "iframes", /* @__PURE__ */ new Map());
19
+ _defineProperty(this, "readyIframes", /* @__PURE__ */ new Set());
20
+ _defineProperty(this, "readyWaiters", /* @__PURE__ */ new Map());
19
21
  _defineProperty(this, "eventTarget", new EventTarget());
20
22
  _defineProperty(this, "traces", void 0);
21
23
  _defineProperty(this, "loggedIframe", /* @__PURE__ */ new WeakSet());
@@ -28,6 +30,9 @@ var IframeOrchestrator = class {
28
30
  });
29
31
  channel.addEventListener("message", (e) => this.onIframeEvent(e));
30
32
  globalChannel.addEventListener("message", (e) => this.onGlobalChannelEvent(e));
33
+ client.waitForConnection().then(() => client.rpc.onOrchestratorReady()).catch((error) => {
34
+ debug("failed to notify orchestrator readiness", error);
35
+ });
31
36
  }
32
37
  async createTesters(options) {
33
38
  await this.traces.waitInit();
@@ -54,6 +59,8 @@ var IframeOrchestrator = class {
54
59
  }
55
60
  this.iframes.forEach((iframe) => iframe.remove());
56
61
  this.iframes.clear();
62
+ this.readyIframes.clear();
63
+ this.readyWaiters.clear();
57
64
  for (let i = 0; i < options.files.length; i++) {
58
65
  if (this.cancelled) {
59
66
  await endSpan();
@@ -85,8 +92,7 @@ var IframeOrchestrator = class {
85
92
  async runNonIsolatedTests(container, options, startTime, otelContext) {
86
93
  if (this.recreateNonIsolatedIframe) {
87
94
  this.recreateNonIsolatedIframe = false;
88
- this.iframes.get(ID_ALL).remove();
89
- this.iframes.delete(ID_ALL);
95
+ this.removeIframe(ID_ALL);
90
96
  debug("recreate non-isolated iframe");
91
97
  }
92
98
  if (!this.iframes.has(ID_ALL)) {
@@ -101,17 +107,16 @@ var IframeOrchestrator = class {
101
107
  iframeId: ID_ALL,
102
108
  files: options.files,
103
109
  method: options.method,
104
- context: options.providedContext
110
+ context: options.providedContext,
111
+ concurrencyId: options.concurrencyId,
112
+ workerId: options.workerId
105
113
  });
106
114
  debug("finished running tests", options.files.join(", "));
107
115
  }
108
116
  async runIsolatedTestInIframe(container, spec, options, startTime, otelContext) {
109
117
  const { width, height } = getConfig().browser.viewport;
110
118
  const file = spec.filepath;
111
- if (this.iframes.has(file)) {
112
- this.iframes.get(file).remove();
113
- this.iframes.delete(file);
114
- }
119
+ if (this.iframes.has(file)) this.removeIframe(file);
115
120
  await this.prepareIframe(container, file, startTime, otelContext);
116
121
  await setIframeViewport(width, height);
117
122
  await this.sendEventToIframe({
@@ -119,7 +124,9 @@ var IframeOrchestrator = class {
119
124
  files: [spec],
120
125
  method: options.method,
121
126
  iframeId: file,
122
- context: options.providedContext
127
+ context: options.providedContext,
128
+ concurrencyId: options.concurrencyId,
129
+ workerId: options.workerId
123
130
  });
124
131
  await this.sendEventToIframe({
125
132
  event: "cleanup",
@@ -147,12 +154,12 @@ Received URL: ${href || "unknown due to CORS"}\nExpected: ${iframe.src}`)));
147
154
  else this.warnReload(iframe, iframeId);
148
155
  } else {
149
156
  this.iframes.set(iframeId, iframe);
150
- this.sendEventToIframe({
157
+ this.waitForReady(iframeId).then(() => this.sendEventToIframe({
151
158
  event: "prepare",
152
159
  iframeId,
153
160
  startTime,
154
161
  otelCarrier: this.traces.getContextCarrier(otelContext)
155
- }).then(resolve, (error) => reject(this.dispatchIframeError(error)));
162
+ })).then(resolve, (error) => reject(this.dispatchIframeError(error)));
156
163
  }
157
164
  };
158
165
  iframe.onerror = (e) => {
@@ -163,6 +170,27 @@ Received URL: ${href || "unknown due to CORS"}\nExpected: ${iframe.src}`)));
163
170
  });
164
171
  return iframe;
165
172
  }
173
+ markReady(iframeId) {
174
+ this.readyIframes.add(iframeId);
175
+ const waiter = this.readyWaiters.get(iframeId);
176
+ if (waiter) {
177
+ this.readyWaiters.delete(iframeId);
178
+ waiter();
179
+ }
180
+ }
181
+ waitForReady(iframeId) {
182
+ if (this.readyIframes.has(iframeId)) return Promise.resolve();
183
+ return new Promise((resolve) => {
184
+ this.readyWaiters.set(iframeId, resolve);
185
+ });
186
+ }
187
+ removeIframe(iframeId) {
188
+ const iframe = this.iframes.get(iframeId);
189
+ this.iframes.delete(iframeId);
190
+ this.readyIframes.delete(iframeId);
191
+ this.readyWaiters.delete(iframeId);
192
+ iframe === null || iframe === void 0 || iframe.remove();
193
+ }
166
194
  createWarningMessage(iframeId, location) {
167
195
  return `The iframe${iframeId === ID_ALL ? "" : ` for "${iframeId}"`} was reloaded ${location}. This can lead to unexpected behavior during tests, duplicated test results or tests hanging.\n\nMake sure that your test code does not change window's location, submit forms without preventing default behavior, or imports unoptimized dependencies.\nIf you are using a framework that manipulates browser history (like React Router), consider using memory-based routing for tests. If you think this is a false positive, open an issue with a reproduction: https://github.com/vitest-dev/vitest/issues/new`;
168
196
  }
@@ -188,7 +216,7 @@ Received URL: ${href || "unknown due to CORS"}\nExpected: ${iframe.src}`)));
188
216
  }
189
217
  createTestIframe(iframeId) {
190
218
  const iframe = document.createElement("iframe");
191
- const src = `/?sessionId=${(/* @__PURE__ */ getBrowserState()).sessionId}&iframeId=${iframeId}`;
219
+ const src = `/?sessionId=${(/* @__PURE__ */ getBrowserState()).sessionId}&iframeId=${encodeURIComponent(iframeId)}`;
192
220
  const config = getConfig();
193
221
  iframe.setAttribute("loading", "eager");
194
222
  iframe.setAttribute("src", src);
@@ -222,6 +250,9 @@ Received URL: ${href || "unknown due to CORS"}\nExpected: ${iframe.src}`)));
222
250
  async onIframeEvent(e) {
223
251
  debug("iframe event", JSON.stringify(e.data));
224
252
  switch (e.data.event) {
253
+ case "ready":
254
+ this.markReady(e.data.iframeId);
255
+ break;
225
256
  case "viewport": {
226
257
  const { width, height, iframeId: id } = e.data;
227
258
  if (!this.iframes.get(id)) {
@@ -300,29 +331,11 @@ async function getContainer(config) {
300
331
  }
301
332
  function generateFileId(file) {
302
333
  const config = getConfig();
303
- return generateFileHash(relative(config.root, file), config.name, {
334
+ return /* @__PURE__ */ generateFileHash(relative(config.root, file), config.name, {
304
335
  typecheck: config.pool === "typescript",
305
336
  __vitest_label__: config.mergeReportsLabel
306
337
  });
307
338
  }
308
- function generateFileHash(file, projectName, meta) {
309
- return generateHash([
310
- file,
311
- projectName || "",
312
- (meta === null || meta === void 0 ? void 0 : meta.typecheck) ? "__typecheck__" : "",
313
- (meta === null || meta === void 0 ? void 0 : meta.__vitest_label__) || ""
314
- ].join("\0"));
315
- }
316
- function generateHash(str) {
317
- let hash = 0;
318
- if (str.length === 0) return `${hash}`;
319
- for (let i = 0; i < str.length; i++) {
320
- const char = str.charCodeAt(i);
321
- hash = (hash << 5) - hash + char;
322
- hash = hash & hash;
323
- }
324
- return `${hash}`;
325
- }
326
339
  async function setIframeViewport(width, height) {
327
340
  const ui = /* @__PURE__ */ getUiAPI();
328
341
  if (ui) await ui.setIframeViewport(width, height);