@vitest/browser 4.0.0-beta.13 → 4.0.0-beta.14

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.
Files changed (35) hide show
  1. package/context.d.ts +50 -9
  2. package/context.js +3 -2
  3. package/dist/client/.vite/manifest.json +2 -2
  4. package/dist/client/__vitest__/assets/{index-C15NF4dG.js → index-CKAjAT2u.js} +1 -1
  5. package/dist/client/__vitest__/index.html +1 -1
  6. package/dist/client/__vitest_browser__/{orchestrator-Pdu7HCGX.js → orchestrator-Ce7D5fGP.js} +8 -6
  7. package/dist/client/__vitest_browser__/{tester-DYNLfPFH.js → tester-Vm4ppAv-.js} +4 -1
  8. package/dist/client/orchestrator.html +1 -1
  9. package/dist/client/tester/tester.html +1 -1
  10. package/dist/client.js +1 -1
  11. package/dist/context.js +70 -12
  12. package/dist/expect-element.js +1 -1
  13. package/dist/{public-utils-B6exS8fl.js → index-BnLTaCRv.js} +3 -3
  14. package/dist/index.d.ts +36 -172
  15. package/dist/index.js +515 -1487
  16. package/dist/{locators/index.d.ts → locators.d.ts} +25 -2
  17. package/dist/locators.js +1 -0
  18. package/jest-dom.d.ts +5 -5
  19. package/matchers.d.ts +1 -1
  20. package/package.json +11 -33
  21. package/utils.d.ts +5 -5
  22. package/dist/index-BPDFwkoW.js +0 -1
  23. package/dist/index-CwoiDq7G.js +0 -6
  24. package/dist/locators/index.js +0 -1
  25. package/dist/locators/playwright.js +0 -1
  26. package/dist/locators/preview.js +0 -1
  27. package/dist/locators/webdriverio.js +0 -1
  28. package/dist/providers/playwright.d.ts +0 -105
  29. package/dist/providers/playwright.js +0 -385
  30. package/dist/providers/preview.d.ts +0 -16
  31. package/dist/providers/preview.js +0 -44
  32. package/dist/providers/webdriverio.d.ts +0 -51
  33. package/dist/providers/webdriverio.js +0 -206
  34. package/dist/utils.js +0 -1
  35. package/providers.d.ts +0 -7
@@ -1,385 +0,0 @@
1
- import { createManualModuleSource } from '@vitest/mocker/node';
2
- import c from 'tinyrainbow';
3
- import { createDebugger, isCSSRequest } from 'vitest/node';
4
-
5
- const debug = createDebugger("vitest:browser:playwright");
6
- const playwrightBrowsers = [
7
- "firefox",
8
- "webkit",
9
- "chromium"
10
- ];
11
- function playwright(options = {}) {
12
- return {
13
- name: "playwright",
14
- supportedBrowser: playwrightBrowsers,
15
- options,
16
- factory(project) {
17
- return new PlaywrightBrowserProvider(project, options);
18
- },
19
- _cli: true
20
- };
21
- }
22
- class PlaywrightBrowserProvider {
23
- name = "playwright";
24
- supportsParallelism = true;
25
- browser = null;
26
- contexts = new Map();
27
- pages = new Map();
28
- mocker;
29
- browserName;
30
- browserPromise = null;
31
- closing = false;
32
- tracingContexts = new Set();
33
- pendingTraces = new Map();
34
- constructor(project, options) {
35
- this.project = project;
36
- this.options = options;
37
- this.browserName = project.config.browser.name;
38
- this.mocker = this.createMocker();
39
- // make sure the traces are finished if the test hangs
40
- process.on("SIGTERM", () => {
41
- if (!this.browser) {
42
- return;
43
- }
44
- const promises = [];
45
- for (const [trace, contextId] of this.pendingTraces.entries()) {
46
- promises.push((() => {
47
- const context = this.contexts.get(contextId);
48
- return context?.tracing.stopChunk({ path: trace });
49
- })());
50
- }
51
- return Promise.allSettled(promises);
52
- });
53
- }
54
- async openBrowser() {
55
- await this._throwIfClosing();
56
- if (this.browserPromise) {
57
- debug?.("[%s] the browser is resolving, reusing the promise", this.browserName);
58
- return this.browserPromise;
59
- }
60
- if (this.browser) {
61
- debug?.("[%s] the browser is resolved, reusing it", this.browserName);
62
- return this.browser;
63
- }
64
- this.browserPromise = (async () => {
65
- const options = this.project.config.browser;
66
- const playwright = await import('playwright');
67
- if (this.options.connectOptions) {
68
- if (this.options.launchOptions) {
69
- this.project.vitest.logger.warn(c.yellow(`Found both ${c.bold(c.italic(c.yellow("connect")))} and ${c.bold(c.italic(c.yellow("launch")))} options in browser instance configuration.
70
- Ignoring ${c.bold(c.italic(c.yellow("launch")))} options and using ${c.bold(c.italic(c.yellow("connect")))} mode.
71
- You probably want to remove one of the two options and keep only the one you want to use.`));
72
- }
73
- const browser = await playwright[this.browserName].connect(this.options.connectOptions.wsEndpoint, this.options.connectOptions);
74
- this.browser = browser;
75
- this.browserPromise = null;
76
- return this.browser;
77
- }
78
- const launchOptions = {
79
- ...this.options.launchOptions,
80
- headless: options.headless
81
- };
82
- if (typeof options.trace === "object" && options.trace.tracesDir) {
83
- launchOptions.tracesDir = options.trace?.tracesDir;
84
- }
85
- const inspector = this.project.vitest.config.inspector;
86
- if (inspector.enabled) {
87
- // NodeJS equivalent defaults: https://nodejs.org/en/learn/getting-started/debugging#enable-inspector
88
- const port = inspector.port || 9229;
89
- const host = inspector.host || "127.0.0.1";
90
- launchOptions.args ||= [];
91
- launchOptions.args.push(`--remote-debugging-port=${port}`);
92
- launchOptions.args.push(`--remote-debugging-address=${host}`);
93
- this.project.vitest.logger.log(`Debugger listening on ws://${host}:${port}`);
94
- }
95
- // start Vitest UI maximized only on supported browsers
96
- if (this.project.config.browser.ui && this.browserName === "chromium") {
97
- if (!launchOptions.args) {
98
- launchOptions.args = [];
99
- }
100
- if (!launchOptions.args.includes("--start-maximized") && !launchOptions.args.includes("--start-fullscreen")) {
101
- launchOptions.args.push("--start-maximized");
102
- }
103
- }
104
- debug?.("[%s] initializing the browser with launch options: %O", this.browserName, launchOptions);
105
- this.browser = await playwright[this.browserName].launch(launchOptions);
106
- this.browserPromise = null;
107
- return this.browser;
108
- })();
109
- return this.browserPromise;
110
- }
111
- createMocker() {
112
- const idPreficates = new Map();
113
- const sessionIds = new Map();
114
- function createPredicate(sessionId, url) {
115
- const moduleUrl = new URL(url, "http://localhost");
116
- const predicate = (url) => {
117
- if (url.searchParams.has("_vitest_original")) {
118
- return false;
119
- }
120
- // different modules, ignore request
121
- if (url.pathname !== moduleUrl.pathname) {
122
- return false;
123
- }
124
- url.searchParams.delete("t");
125
- url.searchParams.delete("v");
126
- url.searchParams.delete("import");
127
- // different search params, ignore request
128
- if (url.searchParams.size !== moduleUrl.searchParams.size) {
129
- return false;
130
- }
131
- // check that all search params are the same
132
- for (const [param, value] of url.searchParams.entries()) {
133
- if (moduleUrl.searchParams.get(param) !== value) {
134
- return false;
135
- }
136
- }
137
- return true;
138
- };
139
- const ids = sessionIds.get(sessionId) || [];
140
- ids.push(moduleUrl.href);
141
- sessionIds.set(sessionId, ids);
142
- idPreficates.set(predicateKey(sessionId, moduleUrl.href), predicate);
143
- return predicate;
144
- }
145
- function predicateKey(sessionId, url) {
146
- return `${sessionId}:${url}`;
147
- }
148
- return {
149
- register: async (sessionId, module) => {
150
- const page = this.getPage(sessionId);
151
- await page.route(createPredicate(sessionId, module.url), async (route) => {
152
- if (module.type === "manual") {
153
- const exports = Object.keys(await module.resolve());
154
- const body = createManualModuleSource(module.url, exports);
155
- return route.fulfill({
156
- body,
157
- headers: getHeaders(this.project.browser.vite.config)
158
- });
159
- }
160
- // webkit doesn't support redirect responses
161
- // https://github.com/microsoft/playwright/issues/18318
162
- const isWebkit = this.browserName === "webkit";
163
- if (isWebkit) {
164
- let url;
165
- if (module.type === "redirect") {
166
- const redirect = new URL(module.redirect);
167
- url = redirect.href.slice(redirect.origin.length);
168
- } else {
169
- const request = new URL(route.request().url());
170
- request.searchParams.set("mock", module.type);
171
- url = request.href.slice(request.origin.length);
172
- }
173
- const result = await this.project.browser.vite.transformRequest(url).catch(() => null);
174
- if (!result) {
175
- return route.continue();
176
- }
177
- let content = result.code;
178
- if (result.map && "version" in result.map && result.map.mappings) {
179
- const type = isDirectCSSRequest(url) ? "css" : "js";
180
- content = getCodeWithSourcemap(type, content.toString(), result.map);
181
- }
182
- return route.fulfill({
183
- body: content,
184
- headers: getHeaders(this.project.browser.vite.config)
185
- });
186
- }
187
- if (module.type === "redirect") {
188
- return route.fulfill({
189
- status: 302,
190
- headers: { Location: module.redirect }
191
- });
192
- } else if (module.type === "automock" || module.type === "autospy") {
193
- const url = new URL(route.request().url());
194
- url.searchParams.set("mock", module.type);
195
- return route.fulfill({
196
- status: 302,
197
- headers: { Location: url.href }
198
- });
199
- } else ;
200
- });
201
- },
202
- delete: async (sessionId, id) => {
203
- const page = this.getPage(sessionId);
204
- const key = predicateKey(sessionId, id);
205
- const predicate = idPreficates.get(key);
206
- if (predicate) {
207
- await page.unroute(predicate).finally(() => idPreficates.delete(key));
208
- }
209
- },
210
- clear: async (sessionId) => {
211
- const page = this.getPage(sessionId);
212
- const ids = sessionIds.get(sessionId) || [];
213
- const promises = ids.map((id) => {
214
- const key = predicateKey(sessionId, id);
215
- const predicate = idPreficates.get(key);
216
- if (predicate) {
217
- return page.unroute(predicate).finally(() => idPreficates.delete(key));
218
- }
219
- return null;
220
- });
221
- await Promise.all(promises).finally(() => sessionIds.delete(sessionId));
222
- }
223
- };
224
- }
225
- async createContext(sessionId) {
226
- await this._throwIfClosing();
227
- if (this.contexts.has(sessionId)) {
228
- debug?.("[%s][%s] the context already exists, reusing it", sessionId, this.browserName);
229
- return this.contexts.get(sessionId);
230
- }
231
- const browser = await this.openBrowser();
232
- await this._throwIfClosing(browser);
233
- const actionTimeout = this.options.actionTimeout;
234
- const contextOptions = this.options.contextOptions ?? {};
235
- const options = {
236
- ...contextOptions,
237
- ignoreHTTPSErrors: true
238
- };
239
- if (this.project.config.browser.ui) {
240
- options.viewport = null;
241
- }
242
- const context = await browser.newContext(options);
243
- await this._throwIfClosing(context);
244
- if (actionTimeout != null) {
245
- context.setDefaultTimeout(actionTimeout);
246
- }
247
- debug?.("[%s][%s] the context is ready", sessionId, this.browserName);
248
- this.contexts.set(sessionId, context);
249
- return context;
250
- }
251
- getPage(sessionId) {
252
- const page = this.pages.get(sessionId);
253
- if (!page) {
254
- throw new Error(`Page "${sessionId}" not found in ${this.browserName} browser.`);
255
- }
256
- return page;
257
- }
258
- getCommandsContext(sessionId) {
259
- const page = this.getPage(sessionId);
260
- return {
261
- page,
262
- context: this.contexts.get(sessionId),
263
- frame() {
264
- return new Promise((resolve, reject) => {
265
- const frame = page.frame("vitest-iframe");
266
- if (frame) {
267
- return resolve(frame);
268
- }
269
- const timeout = setTimeout(() => {
270
- const err = new Error(`Cannot find "vitest-iframe" on the page. This is a bug in Vitest, please report it.`);
271
- reject(err);
272
- }, 1e3).unref();
273
- page.on("frameattached", (frame) => {
274
- clearTimeout(timeout);
275
- resolve(frame);
276
- });
277
- });
278
- },
279
- get iframe() {
280
- return page.frameLocator("[data-vitest=\"true\"]");
281
- }
282
- };
283
- }
284
- async openBrowserPage(sessionId) {
285
- await this._throwIfClosing();
286
- if (this.pages.has(sessionId)) {
287
- debug?.("[%s][%s] the page already exists, closing the old one", sessionId, this.browserName);
288
- const page = this.pages.get(sessionId);
289
- await page.close();
290
- this.pages.delete(sessionId);
291
- }
292
- const context = await this.createContext(sessionId);
293
- const page = await context.newPage();
294
- debug?.("[%s][%s] the page is ready", sessionId, this.browserName);
295
- await this._throwIfClosing(page);
296
- this.pages.set(sessionId, page);
297
- if (process.env.VITEST_PW_DEBUG) {
298
- page.on("requestfailed", (request) => {
299
- console.error("[PW Error]", request.resourceType(), "request failed for", request.url(), "url:", request.failure()?.errorText);
300
- });
301
- }
302
- return page;
303
- }
304
- async openPage(sessionId, url, beforeNavigate) {
305
- debug?.("[%s][%s] creating the browser page for %s", sessionId, this.browserName, url);
306
- const browserPage = await this.openBrowserPage(sessionId);
307
- await beforeNavigate?.();
308
- debug?.("[%s][%s] browser page is created, opening %s", sessionId, this.browserName, url);
309
- await browserPage.goto(url, { timeout: 0 });
310
- await this._throwIfClosing(browserPage);
311
- }
312
- async _throwIfClosing(disposable) {
313
- if (this.closing) {
314
- debug?.("[%s] provider was closed, cannot perform the action on %s", this.browserName, String(disposable));
315
- await disposable?.close();
316
- this.pages.clear();
317
- this.contexts.clear();
318
- this.browser = null;
319
- this.browserPromise = null;
320
- throw new Error(`[vitest] The provider was closed.`);
321
- }
322
- }
323
- async getCDPSession(sessionid) {
324
- const page = this.getPage(sessionid);
325
- const cdp = await page.context().newCDPSession(page);
326
- return {
327
- async send(method, params) {
328
- const result = await cdp.send(method, params);
329
- return result;
330
- },
331
- on(event, listener) {
332
- cdp.on(event, listener);
333
- },
334
- off(event, listener) {
335
- cdp.off(event, listener);
336
- },
337
- once(event, listener) {
338
- cdp.once(event, listener);
339
- }
340
- };
341
- }
342
- async close() {
343
- debug?.("[%s] closing provider", this.browserName);
344
- this.closing = true;
345
- if (this.browserPromise) {
346
- await this.browserPromise;
347
- this.browserPromise = null;
348
- }
349
- const browser = this.browser;
350
- this.browser = null;
351
- await Promise.all([...this.pages.values()].map((p) => p.close()));
352
- this.pages.clear();
353
- await Promise.all([...this.contexts.values()].map((c) => c.close()));
354
- this.contexts.clear();
355
- await browser?.close();
356
- debug?.("[%s] provider is closed", this.browserName);
357
- }
358
- }
359
- function getHeaders(config) {
360
- const headers = { "Content-Type": "application/javascript" };
361
- for (const name in config.server.headers) {
362
- headers[name] = String(config.server.headers[name]);
363
- }
364
- return headers;
365
- }
366
- function getCodeWithSourcemap(type, code, map) {
367
- if (type === "js") {
368
- code += `\n//# sourceMappingURL=${genSourceMapUrl(map)}`;
369
- } else if (type === "css") {
370
- code += `\n/*# sourceMappingURL=${genSourceMapUrl(map)} */`;
371
- }
372
- return code;
373
- }
374
- function genSourceMapUrl(map) {
375
- if (typeof map !== "string") {
376
- map = JSON.stringify(map);
377
- }
378
- return `data:application/json;base64,${Buffer.from(map).toString("base64")}`;
379
- }
380
- const directRequestRE = /[?&]direct\b/;
381
- function isDirectCSSRequest(request) {
382
- return isCSSRequest(request) && directRequestRE.test(request);
383
- }
384
-
385
- export { PlaywrightBrowserProvider, playwright };
@@ -1,16 +0,0 @@
1
- import { BrowserProviderOption, BrowserProvider, TestProject } from 'vitest/node';
2
-
3
- declare function preview(): BrowserProviderOption;
4
- declare class PreviewBrowserProvider implements BrowserProvider {
5
- name: "preview";
6
- supportsParallelism: boolean;
7
- private project;
8
- private open;
9
- constructor(project: TestProject);
10
- isOpen(): boolean;
11
- getCommandsContext(): {};
12
- openPage(_sessionId: string, url: string): Promise<void>;
13
- close(): Promise<void>;
14
- }
15
-
16
- export { PreviewBrowserProvider, preview };
@@ -1,44 +0,0 @@
1
- function preview() {
2
- return {
3
- name: "preview",
4
- options: {},
5
- factory(project) {
6
- return new PreviewBrowserProvider(project);
7
- },
8
- _cli: true
9
- };
10
- }
11
- class PreviewBrowserProvider {
12
- name = "preview";
13
- supportsParallelism = false;
14
- project;
15
- open = false;
16
- constructor(project) {
17
- this.project = project;
18
- this.open = false;
19
- if (project.config.browser.headless) {
20
- throw new Error("You've enabled headless mode for \"preview\" provider but it doesn't support it. Use \"playwright\" or \"webdriverio\" instead: https://vitest.dev/guide/browser/#configuration");
21
- }
22
- project.vitest.logger.printBrowserBanner(project);
23
- }
24
- isOpen() {
25
- return this.open;
26
- }
27
- getCommandsContext() {
28
- return {};
29
- }
30
- async openPage(_sessionId, url) {
31
- this.open = true;
32
- if (!this.project.browser) {
33
- throw new Error("Browser is not initialized");
34
- }
35
- const options = this.project.browser.vite.config.server;
36
- const _open = options.open;
37
- options.open = url;
38
- this.project.browser.vite.openBrowser();
39
- options.open = _open;
40
- }
41
- async close() {}
42
- }
43
-
44
- export { PreviewBrowserProvider, preview };
@@ -1,51 +0,0 @@
1
- import { ScreenshotMatcherOptions, ScreenshotComparatorRegistry } from '@vitest/browser/context';
2
- import { BrowserProviderOption, BrowserProvider, TestProject, CDPSession } from 'vitest/node';
3
- import { ClickOptions, DragAndDropOptions, remote } from 'webdriverio';
4
-
5
- interface WebdriverProviderOptions extends Partial<Parameters<typeof remote>[0]> {}
6
- declare function webdriverio(options?: WebdriverProviderOptions): BrowserProviderOption<WebdriverProviderOptions>;
7
- declare class WebdriverBrowserProvider implements BrowserProvider {
8
- name: "webdriverio";
9
- supportsParallelism: boolean;
10
- browser: WebdriverIO.Browser | null;
11
- private browserName;
12
- private project;
13
- private options?;
14
- private closing;
15
- private iframeSwitched;
16
- private topLevelContext;
17
- getSupportedBrowsers(): readonly string[];
18
- constructor(project: TestProject, options: WebdriverProviderOptions);
19
- isIframeSwitched(): boolean;
20
- switchToTestFrame(): Promise<void>;
21
- switchToMainFrame(): Promise<void>;
22
- setViewport(options: {
23
- width: number;
24
- height: number;
25
- }): Promise<void>;
26
- getCommandsContext(): {
27
- browser: WebdriverIO.Browser | null;
28
- };
29
- openBrowser(): Promise<WebdriverIO.Browser>;
30
- private buildCapabilities;
31
- openPage(sessionId: string, url: string): Promise<void>;
32
- private _throwIfClosing;
33
- close(): Promise<void>;
34
- getCDPSession(_sessionId: string): Promise<CDPSession>;
35
- }
36
- declare module "vitest/node" {
37
- interface UserEventClickOptions extends ClickOptions {}
38
- interface UserEventDragOptions extends DragAndDropOptions {
39
- sourceX?: number;
40
- sourceY?: number;
41
- targetX?: number;
42
- targetY?: number;
43
- }
44
- interface BrowserCommandContext {
45
- browser: WebdriverIO.Browser;
46
- }
47
- interface ToMatchScreenshotOptions extends Omit<ScreenshotMatcherOptions, "comparatorName" | "comparatorOptions"> {}
48
- interface ToMatchScreenshotComparators extends ScreenshotComparatorRegistry {}
49
- }
50
-
51
- export { WebdriverBrowserProvider, webdriverio };
@@ -1,206 +0,0 @@
1
- import { createDebugger } from 'vitest/node';
2
-
3
- const debug = createDebugger("vitest:browser:wdio");
4
- const webdriverBrowsers = [
5
- "firefox",
6
- "chrome",
7
- "edge",
8
- "safari"
9
- ];
10
- function webdriverio(options = {}) {
11
- return {
12
- name: "webdriverio",
13
- supportedBrowser: webdriverBrowsers,
14
- options,
15
- factory(project) {
16
- return new WebdriverBrowserProvider(project, options);
17
- },
18
- _cli: true
19
- };
20
- }
21
- class WebdriverBrowserProvider {
22
- name = "webdriverio";
23
- supportsParallelism = false;
24
- browser = null;
25
- browserName;
26
- project;
27
- options;
28
- closing = false;
29
- iframeSwitched = false;
30
- topLevelContext;
31
- getSupportedBrowsers() {
32
- return webdriverBrowsers;
33
- }
34
- constructor(project, options) {
35
- // increase shutdown timeout because WDIO takes some extra time to kill the driver
36
- if (!project.vitest.state._data.timeoutIncreased) {
37
- project.vitest.state._data.timeoutIncreased = true;
38
- project.vitest.config.teardownTimeout += 1e4;
39
- }
40
- this.closing = false;
41
- this.project = project;
42
- this.browserName = project.config.browser.name;
43
- this.options = options;
44
- }
45
- isIframeSwitched() {
46
- return this.iframeSwitched;
47
- }
48
- async switchToTestFrame() {
49
- const browser = this.browser;
50
- // support wdio@9
51
- if (browser.switchFrame) {
52
- await browser.switchFrame(browser.$("iframe[data-vitest]"));
53
- } else {
54
- const iframe = await browser.findElement("css selector", "iframe[data-vitest]");
55
- await browser.switchToFrame(iframe);
56
- }
57
- this.iframeSwitched = true;
58
- }
59
- async switchToMainFrame() {
60
- const page = this.browser;
61
- if (page.switchFrame) {
62
- await page.switchFrame(null);
63
- } else {
64
- await page.switchToParentFrame();
65
- }
66
- this.iframeSwitched = false;
67
- }
68
- async setViewport(options) {
69
- if (this.topLevelContext == null || !this.browser) {
70
- throw new Error(`The browser has no open pages.`);
71
- }
72
- await this.browser.send({
73
- method: "browsingContext.setViewport",
74
- params: {
75
- context: this.topLevelContext,
76
- devicePixelRatio: 1,
77
- viewport: options
78
- }
79
- });
80
- }
81
- getCommandsContext() {
82
- return { browser: this.browser };
83
- }
84
- async openBrowser() {
85
- await this._throwIfClosing("opening the browser");
86
- if (this.browser) {
87
- debug?.("[%s] the browser is already opened, reusing it", this.browserName);
88
- return this.browser;
89
- }
90
- const options = this.project.config.browser;
91
- if (this.browserName === "safari") {
92
- if (options.headless) {
93
- throw new Error("You've enabled headless mode for Safari but it doesn't currently support it.");
94
- }
95
- }
96
- const { remote } = await import('webdriverio');
97
- const remoteOptions = {
98
- logLevel: "silent",
99
- ...this.options,
100
- capabilities: this.buildCapabilities()
101
- };
102
- debug?.("[%s] opening the browser with options: %O", this.browserName, remoteOptions);
103
- // TODO: close everything, if browser is closed from the outside
104
- this.browser = await remote(remoteOptions);
105
- await this._throwIfClosing();
106
- return this.browser;
107
- }
108
- buildCapabilities() {
109
- const capabilities = {
110
- ...this.options?.capabilities,
111
- browserName: this.browserName
112
- };
113
- const headlessMap = {
114
- chrome: ["goog:chromeOptions", ["headless", "disable-gpu"]],
115
- firefox: ["moz:firefoxOptions", ["-headless"]],
116
- edge: ["ms:edgeOptions", ["--headless"]]
117
- };
118
- const options = this.project.config.browser;
119
- const browser = this.browserName;
120
- if (browser !== "safari" && options.headless) {
121
- const [key, args] = headlessMap[browser];
122
- const currentValues = (this.options?.capabilities)?.[key] || {};
123
- const newArgs = [...currentValues.args || [], ...args];
124
- capabilities[key] = {
125
- ...currentValues,
126
- args: newArgs
127
- };
128
- }
129
- // start Vitest UI maximized only on supported browsers
130
- if (options.ui && (browser === "chrome" || browser === "edge")) {
131
- const key = browser === "chrome" ? "goog:chromeOptions" : "ms:edgeOptions";
132
- const args = capabilities[key]?.args || [];
133
- if (!args.includes("--start-maximized") && !args.includes("--start-fullscreen")) {
134
- args.push("--start-maximized");
135
- }
136
- capabilities[key] ??= {};
137
- capabilities[key].args = args;
138
- }
139
- const inspector = this.project.vitest.config.inspector;
140
- if (inspector.enabled && (browser === "chrome" || browser === "edge")) {
141
- const key = browser === "chrome" ? "goog:chromeOptions" : "ms:edgeOptions";
142
- const args = capabilities[key]?.args || [];
143
- // NodeJS equivalent defaults: https://nodejs.org/en/learn/getting-started/debugging#enable-inspector
144
- const port = inspector.port || 9229;
145
- const host = inspector.host || "127.0.0.1";
146
- args.push(`--remote-debugging-port=${port}`);
147
- args.push(`--remote-debugging-address=${host}`);
148
- this.project.vitest.logger.log(`Debugger listening on ws://${host}:${port}`);
149
- capabilities[key] ??= {};
150
- capabilities[key].args = args;
151
- }
152
- return capabilities;
153
- }
154
- async openPage(sessionId, url) {
155
- await this._throwIfClosing("creating the browser");
156
- debug?.("[%s][%s] creating the browser page for %s", sessionId, this.browserName, url);
157
- const browserInstance = await this.openBrowser();
158
- debug?.("[%s][%s] browser page is created, opening %s", sessionId, this.browserName, url);
159
- await browserInstance.url(url);
160
- this.topLevelContext = await browserInstance.getWindowHandle();
161
- await this._throwIfClosing("opening the url");
162
- }
163
- async _throwIfClosing(action) {
164
- if (this.closing) {
165
- debug?.(`[%s] provider was closed, cannot perform the action${action ? ` ${action}` : ""}`, this.browserName);
166
- await (this.browser?.sessionId ? this.browser?.deleteSession?.() : null);
167
- throw new Error(`[vitest] The provider was closed.`);
168
- }
169
- }
170
- async close() {
171
- debug?.("[%s] closing provider", this.browserName);
172
- this.closing = true;
173
- const browser = this.browser;
174
- const sessionId = browser?.sessionId;
175
- if (!browser || !sessionId) {
176
- return;
177
- }
178
- // https://github.com/webdriverio/webdriverio/blob/ab1a2e82b13a9c7d0e275ae87e7357e1b047d8d3/packages/wdio-runner/src/index.ts#L486
179
- await browser.deleteSession();
180
- browser.sessionId = undefined;
181
- this.browser = null;
182
- }
183
- async getCDPSession(_sessionId) {
184
- return {
185
- send: (method, params) => {
186
- if (!this.browser) {
187
- throw new Error(`The environment was torn down.`);
188
- }
189
- return this.browser.sendCommandAndGetResult(method, params ?? {}).catch((error) => {
190
- return Promise.reject(new Error(`Failed to execute "${method}" command.`, { cause: error }));
191
- });
192
- },
193
- on: () => {
194
- throw new Error(`webdriverio provider doesn't support cdp.on()`);
195
- },
196
- once: () => {
197
- throw new Error(`webdriverio provider doesn't support cdp.once()`);
198
- },
199
- off: () => {
200
- throw new Error(`webdriverio provider doesn't support cdp.off()`);
201
- }
202
- };
203
- }
204
- }
205
-
206
- export { WebdriverBrowserProvider, webdriverio };
package/dist/utils.js DELETED
@@ -1 +0,0 @@
1
- import"@vitest/browser/context";export{u as debug,h as getElementError,t as getElementLocatorSelectors,v as prettyDOM}from"./public-utils-B6exS8fl.js";import"vitest/internal/browser";