@vitest/browser 3.0.0-beta.2 → 3.0.0-beta.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.
@@ -23,7 +23,7 @@
23
23
  })();
24
24
  </script>
25
25
  <!-- !LOAD_METADATA! -->
26
- <script type="module" src="./assets/index-BgsOOCCp.js"></script>
26
+ <script type="module" src="./assets/index-JmEkKNR0.js"></script>
27
27
  <link rel="stylesheet" href="./assets/index-D1v_Nqq1.css">
28
28
  </head>
29
29
  <body>
@@ -26,8 +26,7 @@ class IframeOrchestrator {
26
26
  __publicField(this, "runningFiles", /* @__PURE__ */ new Set());
27
27
  __publicField(this, "iframes", /* @__PURE__ */ new Map());
28
28
  }
29
- async init() {
30
- const testFiles = getBrowserState().files;
29
+ async init(testFiles) {
31
30
  debug("test files", testFiles.join(", "));
32
31
  this.runningFiles.clear();
33
32
  testFiles.forEach((file) => this.runningFiles.add(file));
@@ -45,6 +44,7 @@ class IframeOrchestrator {
45
44
  this.runningFiles.clear();
46
45
  testFiles.forEach((file) => this.runningFiles.add(file));
47
46
  const config = getConfig();
47
+ debug("create testers", testFiles.join(", "));
48
48
  const container = await getContainer(config);
49
49
  if (config.browser.ui) {
50
50
  container.className = "absolute origin-top mt-[8px]";
@@ -55,6 +55,7 @@ class IframeOrchestrator {
55
55
  this.iframes.forEach((iframe) => iframe.remove());
56
56
  this.iframes.clear();
57
57
  if (config.isolate === false) {
58
+ debug("create iframe", ID_ALL);
58
59
  const iframe = this.createIframe(container, ID_ALL);
59
60
  await setIframeViewport(iframe, width, height);
60
61
  return;
@@ -64,6 +65,7 @@ class IframeOrchestrator {
64
65
  done();
65
66
  return;
66
67
  }
68
+ debug("create iframe", file);
67
69
  const iframe = this.createIframe(container, file);
68
70
  await setIframeViewport(iframe, width, height);
69
71
  await new Promise((resolve) => {
@@ -88,7 +90,7 @@ class IframeOrchestrator {
88
90
  iframe.setAttribute("loading", "eager");
89
91
  iframe.setAttribute(
90
92
  "src",
91
- `${url.pathname}__vitest_test__/__test__/${getBrowserState().contextId}/${encodeURIComponent(file)}`
93
+ `${url.pathname}__vitest_test__/__test__/${getBrowserState().sessionId}/${encodeURIComponent(file)}`
92
94
  );
93
95
  iframe.setAttribute("data-vitest", "true");
94
96
  iframe.style.border = "none";
@@ -192,7 +194,7 @@ getBrowserState().createTesters = async (files) => {
192
194
  await promiseTesters;
193
195
  };
194
196
  async function done() {
195
- await client.rpc.finishBrowserTests(getBrowserState().contextId);
197
+ await client.rpc.finishBrowserTests(getBrowserState().sessionId);
196
198
  }
197
199
  async function getContainer(config) {
198
200
  if (config.browser.ui) {
@@ -210,7 +212,7 @@ async function getContainer(config) {
210
212
  }
211
213
  client.waitForConnection().then(async () => {
212
214
  const testFiles = getBrowserState().files;
213
- await orchestrator.init();
215
+ await orchestrator.init(testFiles);
214
216
  if (testFiles.length) {
215
217
  await orchestrator.createTesters(testFiles);
216
218
  }
@@ -12140,9 +12140,9 @@ class ModuleMocker {
12140
12140
  return path;
12141
12141
  }
12142
12142
  }
12143
- const versionRegexp$1 = /(\?|&)v=\w{8}/;
12143
+ const versionRegexp = /(\?|&)v=\w{8}/;
12144
12144
  function cleanVersion(url2) {
12145
- return url2.replace(versionRegexp$1, "");
12145
+ return url2.replace(versionRegexp, "");
12146
12146
  }
12147
12147
  const postfixRE = /[?#].*$/;
12148
12148
  function cleanUrl(url2) {
@@ -12231,10 +12231,11 @@ ${keys7}`;
12231
12231
  return await this.startPromise;
12232
12232
  }
12233
12233
  }
12234
- const timestampRegexp = /(\?|&)t=\d{13}/;
12235
- const versionRegexp = /(\?|&)v=\w{8}/;
12234
+ const trailingSeparatorRE = /[?&]$/;
12235
+ const timestampRE = /\bt=\d{13}&?\b/;
12236
+ const versionRE = /\bv=\w{8}&?\b/;
12236
12237
  function cleanQuery(url2) {
12237
- return url2.replace(timestampRegexp, "").replace(versionRegexp, "");
12238
+ return url2.replace(timestampRE, "").replace(versionRE, "").replace(trailingSeparatorRE, "");
12238
12239
  }
12239
12240
  function passthrough() {
12240
12241
  return new Response(null, {
@@ -13595,8 +13596,13 @@ function createBrowserRunner(runnerClass, mocker, state, coverageModule) {
13595
13596
  });
13596
13597
  __publicField(this, "onTaskFinished", async (task) => {
13597
13598
  var _a;
13598
- if (this.config.browser.screenshotFailures && ((_a = task.result) == null ? void 0 : _a.state) === "fail") {
13599
- task.meta.failScreenshotPath = await page.screenshot();
13599
+ if (this.config.browser.screenshotFailures && document.body.clientHeight > 0 && ((_a = task.result) == null ? void 0 : _a.state) === "fail") {
13600
+ const screenshot = await page.screenshot().catch((err) => {
13601
+ console.error("[vitest] Failed to take a screenshot", err);
13602
+ });
13603
+ if (screenshot) {
13604
+ task.meta.failScreenshotPath = screenshot;
13605
+ }
13600
13606
  }
13601
13607
  });
13602
13608
  __publicField(this, "onCancel", (reason) => {
@@ -13636,6 +13642,9 @@ function createBrowserRunner(runnerClass, mocker, state, coverageModule) {
13636
13642
  });
13637
13643
  }
13638
13644
  });
13645
+ __publicField(this, "onCollectStart", (file) => {
13646
+ return rpc$1().onQueued(file);
13647
+ });
13639
13648
  __publicField(this, "onCollected", async (files) => {
13640
13649
  files.forEach((file) => {
13641
13650
  file.prepareDuration = state.durations.prepare;
@@ -24,7 +24,7 @@
24
24
  viteConfig: { __VITEST_VITE_CONFIG__ },
25
25
  files: { __VITEST_FILES__ },
26
26
  type: { __VITEST_TYPE__ },
27
- contextId: { __VITEST_CONTEXT_ID__ },
27
+ sessionId: { __VITEST_SESSION_ID__ },
28
28
  testerId: { __VITEST_TESTER_ID__ },
29
29
  provider: { __VITEST_PROVIDER__ },
30
30
  providedContext: { __VITEST_PROVIDED_CONTEXT__ },
@@ -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-DnP17K36.js"></script>
29
+ <script type="module" crossorigin src="/__vitest_browser__/orchestrator-vOivV83Y.js"></script>
30
30
  <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-Owv5OOOf.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-BdwA4c5U.js"></script>
8
+ <script type="module" crossorigin src="/__vitest_browser__/tester-CDBn6hqf.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-Owv5OOOf.js">
10
10
  </head>
11
11
  <body>
package/dist/client.js CHANGED
@@ -236,7 +236,7 @@ function getBrowserState() {
236
236
  }
237
237
 
238
238
  const channel = new BroadcastChannel(
239
- `vitest:${getBrowserState().contextId}`
239
+ `vitest:${getBrowserState().sessionId}`
240
240
  );
241
241
  const globalChannel = new BroadcastChannel("vitest:global");
242
242
  function waitForChannel(event) {
@@ -256,8 +256,8 @@ function waitForChannel(event) {
256
256
  const PAGE_TYPE = getBrowserState().type;
257
257
  const PORT = location.port;
258
258
  const HOST = [location.hostname, PORT].filter(Boolean).join(":");
259
- const SESSION_ID = PAGE_TYPE === "orchestrator" ? getBrowserState().contextId : getBrowserState().testerId;
260
- const ENTRY_URL = `${location.protocol === "https:" ? "wss:" : "ws:"}//${HOST}/__vitest_browser_api__?type=${PAGE_TYPE}&sessionId=${SESSION_ID}`;
259
+ const RPC_ID = PAGE_TYPE === "orchestrator" ? getBrowserState().sessionId : getBrowserState().testerId;
260
+ const ENTRY_URL = `${location.protocol === "https:" ? "wss:" : "ws:"}//${HOST}/__vitest_browser_api__?type=${PAGE_TYPE}&rpcId=${RPC_ID}&sessionId=${getBrowserState().sessionId}&projectName=${getBrowserState().config.name || ""}`;
261
261
  let setCancel = (_) => {
262
262
  };
263
263
  const onCancel = new Promise((resolve) => {
@@ -353,4 +353,4 @@ function createClient() {
353
353
  }
354
354
  const client = createClient();
355
355
 
356
- export { ENTRY_URL, HOST, PORT, SESSION_ID, channel, client, globalChannel, onCancel, waitForChannel };
356
+ export { ENTRY_URL, HOST, PORT, RPC_ID, channel, client, globalChannel, onCancel, waitForChannel };
package/dist/context.js CHANGED
@@ -117,10 +117,10 @@ function filepath() {
117
117
  return getWorkerState().filepath || getWorkerState().current?.file?.filepath || void 0;
118
118
  }
119
119
  const rpc = () => getWorkerState().rpc;
120
- const contextId = getBrowserState().contextId;
121
- const channel = new BroadcastChannel(`vitest:${contextId}`);
120
+ const sessionId = getBrowserState().sessionId;
121
+ const channel = new BroadcastChannel(`vitest:${sessionId}`);
122
122
  function triggerCommand(command, ...args) {
123
- return rpc().triggerCommand(contextId, command, filepath(), args);
123
+ return rpc().triggerCommand(sessionId, command, filepath(), args);
124
124
  }
125
125
  function createUserEvent(__tl_user_event_base__, options) {
126
126
  if (__tl_user_event_base__) {
@@ -253,7 +253,7 @@ class Locator {
253
253
  triggerCommand(command, ...args) {
254
254
  const filepath = this.worker.filepath || this.worker.current?.file?.filepath || void 0;
255
255
  return ensureAwaited(() => this.rpc.triggerCommand(
256
- this.state.contextId,
256
+ this.state.sessionId,
257
257
  command,
258
258
  filepath,
259
259
  args
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { Plugin } from 'vitest/config';
2
- import { CDPSession, BrowserServerState as BrowserServerState$1, BrowserServerStateContext, BrowserServer as BrowserServer$1, TestProject, Vite, BrowserProvider, BrowserScript, Vitest, ProcessPool } from 'vitest/node';
3
- import * as vitest from 'vitest';
4
- import { RunnerTestFile, TaskResultPack, AfterSuiteRunMeta, CancelReason, UserConsoleLog, SnapshotResult, SerializedConfig, ErrorWithDiff } from 'vitest';
2
+ import { CDPSession, BrowserServerState as BrowserServerState$1, ProjectBrowser as ProjectBrowser$1, TestProject, BrowserProvider, Vitest, ResolvedConfig, Vite, BrowserCommand, BrowserScript, ProcessPool } from 'vitest/node';
3
+ import * as vite from 'vite';
5
4
  import { HtmlTagDescriptor } from 'vite';
5
+ import * as vitest from 'vitest';
6
+ import { RunnerTestFile, TaskResultPack, AfterSuiteRunMeta, CancelReason, UserConsoleLog, SnapshotResult, SerializedConfig, ErrorWithDiff, ParsedStack } from 'vitest';
6
7
  import { StackTraceParserOptions } from '@vitest/utils/source-map';
7
8
  import { ServerIdResolution, ServerMockResolution } from '@vitest/mocker/node';
8
9
 
@@ -26,6 +27,7 @@ interface WebSocketBrowserHandlers {
26
27
  resolveSnapshotPath: (testPath: string) => string;
27
28
  resolveSnapshotRawPath: (testPath: string, rawPath: string) => string;
28
29
  onUnhandledError: (error: unknown, type: string) => Promise<void>;
30
+ onQueued: (file: RunnerTestFile) => void;
29
31
  onCollected: (files?: RunnerTestFile[]) => Promise<void>;
30
32
  onTaskUpdate: (packs: TaskResultPack[]) => void;
31
33
  onAfterSuiteRun: (meta: AfterSuiteRunMeta) => void;
@@ -35,11 +37,11 @@ interface WebSocketBrowserHandlers {
35
37
  saveSnapshotFile: (id: string, content: string) => Promise<void>;
36
38
  removeSnapshotFile: (id: string) => Promise<void>;
37
39
  sendLog: (log: UserConsoleLog) => void;
38
- finishBrowserTests: (contextId: string) => void;
40
+ finishBrowserTests: (sessionId: string) => void;
39
41
  snapshotSaved: (snapshot: SnapshotResult) => void;
40
42
  debug: (...args: string[]) => void;
41
43
  resolveId: (id: string, importer?: string) => Promise<ServerIdResolution | null>;
42
- triggerCommand: <T>(contextId: string, command: string, testPath: string | undefined, payload: unknown[]) => Promise<T>;
44
+ triggerCommand: <T>(sessionId: string, command: string, testPath: string | undefined, payload: unknown[]) => Promise<T>;
43
45
  resolveMock: (id: string, importer: string, options: {
44
46
  mock: 'spy' | 'factory' | 'auto';
45
47
  }) => Promise<ServerMockResolution>;
@@ -47,8 +49,8 @@ interface WebSocketBrowserHandlers {
47
49
  getBrowserFileSourceMap: (id: string) => SourceMap | null | {
48
50
  mappings: '';
49
51
  } | undefined;
50
- sendCdpEvent: (contextId: string, event: string, payload?: Record<string, unknown>) => unknown;
51
- trackCdpEvent: (contextId: string, type: 'on' | 'once' | 'off', event: string, listenerId: string) => void;
52
+ sendCdpEvent: (sessionId: string, event: string, payload?: Record<string, unknown>) => unknown;
53
+ trackCdpEvent: (sessionId: string, type: 'on' | 'once' | 'off', event: string, listenerId: string) => void;
52
54
  }
53
55
  interface WebSocketBrowserEvents {
54
56
  onCancel: (reason: CancelReason) => void;
@@ -82,52 +84,68 @@ declare class BrowserServerCDPHandler {
82
84
  declare class BrowserServerState implements BrowserServerState$1 {
83
85
  readonly orchestrators: Map<string, WebSocketBrowserRPC>;
84
86
  readonly testers: Map<string, WebSocketBrowserRPC>;
85
- readonly cdps: Map<string, BrowserServerCDPHandler>;
86
- private contexts;
87
- getContext(contextId: string): BrowserServerStateContext | undefined;
88
- createAsyncContext(method: 'run' | 'collect', contextId: string, files: string[]): Promise<void>;
89
- removeCDPHandler(sessionId: string): Promise<void>;
90
87
  }
91
88
 
92
- declare class BrowserServer implements BrowserServer$1 {
89
+ declare class ProjectBrowser implements ProjectBrowser$1 {
90
+ project: TestProject;
91
+ base: string;
92
+ testerHtml: Promise<string> | string;
93
+ testerFilepath: string;
94
+ locatorsUrl: string | undefined;
95
+ provider: BrowserProvider;
96
+ vitest: Vitest;
97
+ config: ResolvedConfig;
98
+ children: Set<ProjectBrowser>;
99
+ parent: ParentBrowserProject;
100
+ state: BrowserServerState;
101
+ constructor(project: TestProject, base: string);
102
+ get vite(): vite.ViteDevServer;
103
+ wrapSerializedConfig(): SerializedConfig;
104
+ initBrowserProvider(project: TestProject): Promise<void>;
105
+ parseErrorStacktrace(e: ErrorWithDiff, options?: StackTraceParserOptions): vitest.ParsedStack[];
106
+ parseStacktrace(trace: string, options?: StackTraceParserOptions): vitest.ParsedStack[];
107
+ close(): Promise<void>;
108
+ }
109
+
110
+ declare class ParentBrowserProject {
93
111
  project: TestProject;
94
112
  base: string;
95
- faviconUrl: string;
96
- prefixTesterUrl: string;
97
113
  orchestratorScripts: string | undefined;
98
114
  testerScripts: HtmlTagDescriptor[] | undefined;
115
+ faviconUrl: string;
116
+ prefixTesterUrl: string;
99
117
  manifest: Promise<Vite.Manifest> | Vite.Manifest;
100
- testerHtml: Promise<string> | string;
101
- testerFilepath: string;
118
+ vite: Vite.ViteDevServer;
119
+ private stackTraceOptions;
102
120
  orchestratorHtml: Promise<string> | string;
103
121
  injectorJs: Promise<string> | string;
104
122
  errorCatcherUrl: string;
105
123
  locatorsUrl: string | undefined;
106
124
  stateJs: Promise<string> | string;
107
- state: BrowserServerState;
108
- provider: BrowserProvider;
109
- vite: Vite.ViteDevServer;
110
- private stackTraceOptions;
125
+ commands: Record<string, BrowserCommand<any>>;
126
+ children: Set<ProjectBrowser>;
127
+ vitest: Vitest;
128
+ config: ResolvedConfig;
111
129
  constructor(project: TestProject, base: string);
112
- setServer(server: Vite.ViteDevServer): void;
113
- getSerializableConfig(): SerializedConfig;
130
+ setServer(vite: Vite.ViteDevServer): void;
131
+ spawn(project: TestProject): ProjectBrowser;
132
+ parseErrorStacktrace(e: ErrorWithDiff, options?: StackTraceParserOptions): ParsedStack[];
133
+ parseStacktrace(trace: string, options?: StackTraceParserOptions): ParsedStack[];
134
+ readonly cdps: Map<string, BrowserServerCDPHandler>;
135
+ private cdpSessionsPromises;
136
+ ensureCDPHandler(sessionId: string, rpcId: string): Promise<BrowserServerCDPHandler>;
137
+ removeCDPHandler(sessionId: string): void;
138
+ formatScripts(scripts: BrowserScript[] | undefined): Promise<HtmlTagDescriptor[]>;
114
139
  resolveTesterUrl(pathname: string): {
115
- contextId: string;
140
+ sessionId: string;
116
141
  testFile: string;
117
142
  };
118
- formatScripts(scripts: BrowserScript[] | undefined): Promise<HtmlTagDescriptor[]>;
119
- initBrowserProvider(): Promise<void>;
120
- parseErrorStacktrace(e: ErrorWithDiff, options?: StackTraceParserOptions): vitest.ParsedStack[];
121
- parseStacktrace(trace: string, options?: StackTraceParserOptions): vitest.ParsedStack[];
122
- private cdpSessionsPromises;
123
- ensureCDPHandler(contextId: string, sessionId: string): Promise<BrowserServerCDPHandler>;
124
- close(): Promise<void>;
125
143
  }
126
144
 
127
145
  declare const distRoot: string;
128
146
 
129
- declare function createBrowserPool(ctx: Vitest): ProcessPool;
147
+ declare function createBrowserPool(vitest: Vitest): ProcessPool;
130
148
 
131
- declare function createBrowserServer(project: TestProject, configFile: string | undefined, prePlugins?: Plugin[], postPlugins?: Plugin[]): Promise<BrowserServer>;
149
+ declare function createBrowserServer(project: TestProject, configFile: string | undefined, prePlugins?: Plugin[], postPlugins?: Plugin[]): Promise<ParentBrowserProject>;
132
150
 
133
- export { BrowserServer, createBrowserPool, createBrowserServer, distRoot };
151
+ export { ProjectBrowser, createBrowserPool, createBrowserServer, distRoot };