@vitest/browser 2.1.0-beta.5 → 2.1.0-beta.7
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/context.d.ts +11 -0
- package/dist/client/.vite/manifest.json +6 -6
- package/dist/client/__vitest__/assets/{index-JTfsnJeu.css → index-BevOiAy-.css} +1 -1
- package/dist/client/__vitest__/assets/index-CEU6kzsk.js +52 -0
- package/dist/client/__vitest__/index.html +2 -2
- package/dist/client/__vitest_browser__/{orchestrator-CnT07ZeZ.js → orchestrator-qtq9EW1J.js} +243 -91
- package/dist/client/__vitest_browser__/preload-helper-D-WYp1PK.js +317 -0
- package/dist/client/__vitest_browser__/{tester-BG73i7yi.js → tester-Bm6k0JOu.js} +588 -379
- package/dist/client/esm-client-injector.js +1 -0
- package/dist/client/orchestrator.html +2 -2
- package/dist/client/tester/tester.html +2 -2
- package/dist/context.js +3 -0
- package/dist/{index-DcU_z8HM.js → index-Cgg35wOd.js} +19 -0
- package/dist/index.d.ts +7 -13
- package/dist/index.js +289 -267
- package/dist/locators/index.d.ts +1 -0
- package/dist/locators/index.js +1 -1
- package/dist/locators/playwright.js +1 -1
- package/dist/locators/preview.js +4 -1
- package/dist/locators/webdriverio.js +1 -1
- package/dist/providers.js +1 -1
- package/dist/state.js +1 -1
- package/dist/{webdriver-BdVqnfdE.js → webdriver-Cv9wga63.js} +10 -1
- package/package.json +13 -10
- package/dist/client/__vitest__/assets/index-BzrnDBXn.js +0 -52
- package/dist/client/__vitest_browser__/preload-helper-BrGs795G.js +0 -301
package/dist/index.js
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import { createDebugger, isFileServingAllowed, getFilePoolName, resolveApiServerConfig, resolveFsAllow, distDir,
|
|
2
|
-
import
|
|
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 {
|
|
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 {
|
|
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-beta.7";
|
|
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
|
-
|
|
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,
|
|
697
|
-
return resolveMock(
|
|
554
|
+
resolveMock(rawId, importer, options) {
|
|
555
|
+
return mockResolver.resolveMock(rawId, importer, options);
|
|
698
556
|
},
|
|
699
557
|
invalidate(ids) {
|
|
700
|
-
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
@@ -1869,15 +1852,32 @@ function getUserEvent(provider) {
|
|
|
1869
1852
|
if (provider.name !== "preview") {
|
|
1870
1853
|
return "__userEvent_CDP__";
|
|
1871
1854
|
}
|
|
1872
|
-
return `{
|
|
1855
|
+
return String.raw`{
|
|
1873
1856
|
..._userEventSetup,
|
|
1874
1857
|
setup() {
|
|
1875
1858
|
const userEvent = __vitest_user_event__.setup()
|
|
1876
1859
|
userEvent.setup = this.setup
|
|
1877
1860
|
userEvent.fill = this.fill.bind(userEvent)
|
|
1861
|
+
userEvent._upload = userEvent.upload.bind(userEvent)
|
|
1862
|
+
userEvent.upload = this.upload.bind(userEvent)
|
|
1878
1863
|
userEvent.dragAndDrop = this.dragAndDrop
|
|
1879
1864
|
return userEvent
|
|
1880
1865
|
},
|
|
1866
|
+
async upload(element, file) {
|
|
1867
|
+
const uploadPromise = (Array.isArray(file) ? file : [file]).map(async (file) => {
|
|
1868
|
+
if (typeof file !== 'string') {
|
|
1869
|
+
return file
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1872
|
+
const { content: base64, basename, mime } = await rpc().triggerCommand(contextId, "__vitest_fileInfo", filepath(), [file, 'base64'])
|
|
1873
|
+
const fileInstance = fetch(base64)
|
|
1874
|
+
.then(r => r.blob())
|
|
1875
|
+
.then(blob => new File([blob], basename, { type: mime }))
|
|
1876
|
+
return fileInstance
|
|
1877
|
+
})
|
|
1878
|
+
const uploadFiles = await Promise.all(uploadPromise)
|
|
1879
|
+
return this._upload(element, uploadFiles)
|
|
1880
|
+
},
|
|
1881
1881
|
async fill(element, text) {
|
|
1882
1882
|
await this.clear(element)
|
|
1883
1883
|
await this.type(element, text)
|
|
@@ -1902,53 +1902,6 @@ const _userEventSetup = __vitest_user_event__.setup()
|
|
|
1902
1902
|
`;
|
|
1903
1903
|
}
|
|
1904
1904
|
|
|
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
1905
|
async function resolveOrchestrator(server, url, res) {
|
|
1953
1906
|
const project = server.project;
|
|
1954
1907
|
let contextId = url.searchParams.get("contextId");
|
|
@@ -2012,7 +1965,7 @@ async function resolveTester(server, url, res) {
|
|
|
2012
1965
|
const { contextId, testFile } = server.resolveTesterUrl(url.pathname);
|
|
2013
1966
|
const project = server.project;
|
|
2014
1967
|
const state = server.state;
|
|
2015
|
-
const testFiles = await project.globTestFiles();
|
|
1968
|
+
const { testFiles } = await project.globTestFiles();
|
|
2016
1969
|
const tests = testFile === "__vitest_all__" || !testFiles.includes(testFile) ? "__vitest_browser_runner__.files" : JSON.stringify([testFile]);
|
|
2017
1970
|
const iframeId = JSON.stringify(testFile);
|
|
2018
1971
|
const context = state.getContext(contextId);
|
|
@@ -2174,7 +2127,7 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2174
2127
|
name: "vitest:browser:tests",
|
|
2175
2128
|
enforce: "pre",
|
|
2176
2129
|
async config() {
|
|
2177
|
-
const allTestFiles = await project.globTestFiles();
|
|
2130
|
+
const { testFiles: allTestFiles } = await project.globTestFiles();
|
|
2178
2131
|
const browserTestFiles = allTestFiles.filter(
|
|
2179
2132
|
(file) => getFilePoolName(project, file) === "browser"
|
|
2180
2133
|
);
|
|
@@ -2194,6 +2147,28 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2194
2147
|
resolve(distDir, "utils.js"),
|
|
2195
2148
|
...project.config.snapshotSerializers || []
|
|
2196
2149
|
];
|
|
2150
|
+
const exclude = [
|
|
2151
|
+
"vitest",
|
|
2152
|
+
"vitest/utils",
|
|
2153
|
+
"vitest/browser",
|
|
2154
|
+
"vitest/runners",
|
|
2155
|
+
"@vitest/browser",
|
|
2156
|
+
"@vitest/browser/client",
|
|
2157
|
+
"@vitest/utils",
|
|
2158
|
+
"@vitest/utils/source-map",
|
|
2159
|
+
"@vitest/runner",
|
|
2160
|
+
"@vitest/spy",
|
|
2161
|
+
"@vitest/utils/error",
|
|
2162
|
+
"@vitest/snapshot",
|
|
2163
|
+
"@vitest/expect",
|
|
2164
|
+
"std-env",
|
|
2165
|
+
"tinybench",
|
|
2166
|
+
"tinyspy",
|
|
2167
|
+
"tinyrainbow",
|
|
2168
|
+
"pathe",
|
|
2169
|
+
"msw",
|
|
2170
|
+
"msw/browser"
|
|
2171
|
+
];
|
|
2197
2172
|
if (project.config.diff) {
|
|
2198
2173
|
entries.push(project.config.diff);
|
|
2199
2174
|
}
|
|
@@ -2204,11 +2179,13 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2204
2179
|
const path = tryResolve("@vitest/coverage-v8", [project.ctx.config.root]);
|
|
2205
2180
|
if (path) {
|
|
2206
2181
|
entries.push(path);
|
|
2182
|
+
exclude.push("@vitest/coverage-v8/browser");
|
|
2207
2183
|
}
|
|
2208
2184
|
} else if (provider === "istanbul") {
|
|
2209
2185
|
const path = tryResolve("@vitest/coverage-istanbul", [project.ctx.config.root]);
|
|
2210
2186
|
if (path) {
|
|
2211
2187
|
entries.push(path);
|
|
2188
|
+
exclude.push("@vitest/coverage-istanbul");
|
|
2212
2189
|
}
|
|
2213
2190
|
} else if (provider === "custom" && coverage.customProviderModule) {
|
|
2214
2191
|
entries.push(coverage.customProviderModule);
|
|
@@ -2230,28 +2207,6 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2230
2207
|
if (vue) {
|
|
2231
2208
|
include.push(vue);
|
|
2232
2209
|
}
|
|
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
2210
|
const svelte = tryResolve("vitest-browser-svelte", [project.ctx.config.root]);
|
|
2256
2211
|
if (svelte) {
|
|
2257
2212
|
exclude.push(svelte);
|
|
@@ -2307,7 +2262,9 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2307
2262
|
}
|
|
2308
2263
|
},
|
|
2309
2264
|
BrowserContext(browserServer),
|
|
2310
|
-
|
|
2265
|
+
dynamicImportPlugin({
|
|
2266
|
+
globalThisAccessor: '"__vitest_browser_runner__"'
|
|
2267
|
+
}),
|
|
2311
2268
|
{
|
|
2312
2269
|
name: "vitest:browser:config",
|
|
2313
2270
|
enforce: "post",
|
|
@@ -2343,6 +2300,23 @@ var BrowserPlugin = (browserServer, base = "/") => {
|
|
|
2343
2300
|
};
|
|
2344
2301
|
}
|
|
2345
2302
|
},
|
|
2303
|
+
{
|
|
2304
|
+
name: "vitest:browser:in-source-tests",
|
|
2305
|
+
transform(code, id) {
|
|
2306
|
+
if (!project.isTestFile(id) || !code.includes("import.meta.vitest")) {
|
|
2307
|
+
return;
|
|
2308
|
+
}
|
|
2309
|
+
const s = new MagicString(code, { filename: cleanUrl(id) });
|
|
2310
|
+
s.prepend(
|
|
2311
|
+
`import.meta.vitest = __vitest_index__;
|
|
2312
|
+
`
|
|
2313
|
+
);
|
|
2314
|
+
return {
|
|
2315
|
+
code: s.toString(),
|
|
2316
|
+
map: s.generateMap({ hires: true })
|
|
2317
|
+
};
|
|
2318
|
+
}
|
|
2319
|
+
},
|
|
2346
2320
|
// TODO: remove this when @testing-library/vue supports ESM
|
|
2347
2321
|
{
|
|
2348
2322
|
name: "vitest:browser:support-testing-library",
|
|
@@ -2420,14 +2394,18 @@ function resolveCoverageFolder(project) {
|
|
|
2420
2394
|
}
|
|
2421
2395
|
return [resolve(root, subdir), `/${basename(root)}/${subdir}/`];
|
|
2422
2396
|
}
|
|
2397
|
+
const postfixRE = /[?#].*$/;
|
|
2398
|
+
function cleanUrl(url) {
|
|
2399
|
+
return url.replace(postfixRE, "");
|
|
2400
|
+
}
|
|
2423
2401
|
|
|
2424
2402
|
const debug = createDebugger("vitest:browser:pool");
|
|
2403
|
+
async function waitForTests(method, contextId, project, files) {
|
|
2404
|
+
const context = project.browser.state.createAsyncContext(method, contextId, files);
|
|
2405
|
+
return await context;
|
|
2406
|
+
}
|
|
2425
2407
|
function createBrowserPool(ctx) {
|
|
2426
2408
|
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
2409
|
const executeTests = async (method, project, files) => {
|
|
2432
2410
|
ctx.state.clearFiles(project, files);
|
|
2433
2411
|
const browser = project.browser;
|
|
@@ -2441,6 +2419,20 @@ function createBrowserPool(ctx) {
|
|
|
2441
2419
|
`Can't find browser origin URL for project "${project.getName()}" when running tests for files "${files.join('", "')}"`
|
|
2442
2420
|
);
|
|
2443
2421
|
}
|
|
2422
|
+
async function setBreakpoint(contextId, file) {
|
|
2423
|
+
if (!project.config.inspector.waitForDebugger) {
|
|
2424
|
+
return;
|
|
2425
|
+
}
|
|
2426
|
+
if (!provider.getCDPSession) {
|
|
2427
|
+
throw new Error("Unable to set breakpoint, CDP not supported");
|
|
2428
|
+
}
|
|
2429
|
+
const session = await provider.getCDPSession(contextId);
|
|
2430
|
+
await session.send("Debugger.enable", {});
|
|
2431
|
+
await session.send("Debugger.setBreakpointByUrl", {
|
|
2432
|
+
lineNumber: 0,
|
|
2433
|
+
urlRegex: escapePathToRegexp(file)
|
|
2434
|
+
});
|
|
2435
|
+
}
|
|
2444
2436
|
const filesPerThread = Math.ceil(files.length / threadsCount);
|
|
2445
2437
|
const chunks = [];
|
|
2446
2438
|
for (let i = 0; i < files.length; i += filesPerThread) {
|
|
@@ -2477,7 +2469,7 @@ function createBrowserPool(ctx) {
|
|
|
2477
2469
|
);
|
|
2478
2470
|
const url = new URL("/", origin);
|
|
2479
2471
|
url.searchParams.set("contextId", contextId);
|
|
2480
|
-
const page = provider.openPage(contextId, url.toString()).then(() => waitPromise);
|
|
2472
|
+
const page = provider.openPage(contextId, url.toString(), () => setBreakpoint(contextId, files2[0])).then(() => waitPromise);
|
|
2481
2473
|
promises.push(page);
|
|
2482
2474
|
}
|
|
2483
2475
|
});
|
|
@@ -2522,17 +2514,47 @@ function createBrowserPool(ctx) {
|
|
|
2522
2514
|
collectTests: (files) => runWorkspaceTests("collect", files)
|
|
2523
2515
|
};
|
|
2524
2516
|
}
|
|
2517
|
+
function escapePathToRegexp(path) {
|
|
2518
|
+
return path.replace(/[/\\.?*()^${}|[\]+]/g, "\\$&");
|
|
2519
|
+
}
|
|
2525
2520
|
|
|
2526
2521
|
async function createBrowserServer(project, configFile, prePlugins = [], postPlugins = []) {
|
|
2522
|
+
if (project.ctx.version !== version) {
|
|
2523
|
+
project.ctx.logger.warn(
|
|
2524
|
+
c.yellow(
|
|
2525
|
+
`Loaded ${c.inverse(c.yellow(` vitest@${project.ctx.version} `))} and ${c.inverse(c.yellow(` @vitest/browser@${version} `))}.
|
|
2526
|
+
Running mixed versions is not supported and may lead into bugs
|
|
2527
|
+
Update your dependencies and make sure the versions match.`
|
|
2528
|
+
)
|
|
2529
|
+
);
|
|
2530
|
+
}
|
|
2527
2531
|
const server = new BrowserServer(project, "/");
|
|
2528
|
-
const root = project.config.root;
|
|
2529
|
-
await project.ctx.packageInstaller.ensureInstalled("@vitest/browser", root);
|
|
2530
2532
|
const configPath = typeof configFile === "string" ? configFile : false;
|
|
2531
|
-
const
|
|
2533
|
+
const logLevel = process.env.VITEST_BROWSER_DEBUG ?? "info";
|
|
2534
|
+
const logger = createViteLogger(logLevel);
|
|
2535
|
+
const vite = await createViteServer({
|
|
2532
2536
|
...project.options,
|
|
2533
2537
|
// spread project config inlined in root workspace config
|
|
2534
2538
|
base: "/",
|
|
2535
|
-
logLevel
|
|
2539
|
+
logLevel,
|
|
2540
|
+
customLogger: {
|
|
2541
|
+
...logger,
|
|
2542
|
+
info(msg, options) {
|
|
2543
|
+
logger.info(msg, options);
|
|
2544
|
+
if (msg.includes("optimized dependencies changed. reloading")) {
|
|
2545
|
+
logger.warn(
|
|
2546
|
+
[
|
|
2547
|
+
c.yellow(`
|
|
2548
|
+
${c.bold("[vitest]")} Vite unexpectedly reloaded a test. This may cause tests to fail, lead to flaky behaviour or duplicated test runs.
|
|
2549
|
+
`),
|
|
2550
|
+
c.yellow(`For a stable experience, please add mentioned dependencies to your config's ${c.bold("`optimizeDeps.include`")} field manually.
|
|
2551
|
+
|
|
2552
|
+
`)
|
|
2553
|
+
].join("")
|
|
2554
|
+
);
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
},
|
|
2536
2558
|
mode: project.config.mode,
|
|
2537
2559
|
configFile: configPath,
|
|
2538
2560
|
// watch is handled by Vitest
|