@vitest/browser 2.1.0-beta.6 → 2.1.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/index.js CHANGED
@@ -1,20 +1,23 @@
1
- import { createDebugger, isFileServingAllowed, getFilePoolName, resolveApiServerConfig, resolveFsAllow, distDir, createServer } from 'vitest/node';
2
- import fs, { existsSync, readdirSync, readFileSync, promises, lstatSync } from 'node:fs';
1
+ import { createDebugger, isFileServingAllowed, getFilePoolName, resolveApiServerConfig, resolveFsAllow, distDir, createViteLogger, createViteServer } from 'vitest/node';
2
+ import c from 'tinyrainbow';
3
+ import fs, { existsSync, promises, readFileSync, lstatSync } from 'node:fs';
3
4
  import { WebSocketServer } from 'ws';
4
- import { builtinModules, createRequire } from 'node:module';
5
+ import { ServerMockResolver, dynamicImportPlugin } from '@vitest/mocker/node';
5
6
  import { readFile as readFile$1, mkdir } from 'node:fs/promises';
6
7
  import { fileURLToPath } from 'node:url';
7
8
  import { createDefer, slash, toArray } from '@vitest/utils';
8
9
  import { parseErrorStacktrace, parseStacktrace } from '@vitest/utils/source-map';
10
+ import { createRequire } from 'node:module';
9
11
  import sirv from 'sirv';
10
12
  import { defaultBrowserPort, coverageConfigDefaults } from 'vitest/config';
11
- import { P as PlaywrightBrowserProvider, W as WebdriverBrowserProvider } from './webdriver-BdVqnfdE.js';
12
- import { resolve as resolve$1, dirname as dirname$1, normalize as normalize$1 } from 'node:path';
13
13
  import MagicString from 'magic-string';
14
- import { esmWalker } from '@vitest/utils/ast';
14
+ import { P as PlaywrightBrowserProvider, W as WebdriverBrowserProvider } from './webdriver-Cv9wga63.js';
15
+ import { resolve as resolve$1, dirname as dirname$1, basename as basename$1, normalize as normalize$1 } from 'node:path';
15
16
  import crypto from 'node:crypto';
16
17
  import * as nodeos from 'node:os';
17
18
 
19
+ var version = "2.1.0";
20
+
18
21
  const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
19
22
  function normalizeWindowsPath(input = "") {
20
23
  if (!input) {
@@ -403,129 +406,8 @@ const stringify = (value, replacer, space) => {
403
406
  }
404
407
  };
405
408
 
406
- async function resolveMock(project, rawId, importer, hasFactory) {
407
- const { id, fsPath, external } = await resolveId(project, rawId, importer);
408
- if (hasFactory) {
409
- const needsInteropMap = viteDepsInteropMap(project.browser.vite.config);
410
- const needsInterop = needsInteropMap?.get(fsPath) ?? false;
411
- return { type: "factory", resolvedId: id, needsInterop };
412
- }
413
- const mockPath = resolveMockPath(project.config.root, fsPath, external);
414
- return {
415
- type: mockPath === null ? "automock" : "redirect",
416
- mockPath,
417
- resolvedId: id
418
- };
419
- }
420
- async function resolveId(project, rawId, importer) {
421
- const resolved = await project.browser.vite.pluginContainer.resolveId(
422
- rawId,
423
- importer,
424
- {
425
- ssr: false
426
- }
427
- );
428
- return resolveModule(project, rawId, resolved);
429
- }
430
- async function resolveModule(project, rawId, resolved) {
431
- const id = resolved?.id || rawId;
432
- const external = !isAbsolute(id) || isModuleDirectory(project.config, id) ? rawId : null;
433
- return {
434
- id,
435
- fsPath: cleanUrl(id),
436
- external
437
- };
438
- }
439
- function isModuleDirectory(config, path) {
440
- const moduleDirectories = config.server.deps?.moduleDirectories || [
441
- "/node_modules/"
442
- ];
443
- return moduleDirectories.some((dir) => path.includes(dir));
444
- }
445
- function resolveMockPath(root, mockPath, external) {
446
- const path = external || mockPath;
447
- if (external || isNodeBuiltin(mockPath) || !existsSync(mockPath)) {
448
- const mockDirname = dirname(path);
449
- const mockFolder = join(
450
- root,
451
- "__mocks__",
452
- mockDirname
453
- );
454
- if (!existsSync(mockFolder)) {
455
- return null;
456
- }
457
- const files = readdirSync(mockFolder);
458
- const baseOriginal = basename(path);
459
- for (const file of files) {
460
- const baseFile = basename(file, extname(file));
461
- if (baseFile === baseOriginal) {
462
- return resolve(mockFolder, file);
463
- }
464
- }
465
- return null;
466
- }
467
- const dir = dirname(path);
468
- const baseId = basename(path);
469
- const fullPath = resolve(dir, "__mocks__", baseId);
470
- return existsSync(fullPath) ? fullPath : null;
471
- }
472
- const prefixedBuiltins = /* @__PURE__ */ new Set(["node:test"]);
473
- const builtins = /* @__PURE__ */ new Set([
474
- ...builtinModules,
475
- "assert/strict",
476
- "diagnostics_channel",
477
- "dns/promises",
478
- "fs/promises",
479
- "path/posix",
480
- "path/win32",
481
- "readline/promises",
482
- "stream/consumers",
483
- "stream/promises",
484
- "stream/web",
485
- "timers/promises",
486
- "util/types",
487
- "wasi"
488
- ]);
489
- const NODE_BUILTIN_NAMESPACE = "node:";
490
- function isNodeBuiltin(id) {
491
- if (prefixedBuiltins.has(id)) {
492
- return true;
493
- }
494
- return builtins.has(
495
- id.startsWith(NODE_BUILTIN_NAMESPACE) ? id.slice(NODE_BUILTIN_NAMESPACE.length) : id
496
- );
497
- }
498
- const postfixRE = /[?#].*$/;
499
- function cleanUrl(url) {
500
- return url.replace(postfixRE, "");
501
- }
502
- const metadata = /* @__PURE__ */ new WeakMap();
503
- function viteDepsInteropMap(config) {
504
- if (metadata.has(config)) {
505
- return metadata.get(config);
506
- }
507
- const cacheDirPath = getDepsCacheDir(config);
508
- const metadataPath = resolve(cacheDirPath, "_metadata.json");
509
- if (!existsSync(metadataPath)) {
510
- return null;
511
- }
512
- const { optimized } = JSON.parse(readFileSync(metadataPath, "utf-8"));
513
- const needsInteropMap = /* @__PURE__ */ new Map();
514
- for (const name in optimized) {
515
- const dep = optimized[name];
516
- const file = resolve(cacheDirPath, dep.file);
517
- needsInteropMap.set(file, dep.needsInterop);
518
- }
519
- metadata.set(config, needsInteropMap);
520
- return needsInteropMap;
521
- }
522
- function getDepsCacheDir(config) {
523
- return resolve(config.cacheDir, "deps");
524
- }
525
-
526
409
  const debug$1 = createDebugger("vitest:browser:api");
527
410
  const BROWSER_API_PATH = "/__vitest_browser_api__";
528
- const VALID_ID_PREFIX = "/@id/";
529
411
  function setupBrowserRpc(server) {
530
412
  const project = server.project;
531
413
  const vite = server.vite;
@@ -563,6 +445,9 @@ function setupBrowserRpc(server) {
563
445
  }
564
446
  }
565
447
  function setupClient(sessionId, ws) {
448
+ const mockResolver = new ServerMockResolver(server.vite, {
449
+ moduleDirectories: project.config.server?.deps?.moduleDirectories
450
+ });
566
451
  const rpc = createBirpc(
567
452
  {
568
453
  async onUnhandledError(error, type) {
@@ -622,34 +507,7 @@ function setupBrowserRpc(server) {
622
507
  ctx.cancelCurrentRun(reason);
623
508
  },
624
509
  async resolveId(id, importer) {
625
- const resolved = await vite.pluginContainer.resolveId(
626
- id,
627
- importer,
628
- {
629
- ssr: false
630
- }
631
- );
632
- if (!resolved) {
633
- return null;
634
- }
635
- const isOptimized = resolved.id.startsWith(withTrailingSlash(vite.config.cacheDir));
636
- let url;
637
- const root = vite.config.root;
638
- if (resolved.id.startsWith(withTrailingSlash(root))) {
639
- url = resolved.id.slice(root.length);
640
- } else if (resolved.id !== "/@react-refresh" && isAbsolute(resolved.id) && existsSync(cleanUrl(resolved.id))) {
641
- url = join("/@fs/", resolved.id);
642
- } else {
643
- url = resolved.id;
644
- }
645
- if (url[0] !== "." && url[0] !== "/") {
646
- url = id.startsWith(VALID_ID_PREFIX) ? id : VALID_ID_PREFIX + id.replace("\0", "__x00__");
647
- }
648
- return {
649
- id: resolved.id,
650
- url,
651
- optimized: isOptimized
652
- };
510
+ return mockResolver.resolveId(id, importer);
653
511
  },
654
512
  debug(...args) {
655
513
  ctx.logger.console.debug(...args);
@@ -693,17 +551,11 @@ function setupBrowserRpc(server) {
693
551
  debug$1?.("[%s] Finishing browser tests for context", contextId);
694
552
  return server.state.getContext(contextId)?.resolve();
695
553
  },
696
- resolveMock(rawId, importer, hasFactory) {
697
- return resolveMock(project, rawId, importer, hasFactory);
554
+ resolveMock(rawId, importer, options) {
555
+ return mockResolver.resolveMock(rawId, importer, options);
698
556
  },
699
557
  invalidate(ids) {
700
- ids.forEach((id) => {
701
- const moduleGraph = server.vite.moduleGraph;
702
- const module = moduleGraph.getModuleById(id);
703
- if (module) {
704
- moduleGraph.invalidateModule(module, /* @__PURE__ */ new Set(), Date.now(), true);
705
- }
706
- });
558
+ return mockResolver.invalidate(ids);
707
559
  },
708
560
  // CDP
709
561
  async sendCdpEvent(contextId, event, payload) {
@@ -752,12 +604,6 @@ function stringifyReplace(key, value) {
752
604
  return value;
753
605
  }
754
606
  }
755
- function withTrailingSlash(path) {
756
- if (path[path.length - 1] !== "/") {
757
- return `${path}/`;
758
- }
759
- return path;
760
- }
761
607
 
762
608
  class BrowserServerState {
763
609
  orchestrators = /* @__PURE__ */ new Map();
@@ -1418,11 +1264,6 @@ var DOM_KEY_LOCATION;
1418
1264
  ];
1419
1265
 
1420
1266
  const keyboard = async (context, text, state) => {
1421
- function focusIframe() {
1422
- if (!document.activeElement || document.activeElement.ownerDocument !== document || document.activeElement === document.body) {
1423
- window.focus();
1424
- }
1425
- }
1426
1267
  if (context.provider instanceof PlaywrightBrowserProvider) {
1427
1268
  const frame = await context.frame();
1428
1269
  await frame.evaluate(focusIframe);
@@ -1436,12 +1277,6 @@ const keyboard = async (context, text, state) => {
1436
1277
  context.contextId,
1437
1278
  text,
1438
1279
  async () => {
1439
- function selectAll() {
1440
- const element = document.activeElement;
1441
- if (element && element.select) {
1442
- element.select();
1443
- }
1444
- }
1445
1280
  if (context.provider instanceof PlaywrightBrowserProvider) {
1446
1281
  const frame = await context.frame();
1447
1282
  await frame.evaluate(selectAll);
@@ -1457,7 +1292,7 @@ const keyboard = async (context, text, state) => {
1457
1292
  unreleased: Array.from(pressed)
1458
1293
  };
1459
1294
  };
1460
- async function keyboardImplementation(pressed, provider, contextId, text, selectAll, skipRelease) {
1295
+ async function keyboardImplementation(pressed, provider, contextId, text, selectAll2, skipRelease) {
1461
1296
  if (provider instanceof PlaywrightBrowserProvider) {
1462
1297
  const page = provider.getPage(contextId);
1463
1298
  const actions = parseKeyDef(defaultKeyMap, text);
@@ -1469,7 +1304,7 @@ async function keyboardImplementation(pressed, provider, contextId, text, select
1469
1304
  }
1470
1305
  if (!releasePrevious) {
1471
1306
  if (key === "selectall") {
1472
- await selectAll();
1307
+ await selectAll2();
1473
1308
  continue;
1474
1309
  }
1475
1310
  for (let i = 1; i <= repeat; i++) {
@@ -1507,7 +1342,7 @@ async function keyboardImplementation(pressed, provider, contextId, text, select
1507
1342
  if (key === "selectall") {
1508
1343
  await keyboard2.perform();
1509
1344
  keyboard2 = browser.action("key");
1510
- await selectAll();
1345
+ await selectAll2();
1511
1346
  continue;
1512
1347
  }
1513
1348
  for (let i = 1; i <= repeat; i++) {
@@ -1527,6 +1362,17 @@ async function keyboardImplementation(pressed, provider, contextId, text, select
1527
1362
  pressed
1528
1363
  };
1529
1364
  }
1365
+ function focusIframe() {
1366
+ if (!document.activeElement || document.activeElement.ownerDocument !== document || document.activeElement === document.body) {
1367
+ window.focus();
1368
+ }
1369
+ }
1370
+ function selectAll() {
1371
+ const element = document.activeElement;
1372
+ if (element && element.select) {
1373
+ element.select();
1374
+ }
1375
+ }
1530
1376
 
1531
1377
  const type = async (context, selector, text, options = {}) => {
1532
1378
  const { skipClick = false, skipAutoClose = false } = options;
@@ -1689,6 +1535,131 @@ const hover = async (context, selector, options = {}) => {
1689
1535
  }
1690
1536
  };
1691
1537
 
1538
+ const upload = async (context, selector, files) => {
1539
+ const testPath = context.testPath;
1540
+ if (!testPath) {
1541
+ throw new Error(`Cannot upload files outside of a test`);
1542
+ }
1543
+ const testDir = dirname(testPath);
1544
+ if (context.provider instanceof PlaywrightBrowserProvider) {
1545
+ const { iframe } = context;
1546
+ const playwrightFiles = files.map((file) => {
1547
+ if (typeof file === "string") {
1548
+ return resolve(testDir, file);
1549
+ }
1550
+ return {
1551
+ name: file.name,
1552
+ mimeType: file.mimeType,
1553
+ buffer: Buffer.from(file.base64, "base64")
1554
+ };
1555
+ });
1556
+ await iframe.locator(selector).setInputFiles(playwrightFiles);
1557
+ } else if (context.provider instanceof WebdriverBrowserProvider) {
1558
+ for (const file of files) {
1559
+ if (typeof file !== "string") {
1560
+ throw new TypeError(`The "${context.provider.name}" provider doesn't support uploading files objects. Provide a file path instead.`);
1561
+ }
1562
+ }
1563
+ const element = context.browser.$(selector);
1564
+ for (const file of files) {
1565
+ const filepath = resolve(testDir, file);
1566
+ const remoteFilePath = await context.browser.uploadFile(filepath);
1567
+ await element.addValue(remoteFilePath);
1568
+ }
1569
+ } else {
1570
+ throw new TypeError(`Provider "${context.provider.name}" does not support uploading files via userEvent.upload`);
1571
+ }
1572
+ };
1573
+
1574
+ const types = { "application/andrew-inset": ["ez"], "application/appinstaller": ["appinstaller"], "application/applixware": ["aw"], "application/appx": ["appx"], "application/appxbundle": ["appxbundle"], "application/atom+xml": ["atom"], "application/atomcat+xml": ["atomcat"], "application/atomdeleted+xml": ["atomdeleted"], "application/atomsvc+xml": ["atomsvc"], "application/atsc-dwd+xml": ["dwd"], "application/atsc-held+xml": ["held"], "application/atsc-rsat+xml": ["rsat"], "application/automationml-aml+xml": ["aml"], "application/automationml-amlx+zip": ["amlx"], "application/bdoc": ["bdoc"], "application/calendar+xml": ["xcs"], "application/ccxml+xml": ["ccxml"], "application/cdfx+xml": ["cdfx"], "application/cdmi-capability": ["cdmia"], "application/cdmi-container": ["cdmic"], "application/cdmi-domain": ["cdmid"], "application/cdmi-object": ["cdmio"], "application/cdmi-queue": ["cdmiq"], "application/cpl+xml": ["cpl"], "application/cu-seeme": ["cu"], "application/cwl": ["cwl"], "application/dash+xml": ["mpd"], "application/dash-patch+xml": ["mpp"], "application/davmount+xml": ["davmount"], "application/docbook+xml": ["dbk"], "application/dssc+der": ["dssc"], "application/dssc+xml": ["xdssc"], "application/ecmascript": ["ecma"], "application/emma+xml": ["emma"], "application/emotionml+xml": ["emotionml"], "application/epub+zip": ["epub"], "application/exi": ["exi"], "application/express": ["exp"], "application/fdf": ["fdf"], "application/fdt+xml": ["fdt"], "application/font-tdpfr": ["pfr"], "application/geo+json": ["geojson"], "application/gml+xml": ["gml"], "application/gpx+xml": ["gpx"], "application/gxf": ["gxf"], "application/gzip": ["gz"], "application/hjson": ["hjson"], "application/hyperstudio": ["stk"], "application/inkml+xml": ["ink", "inkml"], "application/ipfix": ["ipfix"], "application/its+xml": ["its"], "application/java-archive": ["jar", "war", "ear"], "application/java-serialized-object": ["ser"], "application/java-vm": ["class"], "application/javascript": ["*js"], "application/json": ["json", "map"], "application/json5": ["json5"], "application/jsonml+json": ["jsonml"], "application/ld+json": ["jsonld"], "application/lgr+xml": ["lgr"], "application/lost+xml": ["lostxml"], "application/mac-binhex40": ["hqx"], "application/mac-compactpro": ["cpt"], "application/mads+xml": ["mads"], "application/manifest+json": ["webmanifest"], "application/marc": ["mrc"], "application/marcxml+xml": ["mrcx"], "application/mathematica": ["ma", "nb", "mb"], "application/mathml+xml": ["mathml"], "application/mbox": ["mbox"], "application/media-policy-dataset+xml": ["mpf"], "application/mediaservercontrol+xml": ["mscml"], "application/metalink+xml": ["metalink"], "application/metalink4+xml": ["meta4"], "application/mets+xml": ["mets"], "application/mmt-aei+xml": ["maei"], "application/mmt-usd+xml": ["musd"], "application/mods+xml": ["mods"], "application/mp21": ["m21", "mp21"], "application/mp4": ["*mp4", "*mpg4", "mp4s", "m4p"], "application/msix": ["msix"], "application/msixbundle": ["msixbundle"], "application/msword": ["doc", "dot"], "application/mxf": ["mxf"], "application/n-quads": ["nq"], "application/n-triples": ["nt"], "application/node": ["cjs"], "application/octet-stream": ["bin", "dms", "lrf", "mar", "so", "dist", "distz", "pkg", "bpk", "dump", "elc", "deploy", "exe", "dll", "deb", "dmg", "iso", "img", "msi", "msp", "msm", "buffer"], "application/oda": ["oda"], "application/oebps-package+xml": ["opf"], "application/ogg": ["ogx"], "application/omdoc+xml": ["omdoc"], "application/onenote": ["onetoc", "onetoc2", "onetmp", "onepkg"], "application/oxps": ["oxps"], "application/p2p-overlay+xml": ["relo"], "application/patch-ops-error+xml": ["xer"], "application/pdf": ["pdf"], "application/pgp-encrypted": ["pgp"], "application/pgp-keys": ["asc"], "application/pgp-signature": ["sig", "*asc"], "application/pics-rules": ["prf"], "application/pkcs10": ["p10"], "application/pkcs7-mime": ["p7m", "p7c"], "application/pkcs7-signature": ["p7s"], "application/pkcs8": ["p8"], "application/pkix-attr-cert": ["ac"], "application/pkix-cert": ["cer"], "application/pkix-crl": ["crl"], "application/pkix-pkipath": ["pkipath"], "application/pkixcmp": ["pki"], "application/pls+xml": ["pls"], "application/postscript": ["ai", "eps", "ps"], "application/provenance+xml": ["provx"], "application/pskc+xml": ["pskcxml"], "application/raml+yaml": ["raml"], "application/rdf+xml": ["rdf", "owl"], "application/reginfo+xml": ["rif"], "application/relax-ng-compact-syntax": ["rnc"], "application/resource-lists+xml": ["rl"], "application/resource-lists-diff+xml": ["rld"], "application/rls-services+xml": ["rs"], "application/route-apd+xml": ["rapd"], "application/route-s-tsid+xml": ["sls"], "application/route-usd+xml": ["rusd"], "application/rpki-ghostbusters": ["gbr"], "application/rpki-manifest": ["mft"], "application/rpki-roa": ["roa"], "application/rsd+xml": ["rsd"], "application/rss+xml": ["rss"], "application/rtf": ["rtf"], "application/sbml+xml": ["sbml"], "application/scvp-cv-request": ["scq"], "application/scvp-cv-response": ["scs"], "application/scvp-vp-request": ["spq"], "application/scvp-vp-response": ["spp"], "application/sdp": ["sdp"], "application/senml+xml": ["senmlx"], "application/sensml+xml": ["sensmlx"], "application/set-payment-initiation": ["setpay"], "application/set-registration-initiation": ["setreg"], "application/shf+xml": ["shf"], "application/sieve": ["siv", "sieve"], "application/smil+xml": ["smi", "smil"], "application/sparql-query": ["rq"], "application/sparql-results+xml": ["srx"], "application/sql": ["sql"], "application/srgs": ["gram"], "application/srgs+xml": ["grxml"], "application/sru+xml": ["sru"], "application/ssdl+xml": ["ssdl"], "application/ssml+xml": ["ssml"], "application/swid+xml": ["swidtag"], "application/tei+xml": ["tei", "teicorpus"], "application/thraud+xml": ["tfi"], "application/timestamped-data": ["tsd"], "application/toml": ["toml"], "application/trig": ["trig"], "application/ttml+xml": ["ttml"], "application/ubjson": ["ubj"], "application/urc-ressheet+xml": ["rsheet"], "application/urc-targetdesc+xml": ["td"], "application/voicexml+xml": ["vxml"], "application/wasm": ["wasm"], "application/watcherinfo+xml": ["wif"], "application/widget": ["wgt"], "application/winhlp": ["hlp"], "application/wsdl+xml": ["wsdl"], "application/wspolicy+xml": ["wspolicy"], "application/xaml+xml": ["xaml"], "application/xcap-att+xml": ["xav"], "application/xcap-caps+xml": ["xca"], "application/xcap-diff+xml": ["xdf"], "application/xcap-el+xml": ["xel"], "application/xcap-ns+xml": ["xns"], "application/xenc+xml": ["xenc"], "application/xfdf": ["xfdf"], "application/xhtml+xml": ["xhtml", "xht"], "application/xliff+xml": ["xlf"], "application/xml": ["xml", "xsl", "xsd", "rng"], "application/xml-dtd": ["dtd"], "application/xop+xml": ["xop"], "application/xproc+xml": ["xpl"], "application/xslt+xml": ["*xsl", "xslt"], "application/xspf+xml": ["xspf"], "application/xv+xml": ["mxml", "xhvml", "xvml", "xvm"], "application/yang": ["yang"], "application/yin+xml": ["yin"], "application/zip": ["zip"], "audio/3gpp": ["*3gpp"], "audio/aac": ["adts", "aac"], "audio/adpcm": ["adp"], "audio/amr": ["amr"], "audio/basic": ["au", "snd"], "audio/midi": ["mid", "midi", "kar", "rmi"], "audio/mobile-xmf": ["mxmf"], "audio/mp3": ["*mp3"], "audio/mp4": ["m4a", "mp4a"], "audio/mpeg": ["mpga", "mp2", "mp2a", "mp3", "m2a", "m3a"], "audio/ogg": ["oga", "ogg", "spx", "opus"], "audio/s3m": ["s3m"], "audio/silk": ["sil"], "audio/wav": ["wav"], "audio/wave": ["*wav"], "audio/webm": ["weba"], "audio/xm": ["xm"], "font/collection": ["ttc"], "font/otf": ["otf"], "font/ttf": ["ttf"], "font/woff": ["woff"], "font/woff2": ["woff2"], "image/aces": ["exr"], "image/apng": ["apng"], "image/avci": ["avci"], "image/avcs": ["avcs"], "image/avif": ["avif"], "image/bmp": ["bmp", "dib"], "image/cgm": ["cgm"], "image/dicom-rle": ["drle"], "image/dpx": ["dpx"], "image/emf": ["emf"], "image/fits": ["fits"], "image/g3fax": ["g3"], "image/gif": ["gif"], "image/heic": ["heic"], "image/heic-sequence": ["heics"], "image/heif": ["heif"], "image/heif-sequence": ["heifs"], "image/hej2k": ["hej2"], "image/hsj2": ["hsj2"], "image/ief": ["ief"], "image/jls": ["jls"], "image/jp2": ["jp2", "jpg2"], "image/jpeg": ["jpeg", "jpg", "jpe"], "image/jph": ["jph"], "image/jphc": ["jhc"], "image/jpm": ["jpm", "jpgm"], "image/jpx": ["jpx", "jpf"], "image/jxr": ["jxr"], "image/jxra": ["jxra"], "image/jxrs": ["jxrs"], "image/jxs": ["jxs"], "image/jxsc": ["jxsc"], "image/jxsi": ["jxsi"], "image/jxss": ["jxss"], "image/ktx": ["ktx"], "image/ktx2": ["ktx2"], "image/png": ["png"], "image/sgi": ["sgi"], "image/svg+xml": ["svg", "svgz"], "image/t38": ["t38"], "image/tiff": ["tif", "tiff"], "image/tiff-fx": ["tfx"], "image/webp": ["webp"], "image/wmf": ["wmf"], "message/disposition-notification": ["disposition-notification"], "message/global": ["u8msg"], "message/global-delivery-status": ["u8dsn"], "message/global-disposition-notification": ["u8mdn"], "message/global-headers": ["u8hdr"], "message/rfc822": ["eml", "mime"], "model/3mf": ["3mf"], "model/gltf+json": ["gltf"], "model/gltf-binary": ["glb"], "model/iges": ["igs", "iges"], "model/jt": ["jt"], "model/mesh": ["msh", "mesh", "silo"], "model/mtl": ["mtl"], "model/obj": ["obj"], "model/prc": ["prc"], "model/step+xml": ["stpx"], "model/step+zip": ["stpz"], "model/step-xml+zip": ["stpxz"], "model/stl": ["stl"], "model/u3d": ["u3d"], "model/vrml": ["wrl", "vrml"], "model/x3d+binary": ["*x3db", "x3dbz"], "model/x3d+fastinfoset": ["x3db"], "model/x3d+vrml": ["*x3dv", "x3dvz"], "model/x3d+xml": ["x3d", "x3dz"], "model/x3d-vrml": ["x3dv"], "text/cache-manifest": ["appcache", "manifest"], "text/calendar": ["ics", "ifb"], "text/coffeescript": ["coffee", "litcoffee"], "text/css": ["css"], "text/csv": ["csv"], "text/html": ["html", "htm", "shtml"], "text/jade": ["jade"], "text/javascript": ["js", "mjs"], "text/jsx": ["jsx"], "text/less": ["less"], "text/markdown": ["md", "markdown"], "text/mathml": ["mml"], "text/mdx": ["mdx"], "text/n3": ["n3"], "text/plain": ["txt", "text", "conf", "def", "list", "log", "in", "ini"], "text/richtext": ["rtx"], "text/rtf": ["*rtf"], "text/sgml": ["sgml", "sgm"], "text/shex": ["shex"], "text/slim": ["slim", "slm"], "text/spdx": ["spdx"], "text/stylus": ["stylus", "styl"], "text/tab-separated-values": ["tsv"], "text/troff": ["t", "tr", "roff", "man", "me", "ms"], "text/turtle": ["ttl"], "text/uri-list": ["uri", "uris", "urls"], "text/vcard": ["vcard"], "text/vtt": ["vtt"], "text/wgsl": ["wgsl"], "text/xml": ["*xml"], "text/yaml": ["yaml", "yml"], "video/3gpp": ["3gp", "3gpp"], "video/3gpp2": ["3g2"], "video/h261": ["h261"], "video/h263": ["h263"], "video/h264": ["h264"], "video/iso.segment": ["m4s"], "video/jpeg": ["jpgv"], "video/jpm": ["*jpm", "*jpgm"], "video/mj2": ["mj2", "mjp2"], "video/mp2t": ["ts"], "video/mp4": ["mp4", "mp4v", "mpg4"], "video/mpeg": ["mpeg", "mpg", "mpe", "m1v", "m2v"], "video/ogg": ["ogv"], "video/quicktime": ["qt", "mov"], "video/webm": ["webm"] };
1575
+ Object.freeze(types);
1576
+
1577
+ var __classPrivateFieldGet = (null && null.__classPrivateFieldGet) || function (receiver, state, kind, f) {
1578
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
1579
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
1580
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
1581
+ };
1582
+ var _Mime_extensionToType, _Mime_typeToExtension, _Mime_typeToExtensions;
1583
+ class Mime {
1584
+ constructor(...args) {
1585
+ _Mime_extensionToType.set(this, new Map());
1586
+ _Mime_typeToExtension.set(this, new Map());
1587
+ _Mime_typeToExtensions.set(this, new Map());
1588
+ for (const arg of args) {
1589
+ this.define(arg);
1590
+ }
1591
+ }
1592
+ define(typeMap, force = false) {
1593
+ for (let [type, extensions] of Object.entries(typeMap)) {
1594
+ type = type.toLowerCase();
1595
+ extensions = extensions.map((ext) => ext.toLowerCase());
1596
+ if (!__classPrivateFieldGet(this, _Mime_typeToExtensions, "f").has(type)) {
1597
+ __classPrivateFieldGet(this, _Mime_typeToExtensions, "f").set(type, new Set());
1598
+ }
1599
+ const allExtensions = __classPrivateFieldGet(this, _Mime_typeToExtensions, "f").get(type);
1600
+ let first = true;
1601
+ for (let extension of extensions) {
1602
+ const starred = extension.startsWith('*');
1603
+ extension = starred ? extension.slice(1) : extension;
1604
+ allExtensions?.add(extension);
1605
+ if (first) {
1606
+ __classPrivateFieldGet(this, _Mime_typeToExtension, "f").set(type, extension);
1607
+ }
1608
+ first = false;
1609
+ if (starred)
1610
+ continue;
1611
+ const currentType = __classPrivateFieldGet(this, _Mime_extensionToType, "f").get(extension);
1612
+ if (currentType && currentType != type && !force) {
1613
+ throw new Error(`"${type} -> ${extension}" conflicts with "${currentType} -> ${extension}". Pass \`force=true\` to override this definition.`);
1614
+ }
1615
+ __classPrivateFieldGet(this, _Mime_extensionToType, "f").set(extension, type);
1616
+ }
1617
+ }
1618
+ return this;
1619
+ }
1620
+ getType(path) {
1621
+ if (typeof path !== 'string')
1622
+ return null;
1623
+ const last = path.replace(/^.*[/\\]/, '').toLowerCase();
1624
+ const ext = last.replace(/^.*\./, '').toLowerCase();
1625
+ const hasPath = last.length < path.length;
1626
+ const hasDot = ext.length < last.length - 1;
1627
+ if (!hasDot && hasPath)
1628
+ return null;
1629
+ return __classPrivateFieldGet(this, _Mime_extensionToType, "f").get(ext) ?? null;
1630
+ }
1631
+ getExtension(type) {
1632
+ if (typeof type !== 'string')
1633
+ return null;
1634
+ type = type?.split?.(';')[0];
1635
+ return ((type && __classPrivateFieldGet(this, _Mime_typeToExtension, "f").get(type.trim().toLowerCase())) ?? null);
1636
+ }
1637
+ getAllExtensions(type) {
1638
+ if (typeof type !== 'string')
1639
+ return null;
1640
+ return __classPrivateFieldGet(this, _Mime_typeToExtensions, "f").get(type.toLowerCase()) ?? null;
1641
+ }
1642
+ _freeze() {
1643
+ this.define = () => {
1644
+ throw new Error('define() not allowed for built-in Mime objects. See https://github.com/broofa/mime/blob/main/README.md#custom-mime-instances');
1645
+ };
1646
+ Object.freeze(this);
1647
+ for (const extensions of __classPrivateFieldGet(this, _Mime_typeToExtensions, "f").values()) {
1648
+ Object.freeze(extensions);
1649
+ }
1650
+ return this;
1651
+ }
1652
+ _getTestState() {
1653
+ return {
1654
+ types: __classPrivateFieldGet(this, _Mime_extensionToType, "f"),
1655
+ extensions: __classPrivateFieldGet(this, _Mime_typeToExtension, "f"),
1656
+ };
1657
+ }
1658
+ }
1659
+ _Mime_extensionToType = new WeakMap(), _Mime_typeToExtension = new WeakMap(), _Mime_typeToExtensions = new WeakMap();
1660
+
1661
+ var mime = new Mime(types)._freeze();
1662
+
1692
1663
  function assertFileAccess(path, project) {
1693
1664
  if (!isFileServingAllowed(path, project.server) && !isFileServingAllowed(path, project.ctx.server)) {
1694
1665
  throw new Error(
@@ -1718,12 +1689,22 @@ const removeFile = async ({ project, testPath = process.cwd() }, path) => {
1718
1689
  assertFileAccess(filepath, project);
1719
1690
  await promises.rm(filepath);
1720
1691
  };
1692
+ const _fileInfo = async ({ project, testPath = process.cwd() }, path, encoding) => {
1693
+ const filepath = resolve$1(dirname$1(testPath), path);
1694
+ assertFileAccess(filepath, project);
1695
+ const content = await promises.readFile(filepath, encoding || "base64");
1696
+ return {
1697
+ content,
1698
+ basename: basename$1(filepath),
1699
+ mime: mime.getType(filepath)
1700
+ };
1701
+ };
1721
1702
 
1722
1703
  const screenshot = async (context, name, options = {}) => {
1723
1704
  if (!context.testPath) {
1724
1705
  throw new Error(`Cannot take a screenshot without a test path`);
1725
1706
  }
1726
- const path = options.path ? resolve(context.testPath, options.path) : resolveScreenshotPath(
1707
+ const path = options.path ? resolve(dirname(context.testPath), options.path) : resolveScreenshotPath(
1727
1708
  context.testPath,
1728
1709
  name,
1729
1710
  context.project.config
@@ -1786,6 +1767,8 @@ var builtinCommands = {
1786
1767
  readFile,
1787
1768
  removeFile,
1788
1769
  writeFile,
1770
+ __vitest_fileInfo: _fileInfo,
1771
+ __vitest_upload: upload,
1789
1772
  __vitest_click: click,
1790
1773
  __vitest_dblClick: dblClick,
1791
1774
  __vitest_tripleClick: tripleClick,
@@ -1844,7 +1827,7 @@ async function generateContextFile(server) {
1844
1827
  );
1845
1828
  const distContextPath = slash(`/@fs/${resolve(__dirname, "context.js")}`);
1846
1829
  return `
1847
- import { page, userEvent as __userEvent_CDP__, cdp } from '${distContextPath}'
1830
+ import { page, createUserEvent, cdp } from '${distContextPath}'
1848
1831
  ${userEventNonProviderImport}
1849
1832
  const filepath = () => ${filepathCode}
1850
1833
  const rpc = () => __vitest_worker__.rpc
@@ -1861,35 +1844,13 @@ export const server = {
1861
1844
  config: __vitest_browser_runner__.config,
1862
1845
  }
1863
1846
  export const commands = server.commands
1864
- export const userEvent = ${getUserEvent(provider)}
1847
+ export const userEvent = createUserEvent(_userEventSetup)
1865
1848
  export { page, cdp }
1866
1849
  `;
1867
1850
  }
1868
- function getUserEvent(provider) {
1869
- if (provider.name !== "preview") {
1870
- return "__userEvent_CDP__";
1871
- }
1872
- return `{
1873
- ..._userEventSetup,
1874
- setup() {
1875
- const userEvent = __vitest_user_event__.setup()
1876
- userEvent.setup = this.setup
1877
- userEvent.fill = this.fill.bind(userEvent)
1878
- userEvent.dragAndDrop = this.dragAndDrop
1879
- return userEvent
1880
- },
1881
- async fill(element, text) {
1882
- await this.clear(element)
1883
- await this.type(element, text)
1884
- },
1885
- dragAndDrop: async () => {
1886
- throw new Error('Provider "preview" does not support dragging elements')
1887
- }
1888
- }`;
1889
- }
1890
1851
  async function getUserEventImport(provider, resolve2) {
1891
1852
  if (provider.name !== "preview") {
1892
- return "";
1853
+ return "const _userEventSetup = undefined";
1893
1854
  }
1894
1855
  const resolved = await resolve2("@testing-library/user-event", __dirname);
1895
1856
  if (!resolved) {
@@ -1902,53 +1863,6 @@ const _userEventSetup = __vitest_user_event__.setup()
1902
1863
  `;
1903
1864
  }
1904
1865
 
1905
- function injectDynamicImport(code, id, parse) {
1906
- const s = new MagicString(code);
1907
- let ast;
1908
- try {
1909
- ast = parse(code);
1910
- } catch (err) {
1911
- console.error(`Cannot parse ${id}:
1912
- ${err.message}`);
1913
- return;
1914
- }
1915
- esmWalker(ast, {
1916
- // TODO: make env updatable
1917
- onImportMeta() {
1918
- },
1919
- onDynamicImport(node) {
1920
- const replaceString = "__vitest_browser_runner__.wrapModule(() => import(";
1921
- const importSubstring = code.substring(node.start, node.end);
1922
- const hasIgnore = importSubstring.includes("/* @vite-ignore */");
1923
- s.overwrite(
1924
- node.start,
1925
- node.source.start,
1926
- replaceString + (hasIgnore ? "/* @vite-ignore */ " : "")
1927
- );
1928
- s.overwrite(node.end - 1, node.end, "))");
1929
- }
1930
- });
1931
- return {
1932
- ast,
1933
- code: s.toString(),
1934
- map: s.generateMap({ hires: "boundary", source: id })
1935
- };
1936
- }
1937
-
1938
- const regexDynamicImport = /import\s*\(/;
1939
- var DynamicImport = () => {
1940
- return {
1941
- name: "vitest:browser:esm-injector",
1942
- enforce: "post",
1943
- transform(source, id) {
1944
- if (!regexDynamicImport.test(source)) {
1945
- return;
1946
- }
1947
- return injectDynamicImport(source, id, this.parse);
1948
- }
1949
- };
1950
- };
1951
-
1952
1866
  async function resolveOrchestrator(server, url, res) {
1953
1867
  const project = server.project;
1954
1868
  let contextId = url.searchParams.get("contextId");
@@ -2194,6 +2108,28 @@ var BrowserPlugin = (browserServer, base = "/") => {
2194
2108
  resolve(distDir, "utils.js"),
2195
2109
  ...project.config.snapshotSerializers || []
2196
2110
  ];
2111
+ const exclude = [
2112
+ "vitest",
2113
+ "vitest/utils",
2114
+ "vitest/browser",
2115
+ "vitest/runners",
2116
+ "@vitest/browser",
2117
+ "@vitest/browser/client",
2118
+ "@vitest/utils",
2119
+ "@vitest/utils/source-map",
2120
+ "@vitest/runner",
2121
+ "@vitest/spy",
2122
+ "@vitest/utils/error",
2123
+ "@vitest/snapshot",
2124
+ "@vitest/expect",
2125
+ "std-env",
2126
+ "tinybench",
2127
+ "tinyspy",
2128
+ "tinyrainbow",
2129
+ "pathe",
2130
+ "msw",
2131
+ "msw/browser"
2132
+ ];
2197
2133
  if (project.config.diff) {
2198
2134
  entries.push(project.config.diff);
2199
2135
  }
@@ -2204,11 +2140,13 @@ var BrowserPlugin = (browserServer, base = "/") => {
2204
2140
  const path = tryResolve("@vitest/coverage-v8", [project.ctx.config.root]);
2205
2141
  if (path) {
2206
2142
  entries.push(path);
2143
+ exclude.push("@vitest/coverage-v8/browser");
2207
2144
  }
2208
2145
  } else if (provider === "istanbul") {
2209
2146
  const path = tryResolve("@vitest/coverage-istanbul", [project.ctx.config.root]);
2210
2147
  if (path) {
2211
2148
  entries.push(path);
2149
+ exclude.push("@vitest/coverage-istanbul");
2212
2150
  }
2213
2151
  } else if (provider === "custom" && coverage.customProviderModule) {
2214
2152
  entries.push(coverage.customProviderModule);
@@ -2230,28 +2168,6 @@ var BrowserPlugin = (browserServer, base = "/") => {
2230
2168
  if (vue) {
2231
2169
  include.push(vue);
2232
2170
  }
2233
- const exclude = [
2234
- "vitest",
2235
- "vitest/utils",
2236
- "vitest/browser",
2237
- "vitest/runners",
2238
- "@vitest/browser",
2239
- "@vitest/browser/client",
2240
- "@vitest/utils",
2241
- "@vitest/utils/source-map",
2242
- "@vitest/runner",
2243
- "@vitest/spy",
2244
- "@vitest/utils/error",
2245
- "@vitest/snapshot",
2246
- "@vitest/expect",
2247
- "std-env",
2248
- "tinybench",
2249
- "tinyspy",
2250
- "tinyrainbow",
2251
- "pathe",
2252
- "msw",
2253
- "msw/browser"
2254
- ];
2255
2171
  const svelte = tryResolve("vitest-browser-svelte", [project.ctx.config.root]);
2256
2172
  if (svelte) {
2257
2173
  exclude.push(svelte);
@@ -2307,7 +2223,9 @@ var BrowserPlugin = (browserServer, base = "/") => {
2307
2223
  }
2308
2224
  },
2309
2225
  BrowserContext(browserServer),
2310
- DynamicImport(),
2226
+ dynamicImportPlugin({
2227
+ globalThisAccessor: '"__vitest_browser_runner__"'
2228
+ }),
2311
2229
  {
2312
2230
  name: "vitest:browser:config",
2313
2231
  enforce: "post",
@@ -2343,6 +2261,23 @@ var BrowserPlugin = (browserServer, base = "/") => {
2343
2261
  };
2344
2262
  }
2345
2263
  },
2264
+ {
2265
+ name: "vitest:browser:in-source-tests",
2266
+ transform(code, id) {
2267
+ if (!project.isTestFile(id) || !code.includes("import.meta.vitest")) {
2268
+ return;
2269
+ }
2270
+ const s = new MagicString(code, { filename: cleanUrl(id) });
2271
+ s.prepend(
2272
+ `import.meta.vitest = __vitest_index__;
2273
+ `
2274
+ );
2275
+ return {
2276
+ code: s.toString(),
2277
+ map: s.generateMap({ hires: true })
2278
+ };
2279
+ }
2280
+ },
2346
2281
  // TODO: remove this when @testing-library/vue supports ESM
2347
2282
  {
2348
2283
  name: "vitest:browser:support-testing-library",
@@ -2420,14 +2355,18 @@ function resolveCoverageFolder(project) {
2420
2355
  }
2421
2356
  return [resolve(root, subdir), `/${basename(root)}/${subdir}/`];
2422
2357
  }
2358
+ const postfixRE = /[?#].*$/;
2359
+ function cleanUrl(url) {
2360
+ return url.replace(postfixRE, "");
2361
+ }
2423
2362
 
2424
2363
  const debug = createDebugger("vitest:browser:pool");
2364
+ async function waitForTests(method, contextId, project, files) {
2365
+ const context = project.browser.state.createAsyncContext(method, contextId, files);
2366
+ return await context;
2367
+ }
2425
2368
  function createBrowserPool(ctx) {
2426
2369
  const providers = /* @__PURE__ */ new Set();
2427
- const waitForTests = async (method, contextId, project, files) => {
2428
- const context = project.browser.state.createAsyncContext(method, contextId, files);
2429
- return await context;
2430
- };
2431
2370
  const executeTests = async (method, project, files) => {
2432
2371
  ctx.state.clearFiles(project, files);
2433
2372
  const browser = project.browser;
@@ -2441,6 +2380,20 @@ function createBrowserPool(ctx) {
2441
2380
  `Can't find browser origin URL for project "${project.getName()}" when running tests for files "${files.join('", "')}"`
2442
2381
  );
2443
2382
  }
2383
+ async function setBreakpoint(contextId, file) {
2384
+ if (!project.config.inspector.waitForDebugger) {
2385
+ return;
2386
+ }
2387
+ if (!provider.getCDPSession) {
2388
+ throw new Error("Unable to set breakpoint, CDP not supported");
2389
+ }
2390
+ const session = await provider.getCDPSession(contextId);
2391
+ await session.send("Debugger.enable", {});
2392
+ await session.send("Debugger.setBreakpointByUrl", {
2393
+ lineNumber: 0,
2394
+ urlRegex: escapePathToRegexp(file)
2395
+ });
2396
+ }
2444
2397
  const filesPerThread = Math.ceil(files.length / threadsCount);
2445
2398
  const chunks = [];
2446
2399
  for (let i = 0; i < files.length; i += filesPerThread) {
@@ -2477,7 +2430,7 @@ function createBrowserPool(ctx) {
2477
2430
  );
2478
2431
  const url = new URL("/", origin);
2479
2432
  url.searchParams.set("contextId", contextId);
2480
- const page = provider.openPage(contextId, url.toString()).then(() => waitPromise);
2433
+ const page = provider.openPage(contextId, url.toString(), () => setBreakpoint(contextId, files2[0])).then(() => waitPromise);
2481
2434
  promises.push(page);
2482
2435
  }
2483
2436
  });
@@ -2522,15 +2475,47 @@ function createBrowserPool(ctx) {
2522
2475
  collectTests: (files) => runWorkspaceTests("collect", files)
2523
2476
  };
2524
2477
  }
2478
+ function escapePathToRegexp(path) {
2479
+ return path.replace(/[/\\.?*()^${}|[\]+]/g, "\\$&");
2480
+ }
2525
2481
 
2526
2482
  async function createBrowserServer(project, configFile, prePlugins = [], postPlugins = []) {
2483
+ if (project.ctx.version !== version) {
2484
+ project.ctx.logger.warn(
2485
+ c.yellow(
2486
+ `Loaded ${c.inverse(c.yellow(` vitest@${project.ctx.version} `))} and ${c.inverse(c.yellow(` @vitest/browser@${version} `))}.
2487
+ Running mixed versions is not supported and may lead into bugs
2488
+ Update your dependencies and make sure the versions match.`
2489
+ )
2490
+ );
2491
+ }
2527
2492
  const server = new BrowserServer(project, "/");
2528
2493
  const configPath = typeof configFile === "string" ? configFile : false;
2529
- const vite = await createServer({
2494
+ const logLevel = process.env.VITEST_BROWSER_DEBUG ?? "info";
2495
+ const logger = createViteLogger(logLevel);
2496
+ const vite = await createViteServer({
2530
2497
  ...project.options,
2531
2498
  // spread project config inlined in root workspace config
2532
2499
  base: "/",
2533
- logLevel: process.env.VITEST_BROWSER_DEBUG ?? "info",
2500
+ logLevel,
2501
+ customLogger: {
2502
+ ...logger,
2503
+ info(msg, options) {
2504
+ logger.info(msg, options);
2505
+ if (msg.includes("optimized dependencies changed. reloading")) {
2506
+ logger.warn(
2507
+ [
2508
+ c.yellow(`
2509
+ ${c.bold("[vitest]")} Vite unexpectedly reloaded a test. This may cause tests to fail, lead to flaky behaviour or duplicated test runs.
2510
+ `),
2511
+ c.yellow(`For a stable experience, please add mentioned dependencies to your config's ${c.bold("`optimizeDeps.include`")} field manually.
2512
+
2513
+ `)
2514
+ ].join("")
2515
+ );
2516
+ }
2517
+ }
2518
+ },
2534
2519
  mode: project.config.mode,
2535
2520
  configFile: configPath,
2536
2521
  // watch is handled by Vitest