@vitest/browser 2.0.0-beta.9 → 2.0.0

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.
package/dist/providers.js CHANGED
@@ -1,111 +1,8 @@
1
- const playwrightBrowsers = ["firefox", "webkit", "chromium"];
2
- class PlaywrightBrowserProvider {
3
- name = "playwright";
4
- browser = null;
5
- page = null;
6
- browserName;
7
- ctx;
8
- options;
9
- getSupportedBrowsers() {
10
- return playwrightBrowsers;
11
- }
12
- initialize(project, { browser, options }) {
13
- this.ctx = project;
14
- this.browserName = browser;
15
- this.options = options;
16
- }
17
- async openBrowserPage() {
18
- if (this.page)
19
- return this.page;
20
- const options = this.ctx.config.browser;
21
- const playwright = await import('playwright');
22
- const browser = await playwright[this.browserName].launch({
23
- ...this.options?.launch,
24
- headless: options.headless
25
- });
26
- this.browser = browser;
27
- this.page = await browser.newPage(this.options?.page);
28
- return this.page;
29
- }
30
- async openPage(url) {
31
- const browserPage = await this.openBrowserPage();
32
- await browserPage.goto(url);
33
- }
34
- async close() {
35
- const page = this.page;
36
- this.page = null;
37
- const browser = this.browser;
38
- this.browser = null;
39
- await page?.close();
40
- await browser?.close();
41
- }
42
- }
43
-
44
- const webdriverBrowsers = ["firefox", "chrome", "edge", "safari"];
45
- class WebdriverBrowserProvider {
46
- name = "webdriverio";
47
- browser = null;
48
- browserName;
49
- ctx;
50
- options;
51
- getSupportedBrowsers() {
52
- return webdriverBrowsers;
53
- }
54
- async initialize(ctx, { browser, options }) {
55
- this.ctx = ctx;
56
- this.browserName = browser;
57
- this.options = options;
58
- }
59
- async openBrowser() {
60
- if (this.browser)
61
- return this.browser;
62
- const options = this.ctx.config.browser;
63
- if (this.browserName === "safari") {
64
- if (options.headless)
65
- throw new Error("You've enabled headless mode for Safari but it doesn't currently support it.");
66
- }
67
- const { remote } = await import('webdriverio');
68
- this.browser = await remote({
69
- ...this.options,
70
- logLevel: "error",
71
- capabilities: this.buildCapabilities()
72
- });
73
- return this.browser;
74
- }
75
- buildCapabilities() {
76
- const capabilities = {
77
- ...this.options?.capabilities,
78
- browserName: this.browserName
79
- };
80
- const headlessMap = {
81
- chrome: ["goog:chromeOptions", ["headless", "disable-gpu"]],
82
- firefox: ["moz:firefoxOptions", ["-headless"]],
83
- edge: ["ms:edgeOptions", ["--headless"]]
84
- };
85
- const options = this.ctx.config.browser;
86
- const browser = this.browserName;
87
- if (browser !== "safari" && options.headless) {
88
- const [key, args] = headlessMap[browser];
89
- const currentValues = this.options?.capabilities?.[key] || {};
90
- const newArgs = [...currentValues.args || [], ...args];
91
- capabilities[key] = { ...currentValues, args: newArgs };
92
- }
93
- return capabilities;
94
- }
95
- async openPage(url) {
96
- const browserInstance = await this.openBrowser();
97
- await browserInstance.url(url);
98
- }
99
- async close() {
100
- await Promise.all([
101
- this.browser?.sessionId ? this.browser?.deleteSession?.() : null
102
- ]);
103
- process.exit();
104
- }
105
- }
1
+ import { W as WebdriverBrowserProvider, P as PlaywrightBrowserProvider } from './webdriver-BdVqnfdE.js';
106
2
 
107
3
  class PreviewBrowserProvider {
108
4
  name = "preview";
5
+ supportsParallelism = false;
109
6
  ctx;
110
7
  open = false;
111
8
  getSupportedBrowsers() {
@@ -114,20 +11,27 @@ class PreviewBrowserProvider {
114
11
  isOpen() {
115
12
  return this.open;
116
13
  }
14
+ getCommandsContext() {
15
+ return {};
16
+ }
117
17
  async initialize(ctx) {
118
18
  this.ctx = ctx;
119
19
  this.open = false;
120
- if (ctx.config.browser.headless)
121
- 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`);
20
+ if (ctx.config.browser.headless) {
21
+ throw new Error(
22
+ `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`
23
+ );
24
+ }
122
25
  }
123
- async openPage(_url) {
26
+ async openPage(_contextId, url) {
124
27
  this.open = true;
125
- if (!this.ctx.browser)
28
+ if (!this.ctx.browser) {
126
29
  throw new Error("Browser is not initialized");
127
- const options = this.ctx.browser.config.server;
30
+ }
31
+ const options = this.ctx.browser.vite.config.server;
128
32
  const _open = options.open;
129
- options.open = _url;
130
- this.ctx.browser.openBrowser();
33
+ options.open = url;
34
+ this.ctx.browser.vite.openBrowser();
131
35
  options.open = _open;
132
36
  }
133
37
  async close() {
package/dist/state.js ADDED
@@ -0,0 +1 @@
1
+ const{parse:$parse,stringify:$stringify}=JSON;const{keys}=Object;const Primitive=String;const primitive="string";const ignore={};const object="object";const noop=(_,value)=>value;const primitives=value=>value instanceof Primitive?Primitive(value):value;const Primitives=(_,value)=>typeof value===primitive?new Primitive(value):value;const revive=(input,parsed,output,$)=>{const lazy=[];for(let ke=keys(output),{length}=ke,y=0;y<length;y++){const k=ke[y];const value=output[k];if(value instanceof Primitive){const tmp=input[value];if(typeof tmp===object&&!parsed.has(tmp)){parsed.add(tmp);output[k]=ignore;lazy.push({k,a:[input,parsed,tmp,$]})}else output[k]=$.call(output,k,tmp)}else if(output[k]!==ignore)output[k]=$.call(output,k,value)}for(let{length}=lazy,i=0;i<length;i++){const{k,a}=lazy[i];output[k]=$.call(output,k,revive.apply(null,a))}return output};const parse=(text,reviver)=>{const input=$parse(text,Primitives).map(primitives);const value=input[0];const $=noop;const tmp=typeof value===object&&value?revive(input,new Set,value,$):value;return $.call({"":tmp},"",tmp)};function getBrowserState(){return window.__vitest_browser_runner__}const config=getBrowserState().config;const contextId=getBrowserState().contextId;const providedContext=parse(getBrowserState().providedContext);const state={ctx:{pool:"browser",worker:"./browser.js",workerId:1,config,projectName:config.name||"",files:[],environment:{name:"browser",options:null},providedContext,invalidates:[]},onCancel:null,mockMap:new Map,config,environment:{name:"browser",transformMode:"web",setup(){throw new Error("Not called in the browser")}},moduleCache:getBrowserState().moduleCache,rpc:null,durations:{environment:0,prepare:performance.now()},providedContext};globalThis.__vitest_browser__=true;globalThis.__vitest_worker__=state;getBrowserState().cdp=createCdp();function rpc(){return state.rpc}function createCdp(){const listenersMap=new WeakMap;function getId(listener){const id=listenersMap.get(listener)||crypto.randomUUID();listenersMap.set(listener,id);return id}const listeners={};const error=err=>{window.dispatchEvent(new ErrorEvent("error",{error:err}))};const cdp={send(method,params){return rpc().sendCdpEvent(contextId,method,params)},on(event,listener){const listenerId=getId(listener);listeners[event]=listeners[event]||[];listeners[event].push(listener);rpc().trackCdpEvent(contextId,"on",event,listenerId).catch(error);return cdp},once(event,listener){const listenerId=getId(listener);const handler=data=>{listener(data);cdp.off(event,listener)};listeners[event]=listeners[event]||[];listeners[event].push(handler);rpc().trackCdpEvent(contextId,"once",event,listenerId).catch(error);return cdp},off(event,listener){const listenerId=getId(listener);if(listeners[event]){listeners[event]=listeners[event].filter(l=>l!==listener)}rpc().trackCdpEvent(contextId,"off",event,listenerId).catch(error);return cdp},emit(event,payload){if(listeners[event]){listeners[event].forEach(l=>{try{l(payload)}catch(err){error(err)}})}}};return cdp}
@@ -0,0 +1,249 @@
1
+ const playwrightBrowsers = ["firefox", "webkit", "chromium"];
2
+ class PlaywrightBrowserProvider {
3
+ name = "playwright";
4
+ supportsParallelism = true;
5
+ browser = null;
6
+ browserName;
7
+ ctx;
8
+ options;
9
+ contexts = /* @__PURE__ */ new Map();
10
+ pages = /* @__PURE__ */ new Map();
11
+ browserPromise = null;
12
+ getSupportedBrowsers() {
13
+ return playwrightBrowsers;
14
+ }
15
+ initialize(project, { browser, options }) {
16
+ this.ctx = project;
17
+ this.browserName = browser;
18
+ this.options = options;
19
+ }
20
+ async openBrowser() {
21
+ if (this.browserPromise) {
22
+ return this.browserPromise;
23
+ }
24
+ if (this.browser) {
25
+ return this.browser;
26
+ }
27
+ this.browserPromise = (async () => {
28
+ const options = this.ctx.config.browser;
29
+ const playwright = await import('playwright');
30
+ const launchOptions = {
31
+ ...this.options?.launch,
32
+ headless: options.headless
33
+ };
34
+ if (this.ctx.config.browser.ui && this.browserName === "chromium") {
35
+ if (!launchOptions.args) {
36
+ launchOptions.args = [];
37
+ }
38
+ if (!launchOptions.args.includes("--start-maximized") && !launchOptions.args.includes("--start-fullscreen")) {
39
+ launchOptions.args.push("--start-maximized");
40
+ }
41
+ }
42
+ const browser = await playwright[this.browserName].launch(launchOptions);
43
+ this.browser = browser;
44
+ this.browserPromise = null;
45
+ return this.browser;
46
+ })();
47
+ return this.browserPromise;
48
+ }
49
+ async createContext(contextId) {
50
+ if (this.contexts.has(contextId)) {
51
+ return this.contexts.get(contextId);
52
+ }
53
+ const browser = await this.openBrowser();
54
+ const options = {
55
+ ...this.options?.context,
56
+ ignoreHTTPSErrors: true,
57
+ serviceWorkers: "allow"
58
+ };
59
+ if (this.ctx.config.browser.ui) {
60
+ options.viewport = null;
61
+ }
62
+ const context = await browser.newContext(options);
63
+ this.contexts.set(contextId, context);
64
+ return context;
65
+ }
66
+ getPage(contextId) {
67
+ const page = this.pages.get(contextId);
68
+ if (!page) {
69
+ throw new Error(`Page "${contextId}" not found`);
70
+ }
71
+ return page;
72
+ }
73
+ getCommandsContext(contextId) {
74
+ const page = this.getPage(contextId);
75
+ return {
76
+ page,
77
+ context: this.contexts.get(contextId),
78
+ frame() {
79
+ return new Promise((resolve, reject) => {
80
+ const frame = page.frame("vitest-iframe");
81
+ if (frame) {
82
+ return resolve(frame);
83
+ }
84
+ const timeout = setTimeout(() => {
85
+ const err = new Error(`Cannot find "vitest-iframe" on the page. This is a bug in Vitest, please report it.`);
86
+ reject(err);
87
+ }, 1e3);
88
+ page.on("frameattached", (frame2) => {
89
+ clearTimeout(timeout);
90
+ resolve(frame2);
91
+ });
92
+ });
93
+ },
94
+ get iframe() {
95
+ return page.frameLocator('[data-vitest="true"]');
96
+ }
97
+ };
98
+ }
99
+ async openBrowserPage(contextId) {
100
+ if (this.pages.has(contextId)) {
101
+ const page2 = this.pages.get(contextId);
102
+ await page2.close();
103
+ this.pages.delete(contextId);
104
+ }
105
+ const context = await this.createContext(contextId);
106
+ const page = await context.newPage();
107
+ this.pages.set(contextId, page);
108
+ if (process.env.VITEST_PW_DEBUG) {
109
+ page.on("requestfailed", (request) => {
110
+ console.error(
111
+ "[PW Error]",
112
+ request.resourceType(),
113
+ "request failed for",
114
+ request.url(),
115
+ "url:",
116
+ request.failure()?.errorText
117
+ );
118
+ });
119
+ }
120
+ return page;
121
+ }
122
+ async openPage(contextId, url) {
123
+ const browserPage = await this.openBrowserPage(contextId);
124
+ await browserPage.goto(url);
125
+ }
126
+ async getCDPSession(contextId) {
127
+ const page = this.getPage(contextId);
128
+ const cdp = await page.context().newCDPSession(page);
129
+ return {
130
+ async send(method, params) {
131
+ const result = await cdp.send(method, params);
132
+ return result;
133
+ },
134
+ on(event, listener) {
135
+ cdp.on(event, listener);
136
+ },
137
+ off(event, listener) {
138
+ cdp.off(event, listener);
139
+ },
140
+ once(event, listener) {
141
+ cdp.once(event, listener);
142
+ }
143
+ };
144
+ }
145
+ async close() {
146
+ const browser = this.browser;
147
+ this.browser = null;
148
+ await Promise.all([...this.pages.values()].map((p) => p.close()));
149
+ this.pages.clear();
150
+ await Promise.all([...this.contexts.values()].map((c) => c.close()));
151
+ this.contexts.clear();
152
+ await browser?.close();
153
+ }
154
+ }
155
+
156
+ const webdriverBrowsers = ["firefox", "chrome", "edge", "safari"];
157
+ class WebdriverBrowserProvider {
158
+ name = "webdriverio";
159
+ supportsParallelism = false;
160
+ browser = null;
161
+ browserName;
162
+ ctx;
163
+ options;
164
+ getSupportedBrowsers() {
165
+ return webdriverBrowsers;
166
+ }
167
+ async initialize(ctx, { browser, options }) {
168
+ this.ctx = ctx;
169
+ this.browserName = browser;
170
+ this.options = options;
171
+ }
172
+ async beforeCommand() {
173
+ const page = this.browser;
174
+ const iframe = await page.findElement(
175
+ "css selector",
176
+ "iframe[data-vitest]"
177
+ );
178
+ await page.switchToFrame(iframe);
179
+ }
180
+ async afterCommand() {
181
+ await this.browser.switchToParentFrame();
182
+ }
183
+ getCommandsContext() {
184
+ return {
185
+ browser: this.browser
186
+ };
187
+ }
188
+ async openBrowser() {
189
+ if (this.browser) {
190
+ return this.browser;
191
+ }
192
+ const options = this.ctx.config.browser;
193
+ if (this.browserName === "safari") {
194
+ if (options.headless) {
195
+ throw new Error(
196
+ "You've enabled headless mode for Safari but it doesn't currently support it."
197
+ );
198
+ }
199
+ }
200
+ const { remote } = await import('webdriverio');
201
+ this.browser = await remote({
202
+ ...this.options,
203
+ logLevel: "error",
204
+ capabilities: this.buildCapabilities()
205
+ });
206
+ return this.browser;
207
+ }
208
+ buildCapabilities() {
209
+ const capabilities = {
210
+ ...this.options?.capabilities,
211
+ browserName: this.browserName
212
+ };
213
+ const headlessMap = {
214
+ chrome: ["goog:chromeOptions", ["headless", "disable-gpu"]],
215
+ firefox: ["moz:firefoxOptions", ["-headless"]],
216
+ edge: ["ms:edgeOptions", ["--headless"]]
217
+ };
218
+ const options = this.ctx.config.browser;
219
+ const browser = this.browserName;
220
+ if (browser !== "safari" && options.headless) {
221
+ const [key, args] = headlessMap[browser];
222
+ const currentValues = this.options?.capabilities?.[key] || {};
223
+ const newArgs = [...currentValues.args || [], ...args];
224
+ capabilities[key] = { ...currentValues, args: newArgs };
225
+ }
226
+ if (options.ui && (browser === "chrome" || browser === "edge")) {
227
+ const key = browser === "chrome" ? "goog:chromeOptions" : "ms:edgeOptions";
228
+ const args = capabilities[key]?.args || [];
229
+ if (!args.includes("--start-maximized") && !args.includes("--start-fullscreen")) {
230
+ args.push("--start-maximized");
231
+ }
232
+ capabilities[key] ??= {};
233
+ capabilities[key].args = args;
234
+ }
235
+ return capabilities;
236
+ }
237
+ async openPage(_contextId, url) {
238
+ const browserInstance = await this.openBrowser();
239
+ await browserInstance.url(url);
240
+ }
241
+ async close() {
242
+ await Promise.all([
243
+ this.browser?.sessionId ? this.browser?.deleteSession?.() : null
244
+ ]);
245
+ process.exit();
246
+ }
247
+ }
248
+
249
+ export { PlaywrightBrowserProvider as P, WebdriverBrowserProvider as W };