@vitest/browser 4.1.8 → 4.1.9

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.
@@ -4,7 +4,7 @@
4
4
  "name": "utils"
5
5
  },
6
6
  "orchestrator.html": {
7
- "file": "__vitest_browser__/orchestrator-B-wB8WWP.js",
7
+ "file": "__vitest_browser__/orchestrator-KVYrTcFi.js",
8
8
  "name": "orchestrator",
9
9
  "src": "orchestrator.html",
10
10
  "isEntry": true,
@@ -13,7 +13,7 @@
13
13
  ]
14
14
  },
15
15
  "tester/tester.html": {
16
- "file": "__vitest_browser__/tester-DQAp97S5.js",
16
+ "file": "__vitest_browser__/tester-BJtsJFpD.js",
17
17
  "name": "tester",
18
18
  "src": "tester/tester.html",
19
19
  "isEntry": true,
@@ -10,6 +10,8 @@ class IframeOrchestrator {
10
10
  cancelled = false;
11
11
  recreateNonIsolatedIframe = false;
12
12
  iframes = /* @__PURE__ */ new Map();
13
+ readyIframes = /* @__PURE__ */ new Set();
14
+ readyWaiters = /* @__PURE__ */ new Map();
13
15
  eventTarget = new EventTarget();
14
16
  traces;
15
17
  constructor() {
@@ -27,6 +29,9 @@ class IframeOrchestrator {
27
29
  "message",
28
30
  (e) => this.onGlobalChannelEvent(e)
29
31
  );
32
+ void client.waitForConnection().then(() => client.rpc.onOrchestratorReady()).catch((error) => {
33
+ debug("failed to notify orchestrator readiness", error);
34
+ });
30
35
  }
31
36
  async createTesters(options) {
32
37
  await this.traces.waitInit();
@@ -63,6 +68,8 @@ class IframeOrchestrator {
63
68
  }
64
69
  this.iframes.forEach((iframe) => iframe.remove());
65
70
  this.iframes.clear();
71
+ this.readyIframes.clear();
72
+ this.readyWaiters.clear();
66
73
  for (let i = 0; i < options.files.length; i++) {
67
74
  if (this.cancelled) {
68
75
  await endSpan();
@@ -104,8 +111,7 @@ class IframeOrchestrator {
104
111
  async runNonIsolatedTests(container, options, startTime, otelContext) {
105
112
  if (this.recreateNonIsolatedIframe) {
106
113
  this.recreateNonIsolatedIframe = false;
107
- this.iframes.get(ID_ALL).remove();
108
- this.iframes.delete(ID_ALL);
114
+ this.removeIframe(ID_ALL);
109
115
  debug("recreate non-isolated iframe");
110
116
  }
111
117
  if (!this.iframes.has(ID_ALL)) {
@@ -131,8 +137,7 @@ class IframeOrchestrator {
131
137
  const { width, height } = config.browser.viewport;
132
138
  const file = spec.filepath;
133
139
  if (this.iframes.has(file)) {
134
- this.iframes.get(file).remove();
135
- this.iframes.delete(file);
140
+ this.removeIframe(file);
136
141
  }
137
142
  const iframe = await this.prepareIframe(
138
143
  container,
@@ -181,12 +186,12 @@ Expected: ${iframe.src}`
181
186
  }
182
187
  } else {
183
188
  this.iframes.set(iframeId, iframe);
184
- this.sendEventToIframe({
189
+ this.waitForReady(iframeId).then(() => this.sendEventToIframe({
185
190
  event: "prepare",
186
191
  iframeId,
187
192
  startTime,
188
193
  otelCarrier: this.traces.getContextCarrier(otelContext)
189
- }).then(resolve, (error) => reject(this.dispatchIframeError(error)));
194
+ })).then(resolve, (error) => reject(this.dispatchIframeError(error)));
190
195
  }
191
196
  };
192
197
  iframe.onerror = (e) => {
@@ -201,6 +206,29 @@ Expected: ${iframe.src}`
201
206
  });
202
207
  return iframe;
203
208
  }
209
+ markReady(iframeId) {
210
+ this.readyIframes.add(iframeId);
211
+ const waiter = this.readyWaiters.get(iframeId);
212
+ if (waiter) {
213
+ this.readyWaiters.delete(iframeId);
214
+ waiter();
215
+ }
216
+ }
217
+ waitForReady(iframeId) {
218
+ if (this.readyIframes.has(iframeId)) {
219
+ return Promise.resolve();
220
+ }
221
+ return new Promise((resolve) => {
222
+ this.readyWaiters.set(iframeId, resolve);
223
+ });
224
+ }
225
+ removeIframe(iframeId) {
226
+ const iframe = this.iframes.get(iframeId);
227
+ this.iframes.delete(iframeId);
228
+ this.readyIframes.delete(iframeId);
229
+ this.readyWaiters.delete(iframeId);
230
+ iframe == null ? void 0 : iframe.remove();
231
+ }
204
232
  loggedIframe = /* @__PURE__ */ new WeakSet();
205
233
  createWarningMessage(iframeId, location) {
206
234
  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.
@@ -257,6 +285,10 @@ If you are using a framework that manipulates browser history (like React Router
257
285
  async onIframeEvent(e) {
258
286
  debug("iframe event", JSON.stringify(e.data));
259
287
  switch (e.data.event) {
288
+ case "ready": {
289
+ this.markReady(e.data.iframeId);
290
+ break;
291
+ }
260
292
  case "viewport": {
261
293
  const { width, height, iframeId: id } = e.data;
262
294
  const iframe = this.iframes.get(id);
@@ -2151,6 +2151,10 @@ const commands = new CommandsManager();
2151
2151
  getBrowserState().commands = commands;
2152
2152
  getBrowserState().activeTraceTaskIds = /* @__PURE__ */ new Set();
2153
2153
  getBrowserState().iframeId = iframeId;
2154
+ channel.postMessage({
2155
+ event: "ready",
2156
+ iframeId
2157
+ });
2154
2158
  let contextSwitched = false;
2155
2159
  async function prepareTestEnvironment(options) {
2156
2160
  debug == null ? void 0 : debug("trying to resolve the runner");
@@ -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-B-wB8WWP.js"></script>
29
+ <script type="module" crossorigin src="/__vitest_browser__/orchestrator-KVYrTcFi.js"></script>
30
30
  <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-BsFW67Gk.js">
31
31
  </head>
32
32
  <body>
@@ -5,7 +5,7 @@
5
5
  <link rel="icon" href="{__VITEST_FAVICON__}" type="image/svg+xml">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Vitest Browser Tester</title>
8
- <script type="module" crossorigin src="/__vitest_browser__/tester-DQAp97S5.js"></script>
8
+ <script type="module" crossorigin src="/__vitest_browser__/tester-BJtsJFpD.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-BsFW67Gk.js">
10
10
  </head>
11
11
  <body>
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ import { PNG } from 'pngjs';
18
18
  import { diff } from '@blazediff/core';
19
19
  import { WebSocketServer } from 'ws';
20
20
 
21
- var version = "4.1.8";
21
+ var version = "4.1.9";
22
22
 
23
23
  const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
24
24
  function normalizeWindowsPath(input = "") {
@@ -3024,7 +3024,8 @@ function setupBrowserRpc(globalServer, defaultMockerRegistry) {
3024
3024
  }
3025
3025
  if (type === "orchestrator") {
3026
3026
  const session = sessions.getSession(sessionId);
3027
- // it's possible the session was already resolved by the preview provider
3027
+ // it's possible the session was already resolved by the preview provider,
3028
+ // but we still mark the websocket connection when the page reconnects
3028
3029
  session?.connected();
3029
3030
  }
3030
3031
  const project = vitest.getProjectByName(projectName);
@@ -3033,7 +3034,7 @@ function setupBrowserRpc(globalServer, defaultMockerRegistry) {
3033
3034
  }
3034
3035
  wss.handleUpgrade(request, socket, head, (ws) => {
3035
3036
  wss.emit("connection", ws, request);
3036
- const { rpc, offCancel } = setupClient(project, rpcId, ws);
3037
+ const { rpc, offCancel } = setupClient(project, rpcId, ws, { sessionId });
3037
3038
  const state = project.browser.state;
3038
3039
  const clients = type === "tester" ? state.testers : state.orchestrators;
3039
3040
  clients.set(rpcId, rpc);
@@ -3072,10 +3073,14 @@ function setupBrowserRpc(globalServer, defaultMockerRegistry) {
3072
3073
  throw new Error(`Cannot use CDP because browser API write or exec operations are disabled. See https://vitest.dev/config/browser/api.`);
3073
3074
  }
3074
3075
  }
3075
- function setupClient(project, rpcId, ws) {
3076
+ function setupClient(project, rpcId, ws, options) {
3076
3077
  const mockResolver = new ServerMockResolver(globalServer.vite, { moduleDirectories: project.config?.deps?.moduleDirectories });
3077
3078
  const mocker = project.browser?.provider.mocker;
3078
3079
  const rpc = createBirpc({
3080
+ onOrchestratorReady() {
3081
+ const sessions = vitest._browserSessions;
3082
+ sessions.getSession(options.sessionId)?.ready();
3083
+ },
3079
3084
  async onUnhandledError(error, type) {
3080
3085
  if (error && typeof error === "object") {
3081
3086
  const _error = error;
package/dist/types.d.ts CHANGED
@@ -11,6 +11,7 @@ export interface WebSocketBrowserHandlers {
11
11
  onTaskArtifactRecord: <Artifact extends TestArtifact>(testId: string, artifact: Artifact) => Promise<Artifact>;
12
12
  onTaskUpdate: (method: TestExecutionMethod, packs: TaskResultPack[], events: TaskEventPack[]) => void;
13
13
  onAfterSuiteRun: (meta: AfterSuiteRunMeta) => void;
14
+ onOrchestratorReady: () => void;
14
15
  cancelCurrentRun: (reason: CancelReason) => void;
15
16
  getCountOfFailedTests: () => number;
16
17
  readSnapshotFile: (id: string) => Promise<string | null>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/browser",
3
3
  "type": "module",
4
- "version": "4.1.8",
4
+ "version": "4.1.9",
5
5
  "description": "Browser running for Vitest",
6
6
  "license": "MIT",
7
7
  "funding": "https://opencollective.com/vitest",
@@ -57,7 +57,7 @@
57
57
  "providers"
58
58
  ],
59
59
  "peerDependencies": {
60
- "vitest": "4.1.8"
60
+ "vitest": "4.1.9"
61
61
  },
62
62
  "dependencies": {
63
63
  "@blazediff/core": "1.9.1",
@@ -66,8 +66,8 @@
66
66
  "sirv": "^3.0.2",
67
67
  "tinyrainbow": "^3.1.0",
68
68
  "ws": "^8.19.0",
69
- "@vitest/mocker": "4.1.8",
70
- "@vitest/utils": "4.1.8"
69
+ "@vitest/utils": "4.1.9",
70
+ "@vitest/mocker": "4.1.9"
71
71
  },
72
72
  "devDependencies": {
73
73
  "@opentelemetry/api": "^1.9.0",
@@ -79,8 +79,8 @@
79
79
  "ivya": "^1.8.0",
80
80
  "mime": "^4.1.0",
81
81
  "pathe": "^2.0.3",
82
- "vitest": "4.1.8",
83
- "@vitest/runner": "4.1.8"
82
+ "vitest": "4.1.9",
83
+ "@vitest/runner": "4.1.9"
84
84
  },
85
85
  "scripts": {
86
86
  "typecheck": "tsc -p ./src/client/tsconfig.json --noEmit",