@vitest/browser 2.0.0-beta.1 → 2.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/context.d.ts +83 -0
- package/dist/client/__vitest__/assets/{index-D0Wp7rbG.css → index-C576npev.css} +1 -1
- package/dist/client/__vitest__/assets/{index-BMbN3lBu.js → index-DBVixaI-.js} +24 -24
- package/dist/client/__vitest__/index.html +2 -2
- package/dist/client/__vitest_browser__/{main-DmAU-Uff.js → main-uRgy0zc4.js} +1 -1
- package/dist/client/__vitest_browser__/{rpc-By4jD8av.js → rpc-Hw6RY18C.js} +53 -24
- package/dist/client/__vitest_browser__/{tester-CrKhlp5g.js → tester-Ly7RLJnN.js} +1 -1
- package/dist/client/index.html +3 -3
- package/dist/client/tester.html +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +157 -5
- package/dist/providers.js +25 -25
- package/package.json +11 -7
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
})()
|
|
18
18
|
</script>
|
|
19
19
|
<!-- !LOAD_METADATA! -->
|
|
20
|
-
<script type="module" crossorigin src="./assets/index-
|
|
21
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
20
|
+
<script type="module" crossorigin src="./assets/index-DBVixaI-.js"></script>
|
|
21
|
+
<link rel="stylesheet" crossorigin href="./assets/index-C576npev.css">
|
|
22
22
|
</head>
|
|
23
23
|
<body>
|
|
24
24
|
<div id="app"></div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as client, g as getConfig, a as getBrowserState, b as channel, r as rpcDone } from "./rpc-
|
|
1
|
+
import { c as client, g as getConfig, a as getBrowserState, b as channel, r as rpcDone } from "./rpc-Hw6RY18C.js";
|
|
2
2
|
const url = new URL(location.href);
|
|
3
3
|
const ID_ALL = "__vitest_all__";
|
|
4
4
|
const iframes = /* @__PURE__ */ new Map();
|
|
@@ -338,6 +338,33 @@ const relative = function(from, to) {
|
|
|
338
338
|
}
|
|
339
339
|
return [..._from.map(() => ".."), ..._to].join("/");
|
|
340
340
|
};
|
|
341
|
+
function generateHash(str) {
|
|
342
|
+
let hash = 0;
|
|
343
|
+
if (str.length === 0)
|
|
344
|
+
return `${hash}`;
|
|
345
|
+
for (let i = 0; i < str.length; i++) {
|
|
346
|
+
const char = str.charCodeAt(i);
|
|
347
|
+
hash = (hash << 5) - hash + char;
|
|
348
|
+
hash = hash & hash;
|
|
349
|
+
}
|
|
350
|
+
return `${hash}`;
|
|
351
|
+
}
|
|
352
|
+
function createFileTask(filepath, root, projectName) {
|
|
353
|
+
const path = relative(root, filepath);
|
|
354
|
+
const file = {
|
|
355
|
+
id: generateHash(`${path}${projectName || ""}`),
|
|
356
|
+
name: path,
|
|
357
|
+
type: "suite",
|
|
358
|
+
mode: "run",
|
|
359
|
+
filepath,
|
|
360
|
+
tasks: [],
|
|
361
|
+
meta: /* @__PURE__ */ Object.create(null),
|
|
362
|
+
projectName,
|
|
363
|
+
file: void 0
|
|
364
|
+
};
|
|
365
|
+
file.file = file;
|
|
366
|
+
return file;
|
|
367
|
+
}
|
|
341
368
|
function isAggregateError(err) {
|
|
342
369
|
if (typeof AggregateError !== "undefined" && err instanceof AggregateError)
|
|
343
370
|
return true;
|
|
@@ -409,6 +436,9 @@ class StateManager {
|
|
|
409
436
|
files.forEach((file) => {
|
|
410
437
|
const existing = this.filesMap.get(file.filepath) || [];
|
|
411
438
|
const otherProject = existing.filter((i) => i.projectName !== file.projectName);
|
|
439
|
+
const currentFile = existing.find((i) => i.projectName === file.projectName);
|
|
440
|
+
if (currentFile)
|
|
441
|
+
file.logs = currentFile.logs;
|
|
412
442
|
otherProject.push(file);
|
|
413
443
|
this.filesMap.set(file.filepath, otherProject);
|
|
414
444
|
this.updateId(file);
|
|
@@ -419,13 +449,21 @@ class StateManager {
|
|
|
419
449
|
const project = _project;
|
|
420
450
|
paths.forEach((path) => {
|
|
421
451
|
const files = this.filesMap.get(path);
|
|
422
|
-
|
|
452
|
+
const fileTask = createFileTask(path, project.config.root, project.config.name);
|
|
453
|
+
this.idMap.set(fileTask.id, fileTask);
|
|
454
|
+
if (!files) {
|
|
455
|
+
this.filesMap.set(path, [fileTask]);
|
|
423
456
|
return;
|
|
457
|
+
}
|
|
424
458
|
const filtered = files.filter((file) => file.projectName !== project.config.name);
|
|
425
|
-
if (!filtered.length)
|
|
426
|
-
this.filesMap.
|
|
427
|
-
else
|
|
428
|
-
this.filesMap.set(path,
|
|
459
|
+
if (!filtered.length) {
|
|
460
|
+
this.filesMap.set(path, [fileTask]);
|
|
461
|
+
} else {
|
|
462
|
+
this.filesMap.set(path, [
|
|
463
|
+
...filtered,
|
|
464
|
+
fileTask
|
|
465
|
+
]);
|
|
466
|
+
}
|
|
429
467
|
});
|
|
430
468
|
}
|
|
431
469
|
updateId(task) {
|
|
@@ -464,25 +502,7 @@ class StateManager {
|
|
|
464
502
|
}).length;
|
|
465
503
|
}
|
|
466
504
|
cancelFiles(files, root, projectName) {
|
|
467
|
-
this.collectFiles(files.map((filepath) =>
|
|
468
|
-
const file = {
|
|
469
|
-
filepath,
|
|
470
|
-
name: relative(root, filepath),
|
|
471
|
-
id: filepath,
|
|
472
|
-
mode: "skip",
|
|
473
|
-
type: "suite",
|
|
474
|
-
result: {
|
|
475
|
-
state: "skip"
|
|
476
|
-
},
|
|
477
|
-
meta: {},
|
|
478
|
-
// Cancelled files have not yet collected tests
|
|
479
|
-
tasks: [],
|
|
480
|
-
projectName,
|
|
481
|
-
file: null
|
|
482
|
-
};
|
|
483
|
-
file.file = file;
|
|
484
|
-
return file;
|
|
485
|
-
}));
|
|
505
|
+
this.collectFiles(files.map((filepath) => createFileTask(filepath, root, projectName)));
|
|
486
506
|
}
|
|
487
507
|
}
|
|
488
508
|
function createClient(url, options = {}) {
|
|
@@ -506,6 +526,13 @@ function createClient(url, options = {}) {
|
|
|
506
526
|
ctx.state.idMap = reactive(ctx.state.idMap);
|
|
507
527
|
let onMessage;
|
|
508
528
|
const functions = {
|
|
529
|
+
onSpecsCollected(specs) {
|
|
530
|
+
var _a;
|
|
531
|
+
specs == null ? void 0 : specs.forEach(([config, file]) => {
|
|
532
|
+
ctx.state.clearFiles({ config }, [file]);
|
|
533
|
+
});
|
|
534
|
+
(_a = handlers.onSpecsCollected) == null ? void 0 : _a.call(handlers, specs);
|
|
535
|
+
},
|
|
509
536
|
onPathsCollected(paths) {
|
|
510
537
|
var _a;
|
|
511
538
|
ctx.state.collectPaths(paths);
|
|
@@ -522,7 +549,9 @@ function createClient(url, options = {}) {
|
|
|
522
549
|
(_a = handlers.onTaskUpdate) == null ? void 0 : _a.call(handlers, packs);
|
|
523
550
|
},
|
|
524
551
|
onUserConsoleLog(log) {
|
|
552
|
+
var _a;
|
|
525
553
|
ctx.state.updateUserLog(log);
|
|
554
|
+
(_a = handlers.onUserConsoleLog) == null ? void 0 : _a.call(handlers, log);
|
|
526
555
|
},
|
|
527
556
|
onFinished(files, errors) {
|
|
528
557
|
var _a;
|
|
@@ -10,7 +10,7 @@ var __publicField = (obj, key, value) => {
|
|
|
10
10
|
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
11
11
|
return value;
|
|
12
12
|
};
|
|
13
|
-
import { i as importId, d as rpc$1, g as getConfig, _ as __vitePreload, b as channel, a as getBrowserState, c as client, l as loadSafeRpc, o as onCancel } from "./rpc-
|
|
13
|
+
import { i as importId, d as rpc$1, g as getConfig, _ as __vitePreload, b as channel, a as getBrowserState, c as client, l as loadSafeRpc, o as onCancel } from "./rpc-Hw6RY18C.js";
|
|
14
14
|
function showPopupWarning(name, value, defaultValue) {
|
|
15
15
|
return (...params) => {
|
|
16
16
|
const formatedParams = params.map((p) => JSON.stringify(p)).join(", ");
|
package/dist/client/index.html
CHANGED
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
</style>
|
|
24
24
|
<script>{__VITEST_INJECTOR__}</script>
|
|
25
25
|
{__VITEST_SCRIPTS__}
|
|
26
|
-
<script type="module" crossorigin src="/__vitest_browser__/main-
|
|
27
|
-
<link rel="modulepreload" crossorigin href="/__vitest_browser__/rpc-
|
|
26
|
+
<script type="module" crossorigin src="/__vitest_browser__/main-uRgy0zc4.js"></script>
|
|
27
|
+
<link rel="modulepreload" crossorigin href="/__vitest_browser__/rpc-Hw6RY18C.js">
|
|
28
28
|
</head>
|
|
29
29
|
<body>
|
|
30
|
-
<iframe id="vitest-ui" src=""></iframe>
|
|
30
|
+
<iframe id="vitest-ui" src="/__vitest__/"></iframe>
|
|
31
31
|
<div id="vitest-tester"></div>
|
|
32
32
|
</body>
|
|
33
33
|
</html>
|
package/dist/client/tester.html
CHANGED
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
</style>
|
|
18
18
|
<script>{__VITEST_INJECTOR__}</script>
|
|
19
19
|
{__VITEST_SCRIPTS__}
|
|
20
|
-
<script type="module" crossorigin src="/__vitest_browser__/tester-
|
|
21
|
-
<link rel="modulepreload" crossorigin href="/__vitest_browser__/rpc-
|
|
20
|
+
<script type="module" crossorigin src="/__vitest_browser__/tester-Ly7RLJnN.js"></script>
|
|
21
|
+
<link rel="modulepreload" crossorigin href="/__vitest_browser__/rpc-Hw6RY18C.js">
|
|
22
22
|
</head>
|
|
23
23
|
<body>
|
|
24
24
|
{__VITEST_APPEND__}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { fileURLToPath } from 'node:url';
|
|
2
|
-
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { readFile as readFile$1 } from 'node:fs/promises';
|
|
3
3
|
import sirv from 'sirv';
|
|
4
4
|
import { coverageConfigDefaults } from 'vitest/config';
|
|
5
5
|
import { slash } from '@vitest/utils';
|
|
6
6
|
import MagicString from 'magic-string';
|
|
7
7
|
import { esmWalker } from '@vitest/utils/ast';
|
|
8
|
+
import fs, { promises } from 'node:fs';
|
|
9
|
+
import { resolve as resolve$1, dirname } from 'node:path';
|
|
10
|
+
import { isFileServingAllowed } from 'vitest/node';
|
|
8
11
|
|
|
9
12
|
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
10
13
|
function normalizeWindowsPath(input = "") {
|
|
@@ -398,6 +401,154 @@ export { ${viInjectedKey} }`);
|
|
|
398
401
|
};
|
|
399
402
|
}
|
|
400
403
|
|
|
404
|
+
function assertFileAccess(path, project) {
|
|
405
|
+
if (!isFileServingAllowed(path, project.server) && !isFileServingAllowed(path, project.ctx.server))
|
|
406
|
+
throw new Error(`Access denied to "${path}". See Vite config documentation for "server.fs": https://vitejs.dev/config/server-options.html#server-fs-strict.`);
|
|
407
|
+
}
|
|
408
|
+
const readFile = async ({ project, testPath = process.cwd() }, path, options = {}) => {
|
|
409
|
+
const filepath = resolve$1(dirname(testPath), path);
|
|
410
|
+
assertFileAccess(filepath, project);
|
|
411
|
+
if (typeof options === "object" && !options.encoding)
|
|
412
|
+
options.encoding = "utf-8";
|
|
413
|
+
return promises.readFile(filepath, options);
|
|
414
|
+
};
|
|
415
|
+
const writeFile = async ({ project, testPath = process.cwd() }, path, data, options) => {
|
|
416
|
+
const filepath = resolve$1(dirname(testPath), path);
|
|
417
|
+
assertFileAccess(filepath, project);
|
|
418
|
+
const dir = dirname(filepath);
|
|
419
|
+
if (!fs.existsSync(dir))
|
|
420
|
+
await promises.mkdir(dir, { recursive: true });
|
|
421
|
+
await promises.writeFile(filepath, data, options);
|
|
422
|
+
};
|
|
423
|
+
const removeFile = async ({ project, testPath = process.cwd() }, path) => {
|
|
424
|
+
const filepath = resolve$1(dirname(testPath), path);
|
|
425
|
+
assertFileAccess(filepath, project);
|
|
426
|
+
await promises.rm(filepath);
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
function isObject(payload) {
|
|
430
|
+
return payload != null && typeof payload === "object";
|
|
431
|
+
}
|
|
432
|
+
function isSendKeysPayload(payload) {
|
|
433
|
+
const validOptions = ["type", "press", "down", "up"];
|
|
434
|
+
if (!isObject(payload))
|
|
435
|
+
throw new Error("You must provide a `SendKeysPayload` object");
|
|
436
|
+
const numberOfValidOptions = Object.keys(payload).filter(
|
|
437
|
+
(key) => validOptions.includes(key)
|
|
438
|
+
).length;
|
|
439
|
+
const unknownOptions = Object.keys(payload).filter((key) => !validOptions.includes(key));
|
|
440
|
+
if (numberOfValidOptions > 1) {
|
|
441
|
+
throw new Error(
|
|
442
|
+
`You must provide ONLY one of the following properties to pass to the browser runner: ${validOptions.join(
|
|
443
|
+
", "
|
|
444
|
+
)}.`
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
if (numberOfValidOptions === 0) {
|
|
448
|
+
throw new Error(
|
|
449
|
+
`You must provide one of the following properties to pass to the browser runner: ${validOptions.join(
|
|
450
|
+
", "
|
|
451
|
+
)}.`
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
if (unknownOptions.length > 0)
|
|
455
|
+
throw new Error(`Unknown options \`${unknownOptions.join(", ")}\` present.`);
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
function isTypePayload(payload) {
|
|
459
|
+
return "type" in payload;
|
|
460
|
+
}
|
|
461
|
+
function isPressPayload(payload) {
|
|
462
|
+
return "press" in payload;
|
|
463
|
+
}
|
|
464
|
+
function isDownPayload(payload) {
|
|
465
|
+
return "down" in payload;
|
|
466
|
+
}
|
|
467
|
+
function isUpPayload(payload) {
|
|
468
|
+
return "up" in payload;
|
|
469
|
+
}
|
|
470
|
+
const sendKeys = async ({ provider }, payload) => {
|
|
471
|
+
if (!isSendKeysPayload(payload) || !payload)
|
|
472
|
+
throw new Error("You must provide a `SendKeysPayload` object");
|
|
473
|
+
if (provider.name === "playwright") {
|
|
474
|
+
const page = provider.page;
|
|
475
|
+
if (isTypePayload(payload))
|
|
476
|
+
await page.keyboard.type(payload.type);
|
|
477
|
+
else if (isPressPayload(payload))
|
|
478
|
+
await page.keyboard.press(payload.press);
|
|
479
|
+
else if (isDownPayload(payload))
|
|
480
|
+
await page.keyboard.down(payload.down);
|
|
481
|
+
else if (isUpPayload(payload))
|
|
482
|
+
await page.keyboard.up(payload.up);
|
|
483
|
+
} else if (provider.name === "webdriverio") {
|
|
484
|
+
const browser = provider.browser;
|
|
485
|
+
if (isTypePayload(payload))
|
|
486
|
+
await browser.keys(payload.type.split(""));
|
|
487
|
+
else if (isPressPayload(payload))
|
|
488
|
+
await browser.keys([payload.press]);
|
|
489
|
+
else
|
|
490
|
+
throw new Error('Only "press" and "type" are supported by webdriverio.');
|
|
491
|
+
} else {
|
|
492
|
+
throw new Error(`"sendKeys" is not supported for ${provider.name} browser provider.`);
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
var builtinCommands = {
|
|
497
|
+
readFile,
|
|
498
|
+
removeFile,
|
|
499
|
+
writeFile,
|
|
500
|
+
sendKeys
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
const VIRTUAL_ID_CONTEXT = "\0@vitest/browser/context";
|
|
504
|
+
const ID_CONTEXT = "@vitest/browser/context";
|
|
505
|
+
function BrowserContext(project) {
|
|
506
|
+
project.config.browser.commands ??= {};
|
|
507
|
+
for (const [name, command] of Object.entries(builtinCommands))
|
|
508
|
+
project.config.browser.commands[name] ??= command;
|
|
509
|
+
for (const command in project.config.browser.commands) {
|
|
510
|
+
if (!/^[a-z_$][\w$]*$/i.test(command))
|
|
511
|
+
throw new Error(`Invalid command name "${command}". Only alphanumeric characters, $ and _ are allowed.`);
|
|
512
|
+
}
|
|
513
|
+
return {
|
|
514
|
+
name: "vitest:browser:virtual-module:context",
|
|
515
|
+
enforce: "pre",
|
|
516
|
+
resolveId(id) {
|
|
517
|
+
if (id === ID_CONTEXT)
|
|
518
|
+
return VIRTUAL_ID_CONTEXT;
|
|
519
|
+
},
|
|
520
|
+
load(id) {
|
|
521
|
+
if (id === VIRTUAL_ID_CONTEXT)
|
|
522
|
+
return generateContextFile(project);
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
function generateContextFile(project) {
|
|
527
|
+
const commands = Object.keys(project.config.browser.commands ?? {});
|
|
528
|
+
const filepathCode = "__vitest_worker__.filepath || __vitest_worker__.current?.file?.filepath || undefined";
|
|
529
|
+
const commandsCode = commands.map((command) => {
|
|
530
|
+
return ` ["${command}"]: (...args) => rpc().triggerCommand("${command}", ${filepathCode}, args),`;
|
|
531
|
+
}).join("\n");
|
|
532
|
+
return `
|
|
533
|
+
const rpc = () => __vitest_worker__.rpc
|
|
534
|
+
|
|
535
|
+
export const server = {
|
|
536
|
+
platform: ${JSON.stringify(process.platform)},
|
|
537
|
+
version: ${JSON.stringify(process.version)},
|
|
538
|
+
provider: ${JSON.stringify(project.browserProvider.name)},
|
|
539
|
+
commands: {
|
|
540
|
+
${commandsCode}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
export const commands = server.commands
|
|
544
|
+
export const page = {
|
|
545
|
+
get config() {
|
|
546
|
+
return __vitest_browser_runner__.config
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
`;
|
|
550
|
+
}
|
|
551
|
+
|
|
401
552
|
var index = (project, base = "/") => {
|
|
402
553
|
const pkgRoot = resolve(fileURLToPath(import.meta.url), "../..");
|
|
403
554
|
const distRoot = resolve(pkgRoot, "dist");
|
|
@@ -413,9 +564,9 @@ var index = (project, base = "/") => {
|
|
|
413
564
|
}
|
|
414
565
|
},
|
|
415
566
|
async configureServer(server) {
|
|
416
|
-
const testerHtml = readFile(resolve(distRoot, "client/tester.html"), "utf8");
|
|
417
|
-
const runnerHtml = readFile(resolve(distRoot, "client/index.html"), "utf8");
|
|
418
|
-
const injectorJs = readFile(resolve(distRoot, "client/esm-client-injector.js"), "utf8");
|
|
567
|
+
const testerHtml = readFile$1(resolve(distRoot, "client/tester.html"), "utf8");
|
|
568
|
+
const runnerHtml = readFile$1(resolve(distRoot, "client/index.html"), "utf8");
|
|
569
|
+
const injectorJs = readFile$1(resolve(distRoot, "client/esm-client-injector.js"), "utf8");
|
|
419
570
|
const favicon = `${base}favicon.svg`;
|
|
420
571
|
const testerPrefix = `${base}__vitest_test__/__test__/`;
|
|
421
572
|
server.middlewares.use((_req, res, next) => {
|
|
@@ -562,6 +713,7 @@ export default globalThis.loupe`;
|
|
|
562
713
|
return useId;
|
|
563
714
|
}
|
|
564
715
|
},
|
|
716
|
+
BrowserContext(project),
|
|
565
717
|
{
|
|
566
718
|
name: "vitest:browser:esm-injector",
|
|
567
719
|
enforce: "post",
|
|
@@ -600,7 +752,7 @@ function wrapConfig(config) {
|
|
|
600
752
|
};
|
|
601
753
|
}
|
|
602
754
|
function replacer(code, values) {
|
|
603
|
-
return code.replace(
|
|
755
|
+
return code.replace(/\{\s*(\w+)\s*\}/g, (_, key) => values[key] ?? "");
|
|
604
756
|
}
|
|
605
757
|
async function formatScripts(scripts, server) {
|
|
606
758
|
if (!scripts?.length)
|
package/dist/providers.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
const playwrightBrowsers = ["firefox", "webkit", "chromium"];
|
|
2
2
|
class PlaywrightBrowserProvider {
|
|
3
3
|
name = "playwright";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
browser = null;
|
|
5
|
+
page = null;
|
|
6
|
+
browserName;
|
|
7
7
|
ctx;
|
|
8
8
|
options;
|
|
9
9
|
getSupportedBrowsers() {
|
|
@@ -11,31 +11,31 @@ class PlaywrightBrowserProvider {
|
|
|
11
11
|
}
|
|
12
12
|
initialize(project, { browser, options }) {
|
|
13
13
|
this.ctx = project;
|
|
14
|
-
this.
|
|
14
|
+
this.browserName = browser;
|
|
15
15
|
this.options = options;
|
|
16
16
|
}
|
|
17
17
|
async openBrowserPage() {
|
|
18
|
-
if (this.
|
|
19
|
-
return this.
|
|
18
|
+
if (this.page)
|
|
19
|
+
return this.page;
|
|
20
20
|
const options = this.ctx.config.browser;
|
|
21
21
|
const playwright = await import('playwright');
|
|
22
|
-
const browser = await playwright[this.
|
|
22
|
+
const browser = await playwright[this.browserName].launch({
|
|
23
23
|
...this.options?.launch,
|
|
24
24
|
headless: options.headless
|
|
25
25
|
});
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
28
|
-
return this.
|
|
26
|
+
this.browser = browser;
|
|
27
|
+
this.page = await browser.newPage(this.options?.page);
|
|
28
|
+
return this.page;
|
|
29
29
|
}
|
|
30
30
|
async openPage(url) {
|
|
31
31
|
const browserPage = await this.openBrowserPage();
|
|
32
32
|
await browserPage.goto(url);
|
|
33
33
|
}
|
|
34
34
|
async close() {
|
|
35
|
-
const page = this.
|
|
36
|
-
this.
|
|
37
|
-
const browser = this.
|
|
38
|
-
this.
|
|
35
|
+
const page = this.page;
|
|
36
|
+
this.page = null;
|
|
37
|
+
const browser = this.browser;
|
|
38
|
+
this.browser = null;
|
|
39
39
|
await page?.close();
|
|
40
40
|
await browser?.close();
|
|
41
41
|
}
|
|
@@ -44,8 +44,8 @@ class PlaywrightBrowserProvider {
|
|
|
44
44
|
const webdriverBrowsers = ["firefox", "chrome", "edge", "safari"];
|
|
45
45
|
class WebdriverBrowserProvider {
|
|
46
46
|
name = "webdriverio";
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
browser = null;
|
|
48
|
+
browserName;
|
|
49
49
|
ctx;
|
|
50
50
|
options;
|
|
51
51
|
getSupportedBrowsers() {
|
|
@@ -53,29 +53,29 @@ class WebdriverBrowserProvider {
|
|
|
53
53
|
}
|
|
54
54
|
async initialize(ctx, { browser, options }) {
|
|
55
55
|
this.ctx = ctx;
|
|
56
|
-
this.
|
|
56
|
+
this.browserName = browser;
|
|
57
57
|
this.options = options;
|
|
58
58
|
}
|
|
59
59
|
async openBrowser() {
|
|
60
|
-
if (this.
|
|
61
|
-
return this.
|
|
60
|
+
if (this.browser)
|
|
61
|
+
return this.browser;
|
|
62
62
|
const options = this.ctx.config.browser;
|
|
63
|
-
if (this.
|
|
63
|
+
if (this.browserName === "safari") {
|
|
64
64
|
if (options.headless)
|
|
65
65
|
throw new Error("You've enabled headless mode for Safari but it doesn't currently support it.");
|
|
66
66
|
}
|
|
67
67
|
const { remote } = await import('webdriverio');
|
|
68
|
-
this.
|
|
68
|
+
this.browser = await remote({
|
|
69
69
|
...this.options,
|
|
70
70
|
logLevel: "error",
|
|
71
71
|
capabilities: this.buildCapabilities()
|
|
72
72
|
});
|
|
73
|
-
return this.
|
|
73
|
+
return this.browser;
|
|
74
74
|
}
|
|
75
75
|
buildCapabilities() {
|
|
76
76
|
const capabilities = {
|
|
77
77
|
...this.options?.capabilities,
|
|
78
|
-
browserName: this.
|
|
78
|
+
browserName: this.browserName
|
|
79
79
|
};
|
|
80
80
|
const headlessMap = {
|
|
81
81
|
chrome: ["goog:chromeOptions", ["headless", "disable-gpu"]],
|
|
@@ -83,7 +83,7 @@ class WebdriverBrowserProvider {
|
|
|
83
83
|
edge: ["ms:edgeOptions", ["--headless"]]
|
|
84
84
|
};
|
|
85
85
|
const options = this.ctx.config.browser;
|
|
86
|
-
const browser = this.
|
|
86
|
+
const browser = this.browserName;
|
|
87
87
|
if (browser !== "safari" && options.headless) {
|
|
88
88
|
const [key, args] = headlessMap[browser];
|
|
89
89
|
const currentValues = this.options?.capabilities?.[key] || {};
|
|
@@ -98,7 +98,7 @@ class WebdriverBrowserProvider {
|
|
|
98
98
|
}
|
|
99
99
|
async close() {
|
|
100
100
|
await Promise.all([
|
|
101
|
-
this.
|
|
101
|
+
this.browser?.sessionId ? this.browser?.deleteSession?.() : null
|
|
102
102
|
]);
|
|
103
103
|
process.exit();
|
|
104
104
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitest/browser",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.3",
|
|
5
5
|
"description": "Browser running for Vitest",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": "https://opencollective.com/vitest",
|
|
@@ -24,6 +24,10 @@
|
|
|
24
24
|
"types": "./providers.d.ts",
|
|
25
25
|
"default": "./dist/providers.js"
|
|
26
26
|
},
|
|
27
|
+
"./context": {
|
|
28
|
+
"types": "./context.d.ts",
|
|
29
|
+
"default": "./context.js"
|
|
30
|
+
},
|
|
27
31
|
"./providers/webdriverio": {
|
|
28
32
|
"types": "./providers/webdriverio.d.ts"
|
|
29
33
|
},
|
|
@@ -43,7 +47,7 @@
|
|
|
43
47
|
"peerDependencies": {
|
|
44
48
|
"playwright": "*",
|
|
45
49
|
"webdriverio": "*",
|
|
46
|
-
"vitest": "2.0.0-beta.
|
|
50
|
+
"vitest": "2.0.0-beta.3"
|
|
47
51
|
},
|
|
48
52
|
"peerDependenciesMeta": {
|
|
49
53
|
"playwright": {
|
|
@@ -59,7 +63,7 @@
|
|
|
59
63
|
"dependencies": {
|
|
60
64
|
"magic-string": "^0.30.10",
|
|
61
65
|
"sirv": "^2.0.4",
|
|
62
|
-
"@vitest/utils": "2.0.0-beta.
|
|
66
|
+
"@vitest/utils": "2.0.0-beta.3"
|
|
63
67
|
},
|
|
64
68
|
"devDependencies": {
|
|
65
69
|
"@types/ws": "^8.5.10",
|
|
@@ -69,10 +73,10 @@
|
|
|
69
73
|
"playwright-core": "^1.44.0",
|
|
70
74
|
"safaridriver": "^0.1.2",
|
|
71
75
|
"webdriverio": "^8.36.1",
|
|
72
|
-
"@vitest/
|
|
73
|
-
"@vitest/ui": "2.0.0-beta.
|
|
74
|
-
"@vitest/
|
|
75
|
-
"vitest": "2.0.0-beta.
|
|
76
|
+
"@vitest/runner": "2.0.0-beta.3",
|
|
77
|
+
"@vitest/ui": "2.0.0-beta.3",
|
|
78
|
+
"@vitest/ws-client": "2.0.0-beta.3",
|
|
79
|
+
"vitest": "2.0.0-beta.3"
|
|
76
80
|
},
|
|
77
81
|
"scripts": {
|
|
78
82
|
"build": "rimraf dist && pnpm build:node && pnpm build:client",
|