@vitest/browser 2.0.4 → 2.1.0-beta.1
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/aria-role.d.ts +96 -0
- package/context.d.ts +232 -20
- package/dist/client/.vite/manifest.json +2 -2
- package/dist/client/__vitest__/assets/index-JTfsnJeu.css +1 -0
- package/dist/client/__vitest__/assets/index-uh8h5Yzr.js +52 -0
- package/dist/client/__vitest__/favicon.ico +0 -0
- package/dist/client/__vitest__/index.html +4 -3
- package/dist/client/__vitest_browser__/{orchestrator-CNOAigTE.js → orchestrator-BObhEEvc.js} +4 -4
- package/dist/client/__vitest_browser__/{tester-BSSDPE9E.js → tester-CRcWWhrn.js} +19 -5
- package/dist/client/error-catcher.js +10 -16
- package/dist/client/orchestrator.html +1 -1
- package/dist/client/tester/tester.html +3 -11
- package/dist/context.js +260 -111
- package/dist/index-BRfqvYVY.js +5722 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.js +100 -62
- package/dist/locators/index.d.ts +261 -0
- package/dist/locators/index.js +2 -0
- package/dist/locators/playwright.js +42 -0
- package/dist/locators/preview.js +86 -0
- package/dist/locators/webdriverio.js +83 -0
- package/jest-dom.d.ts +1 -97
- package/matchers.d.ts +2 -1
- package/package.json +19 -14
- package/providers/playwright.d.ts +2 -1
- package/providers/webdriverio.d.ts +10 -1
- package/dist/client/__vitest__/assets/index--tE7Z8jQ.js +0 -52
- package/dist/client/__vitest__/assets/index-C0SwoDYm.css +0 -1
|
Binary file
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" href="./favicon.
|
|
5
|
+
<link rel="icon" href="./favicon.ico" sizes="48x48">
|
|
6
|
+
<link rel="icon" href="./favicon.svg" sizes="any" type="image/svg+xml">
|
|
6
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
8
|
<title>Vitest</title>
|
|
8
9
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
@@ -22,8 +23,8 @@
|
|
|
22
23
|
})();
|
|
23
24
|
</script>
|
|
24
25
|
<!-- !LOAD_METADATA! -->
|
|
25
|
-
<script type="module" crossorigin src="./assets/index
|
|
26
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
26
|
+
<script type="module" crossorigin src="./assets/index-uh8h5Yzr.js"></script>
|
|
27
|
+
<link rel="stylesheet" crossorigin href="./assets/index-JTfsnJeu.css">
|
|
27
28
|
</head>
|
|
28
29
|
<body>
|
|
29
30
|
<div id="app"></div>
|
package/dist/client/__vitest_browser__/{orchestrator-CNOAigTE.js → orchestrator-BObhEEvc.js}
RENAMED
|
@@ -186,7 +186,8 @@ class IframeOrchestrator {
|
|
|
186
186
|
const config = getConfig();
|
|
187
187
|
const container = await getContainer(config);
|
|
188
188
|
if (config.browser.ui) {
|
|
189
|
-
container.className = "
|
|
189
|
+
container.className = "absolute origin-top mt-[8px]";
|
|
190
|
+
container.parentElement.setAttribute("data-ready", "true");
|
|
190
191
|
container.textContent = "";
|
|
191
192
|
}
|
|
192
193
|
const { width, height } = config.browser.viewport;
|
|
@@ -229,10 +230,9 @@ class IframeOrchestrator {
|
|
|
229
230
|
`${url.pathname}__vitest_test__/__test__/${getBrowserState().contextId}/${encodeURIComponent(file)}`
|
|
230
231
|
);
|
|
231
232
|
iframe.setAttribute("data-vitest", "true");
|
|
232
|
-
iframe.style.display = "block";
|
|
233
233
|
iframe.style.border = "none";
|
|
234
|
-
iframe.style.
|
|
235
|
-
iframe.style.
|
|
234
|
+
iframe.style.width = "100%";
|
|
235
|
+
iframe.style.height = "100%";
|
|
236
236
|
iframe.setAttribute("allowfullscreen", "true");
|
|
237
237
|
iframe.setAttribute("allow", "clipboard-write;");
|
|
238
238
|
iframe.setAttribute("name", "vitest-iframe");
|
|
@@ -436,13 +436,19 @@ class VitestBrowserClientMocker {
|
|
|
436
436
|
);
|
|
437
437
|
}
|
|
438
438
|
const ext = extname(resolved.id);
|
|
439
|
-
const url2 = new URL(
|
|
440
|
-
const query = `_vitest_original&ext
|
|
439
|
+
const url2 = new URL(resolved.url, location.href);
|
|
440
|
+
const query = `_vitest_original&ext${ext}`;
|
|
441
441
|
const actualUrl = `${url2.pathname}${url2.search ? `${url2.search}&${query}` : `?${query}`}${url2.hash}`;
|
|
442
442
|
return getBrowserState().wrapModule(() => import(
|
|
443
443
|
/* @vite-ignore */
|
|
444
444
|
actualUrl
|
|
445
|
-
))
|
|
445
|
+
)).then((mod) => {
|
|
446
|
+
if (!resolved.optimized || typeof mod.default === "undefined") {
|
|
447
|
+
return mod;
|
|
448
|
+
}
|
|
449
|
+
const m = mod.default;
|
|
450
|
+
return (m == null ? void 0 : m.__esModule) ? m : { ...typeof m === "object" && !Array.isArray(m) || typeof m === "function" ? m : {}, default: m };
|
|
451
|
+
});
|
|
446
452
|
}
|
|
447
453
|
async importMock(rawId, importer) {
|
|
448
454
|
await this.prepare();
|
|
@@ -11874,8 +11880,16 @@ const matchers = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProp
|
|
|
11874
11880
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
11875
11881
|
async function setupExpectDom() {
|
|
11876
11882
|
expect.extend(matchers);
|
|
11877
|
-
expect.element = (
|
|
11878
|
-
|
|
11883
|
+
expect.element = (elementOrLocator, options) => {
|
|
11884
|
+
if (!(elementOrLocator instanceof Element) && !("element" in elementOrLocator)) {
|
|
11885
|
+
throw new Error(`Invalid element or locator: ${elementOrLocator}. Expected an instance of Element or Locator, received ${typeof elementOrLocator}`);
|
|
11886
|
+
}
|
|
11887
|
+
return expect.poll(() => {
|
|
11888
|
+
if (elementOrLocator instanceof Element) {
|
|
11889
|
+
return elementOrLocator;
|
|
11890
|
+
}
|
|
11891
|
+
return elementOrLocator.element();
|
|
11892
|
+
}, options);
|
|
11879
11893
|
};
|
|
11880
11894
|
}
|
|
11881
11895
|
const url = new URL(location.href);
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import { channel, client } from '@vitest/browser/client'
|
|
2
2
|
|
|
3
|
-
function on(event, listener) {
|
|
4
|
-
window.addEventListener(event, listener)
|
|
5
|
-
return () => window.removeEventListener(event, listener)
|
|
6
|
-
}
|
|
7
|
-
|
|
8
3
|
function serializeError(unhandledError) {
|
|
9
4
|
if (typeof unhandledError !== 'object' || !unhandledError) {
|
|
10
5
|
return {
|
|
@@ -19,41 +14,40 @@ function serializeError(unhandledError) {
|
|
|
19
14
|
}
|
|
20
15
|
}
|
|
21
16
|
|
|
22
|
-
function catchWindowErrors(cb) {
|
|
17
|
+
function catchWindowErrors(errorEvent, prop, cb) {
|
|
23
18
|
let userErrorListenerCount = 0
|
|
24
19
|
function throwUnhandlerError(e) {
|
|
25
|
-
if (userErrorListenerCount === 0 && e
|
|
20
|
+
if (userErrorListenerCount === 0 && e[prop] != null) {
|
|
26
21
|
cb(e)
|
|
27
22
|
}
|
|
28
23
|
else {
|
|
29
|
-
console.error(e
|
|
24
|
+
console.error(e[prop])
|
|
30
25
|
}
|
|
31
26
|
}
|
|
32
27
|
const addEventListener = window.addEventListener.bind(window)
|
|
33
28
|
const removeEventListener = window.removeEventListener.bind(window)
|
|
34
|
-
window.addEventListener(
|
|
29
|
+
window.addEventListener(errorEvent, throwUnhandlerError)
|
|
35
30
|
window.addEventListener = function (...args) {
|
|
36
|
-
if (args[0] ===
|
|
31
|
+
if (args[0] === errorEvent) {
|
|
37
32
|
userErrorListenerCount++
|
|
38
33
|
}
|
|
39
34
|
return addEventListener.apply(this, args)
|
|
40
35
|
}
|
|
41
36
|
window.removeEventListener = function (...args) {
|
|
42
|
-
if (args[0] ===
|
|
37
|
+
if (args[0] === errorEvent && userErrorListenerCount) {
|
|
43
38
|
userErrorListenerCount--
|
|
44
39
|
}
|
|
45
40
|
return removeEventListener.apply(this, args)
|
|
46
41
|
}
|
|
47
42
|
return function clearErrorHandlers() {
|
|
48
|
-
window.removeEventListener(
|
|
43
|
+
window.removeEventListener(errorEvent, throwUnhandlerError)
|
|
49
44
|
}
|
|
50
45
|
}
|
|
51
46
|
|
|
52
47
|
function registerUnexpectedErrors() {
|
|
53
|
-
catchWindowErrors(event =>
|
|
54
|
-
reportUnexpectedError('Error', event.error)
|
|
55
|
-
|
|
56
|
-
on('unhandledrejection', event =>
|
|
48
|
+
catchWindowErrors('error', 'error', event =>
|
|
49
|
+
reportUnexpectedError('Error', event.error))
|
|
50
|
+
catchWindowErrors('unhandledrejection', 'reason', event =>
|
|
57
51
|
reportUnexpectedError('Unhandled Rejection', event.reason))
|
|
58
52
|
}
|
|
59
53
|
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
{__VITEST_INJECTOR__}
|
|
27
27
|
{__VITEST_ERROR_CATCHER__}
|
|
28
28
|
{__VITEST_SCRIPTS__}
|
|
29
|
-
<script type="module" crossorigin src="/__vitest_browser__/orchestrator-
|
|
29
|
+
<script type="module" crossorigin src="/__vitest_browser__/orchestrator-BObhEEvc.js"></script>
|
|
30
30
|
<link rel="modulepreload" crossorigin href="/__vitest_browser__/preload-helper-Btt6SgIy.js">
|
|
31
31
|
</head>
|
|
32
32
|
<body>
|
|
@@ -18,20 +18,12 @@
|
|
|
18
18
|
</style>
|
|
19
19
|
{__VITEST_INJECTOR__}
|
|
20
20
|
<script>{__VITEST_STATE__}</script>
|
|
21
|
-
{
|
|
21
|
+
{__VITEST_INTERNAL_SCRIPTS__}
|
|
22
22
|
{__VITEST_SCRIPTS__}
|
|
23
|
-
<script type="module" crossorigin src="/__vitest_browser__/tester-
|
|
23
|
+
<script type="module" crossorigin src="/__vitest_browser__/tester-CRcWWhrn.js"></script>
|
|
24
24
|
<link rel="modulepreload" crossorigin href="/__vitest_browser__/preload-helper-Btt6SgIy.js">
|
|
25
25
|
</head>
|
|
26
|
-
<body
|
|
27
|
-
data-vitest-body
|
|
28
|
-
style="
|
|
29
|
-
width: 100%;
|
|
30
|
-
height: 100%;
|
|
31
|
-
transform: scale(1);
|
|
32
|
-
transform-origin: left top;
|
|
33
|
-
"
|
|
34
|
-
>
|
|
26
|
+
<body data-vitest-body>
|
|
35
27
|
{__VITEST_APPEND__}
|
|
36
28
|
</body>
|
|
37
29
|
</html>
|
package/dist/context.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
return state().filepath || state().current?.file?.filepath || void 0;
|
|
1
|
+
// @__NO_SIDE_EFFECTS__
|
|
2
|
+
function getBrowserState() {
|
|
3
|
+
return window.__vitest_browser_runner__;
|
|
5
4
|
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
// @__NO_SIDE_EFFECTS__
|
|
6
|
+
function getWorkerState() {
|
|
7
|
+
const state = window.__vitest_worker__;
|
|
8
|
+
if (!state) {
|
|
9
|
+
throw new Error("Worker state is not found. This is an issue with Vitest. Please, open an issue.");
|
|
10
|
+
}
|
|
11
|
+
return state;
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
+
// @__NO_SIDE_EFFECTS__
|
|
13
14
|
function convertElementToCssSelector(element) {
|
|
14
15
|
if (!element || !(element instanceof Element)) {
|
|
15
16
|
throw new Error(
|
|
@@ -18,6 +19,22 @@ function convertElementToCssSelector(element) {
|
|
|
18
19
|
}
|
|
19
20
|
return getUniqueCssSelector(element);
|
|
20
21
|
}
|
|
22
|
+
function escapeIdForCSSSelector(id) {
|
|
23
|
+
return id.split("").map((char) => {
|
|
24
|
+
const code = char.charCodeAt(0);
|
|
25
|
+
if (char === " " || char === "#" || char === "." || char === ":" || char === "[" || char === "]" || char === ">" || char === "+" || char === "~" || char === "\\") {
|
|
26
|
+
return `\\${char}`;
|
|
27
|
+
} else if (code >= 65536) {
|
|
28
|
+
return `\\${code.toString(16).toUpperCase().padStart(6, "0")} `;
|
|
29
|
+
} else if (code < 32 || code === 127) {
|
|
30
|
+
return `\\${code.toString(16).toUpperCase().padStart(2, "0")} `;
|
|
31
|
+
} else if (code >= 128) {
|
|
32
|
+
return `\\${code.toString(16).toUpperCase().padStart(2, "0")} `;
|
|
33
|
+
} else {
|
|
34
|
+
return char;
|
|
35
|
+
}
|
|
36
|
+
}).join("");
|
|
37
|
+
}
|
|
21
38
|
function getUniqueCssSelector(el) {
|
|
22
39
|
const path = [];
|
|
23
40
|
let parent;
|
|
@@ -28,9 +45,9 @@ function getUniqueCssSelector(el) {
|
|
|
28
45
|
}
|
|
29
46
|
const tag = el.tagName;
|
|
30
47
|
if (el.id) {
|
|
31
|
-
path.push(`#${el.id}`);
|
|
48
|
+
path.push(`#${escapeIdForCSSSelector(el.id)}`);
|
|
32
49
|
} else if (!el.nextElementSibling && !el.previousElementSibling) {
|
|
33
|
-
path.push(tag);
|
|
50
|
+
path.push(tag.toLowerCase());
|
|
34
51
|
} else {
|
|
35
52
|
let index = 0;
|
|
36
53
|
let sameTagSiblings = 0;
|
|
@@ -45,14 +62,14 @@ function getUniqueCssSelector(el) {
|
|
|
45
62
|
}
|
|
46
63
|
}
|
|
47
64
|
if (sameTagSiblings > 1) {
|
|
48
|
-
path.push(`${tag}:nth-child(${elementIndex})`);
|
|
65
|
+
path.push(`${tag.toLowerCase()}:nth-child(${elementIndex})`);
|
|
49
66
|
} else {
|
|
50
|
-
path.push(tag);
|
|
67
|
+
path.push(tag.toLowerCase());
|
|
51
68
|
}
|
|
52
69
|
}
|
|
53
70
|
el = parent;
|
|
54
71
|
}
|
|
55
|
-
return `${provider === "webdriverio" && hasShadowRoot ? ">>>" : ""}${path.reverse().join(" > ")}
|
|
72
|
+
return `${(/* @__PURE__ */ getBrowserState()).provider === "webdriverio" && hasShadowRoot ? ">>>" : ""}${path.reverse().join(" > ")}`;
|
|
56
73
|
}
|
|
57
74
|
function getParent(el) {
|
|
58
75
|
const parent = el.parentNode;
|
|
@@ -61,108 +78,87 @@ function getParent(el) {
|
|
|
61
78
|
}
|
|
62
79
|
return parent;
|
|
63
80
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
click(element, options = {}) {
|
|
70
|
-
const css = convertElementToCssSelector(element);
|
|
71
|
-
return triggerCommand("__vitest_click", css, options);
|
|
72
|
-
},
|
|
73
|
-
dblClick(element, options = {}) {
|
|
74
|
-
const css = convertElementToCssSelector(element);
|
|
75
|
-
return triggerCommand("__vitest_dblClick", css, options);
|
|
76
|
-
},
|
|
77
|
-
tripleClick(element, options = {}) {
|
|
78
|
-
const css = convertElementToCssSelector(element);
|
|
79
|
-
return triggerCommand("__vitest_tripleClick", css, options);
|
|
80
|
-
},
|
|
81
|
-
selectOptions(element, value) {
|
|
82
|
-
const values = provider === "webdriverio" ? getWebdriverioSelectOptions(element, value) : getSimpleSelectOptions(element, value);
|
|
83
|
-
const css = convertElementToCssSelector(element);
|
|
84
|
-
return triggerCommand("__vitest_selectOptions", css, values);
|
|
85
|
-
},
|
|
86
|
-
type(element, text, options = {}) {
|
|
87
|
-
const css = convertElementToCssSelector(element);
|
|
88
|
-
return triggerCommand("__vitest_type", css, text, options);
|
|
89
|
-
},
|
|
90
|
-
clear(element) {
|
|
91
|
-
const css = convertElementToCssSelector(element);
|
|
92
|
-
return triggerCommand("__vitest_clear", css);
|
|
93
|
-
},
|
|
94
|
-
tab(options = {}) {
|
|
95
|
-
return triggerCommand("__vitest_tab", options);
|
|
96
|
-
},
|
|
97
|
-
keyboard(text) {
|
|
98
|
-
return triggerCommand("__vitest_keyboard", text);
|
|
99
|
-
},
|
|
100
|
-
hover(element) {
|
|
101
|
-
const css = convertElementToCssSelector(element);
|
|
102
|
-
return triggerCommand("__vitest_hover", css);
|
|
103
|
-
},
|
|
104
|
-
unhover(element) {
|
|
105
|
-
const css = convertElementToCssSelector(element.ownerDocument.body);
|
|
106
|
-
return triggerCommand("__vitest_hover", css);
|
|
107
|
-
},
|
|
108
|
-
// non userEvent events, but still useful
|
|
109
|
-
fill(element, text, options) {
|
|
110
|
-
const css = convertElementToCssSelector(element);
|
|
111
|
-
return triggerCommand("__vitest_fill", css, text, options);
|
|
112
|
-
},
|
|
113
|
-
dragAndDrop(source, target, options = {}) {
|
|
114
|
-
const sourceCss = convertElementToCssSelector(source);
|
|
115
|
-
const targetCss = convertElementToCssSelector(target);
|
|
116
|
-
return triggerCommand("__vitest_dragAndDrop", sourceCss, targetCss, options);
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
function getWebdriverioSelectOptions(element, value) {
|
|
120
|
-
const options = [...element.querySelectorAll("option")];
|
|
121
|
-
const arrayValues = Array.isArray(value) ? value : [value];
|
|
122
|
-
if (!arrayValues.length) {
|
|
123
|
-
return [];
|
|
124
|
-
}
|
|
125
|
-
if (arrayValues.length > 1) {
|
|
126
|
-
throw new Error(`Provider "webdriverio" doesn't support selecting multiple values at once`);
|
|
127
|
-
}
|
|
128
|
-
const optionValue = arrayValues[0];
|
|
129
|
-
if (typeof optionValue !== "string") {
|
|
130
|
-
const index = options.indexOf(optionValue);
|
|
131
|
-
if (index === -1) {
|
|
132
|
-
throw new Error(`The element ${convertElementToCssSelector(optionValue)} was not found in the "select" options.`);
|
|
133
|
-
}
|
|
134
|
-
return [{ index }];
|
|
135
|
-
}
|
|
136
|
-
const valueIndex = options.findIndex((option) => option.value === optionValue);
|
|
137
|
-
if (valueIndex !== -1) {
|
|
138
|
-
return [{ index: valueIndex }];
|
|
139
|
-
}
|
|
140
|
-
const labelIndex = options.findIndex(
|
|
141
|
-
(option) => option.textContent?.trim() === optionValue || option.ariaLabel === optionValue
|
|
142
|
-
);
|
|
143
|
-
if (labelIndex === -1) {
|
|
144
|
-
throw new Error(`The option "${optionValue}" was not found in the "select" options.`);
|
|
145
|
-
}
|
|
146
|
-
return [{ index: labelIndex }];
|
|
81
|
+
|
|
82
|
+
const state = () => getWorkerState();
|
|
83
|
+
const provider = __vitest_browser_runner__.provider;
|
|
84
|
+
function filepath() {
|
|
85
|
+
return getWorkerState().filepath || getWorkerState().current?.file?.filepath || void 0;
|
|
147
86
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
87
|
+
const rpc = () => getWorkerState().rpc;
|
|
88
|
+
const contextId = getBrowserState().contextId;
|
|
89
|
+
const channel = new BroadcastChannel(`vitest:${contextId}`);
|
|
90
|
+
function triggerCommand(command, ...args) {
|
|
91
|
+
return rpc().triggerCommand(contextId, command, filepath(), args);
|
|
92
|
+
}
|
|
93
|
+
function createUserEvent() {
|
|
94
|
+
const keyboard = {
|
|
95
|
+
unreleased: []
|
|
96
|
+
};
|
|
97
|
+
return {
|
|
98
|
+
setup() {
|
|
99
|
+
return createUserEvent();
|
|
100
|
+
},
|
|
101
|
+
click(element, options = {}) {
|
|
102
|
+
return convertToLocator(element).click(processClickOptions(options));
|
|
103
|
+
},
|
|
104
|
+
dblClick(element, options = {}) {
|
|
105
|
+
return convertToLocator(element).dblClick(processClickOptions(options));
|
|
106
|
+
},
|
|
107
|
+
tripleClick(element, options = {}) {
|
|
108
|
+
return convertToLocator(element).tripleClick(processClickOptions(options));
|
|
109
|
+
},
|
|
110
|
+
selectOptions(element, value) {
|
|
111
|
+
return convertToLocator(element).selectOptions(value);
|
|
112
|
+
},
|
|
113
|
+
async type(element, text, options = {}) {
|
|
114
|
+
const selector = convertToSelector(element);
|
|
115
|
+
const { unreleased } = await triggerCommand(
|
|
116
|
+
"__vitest_type",
|
|
117
|
+
selector,
|
|
118
|
+
text,
|
|
119
|
+
{ ...options, unreleased: keyboard.unreleased }
|
|
120
|
+
);
|
|
121
|
+
keyboard.unreleased = unreleased;
|
|
122
|
+
},
|
|
123
|
+
clear(element) {
|
|
124
|
+
return convertToLocator(element).clear();
|
|
125
|
+
},
|
|
126
|
+
tab(options = {}) {
|
|
127
|
+
return triggerCommand("__vitest_tab", options);
|
|
128
|
+
},
|
|
129
|
+
async keyboard(text) {
|
|
130
|
+
const { unreleased } = await triggerCommand(
|
|
131
|
+
"__vitest_keyboard",
|
|
132
|
+
text,
|
|
133
|
+
keyboard
|
|
134
|
+
);
|
|
135
|
+
keyboard.unreleased = unreleased;
|
|
136
|
+
},
|
|
137
|
+
hover(element, options = {}) {
|
|
138
|
+
return convertToLocator(element).hover(processHoverOptions(options));
|
|
139
|
+
},
|
|
140
|
+
unhover(element, options = {}) {
|
|
141
|
+
return convertToLocator(element).unhover(options);
|
|
142
|
+
},
|
|
143
|
+
// non userEvent events, but still useful
|
|
144
|
+
fill(element, text, options) {
|
|
145
|
+
return convertToLocator(element).fill(text, options);
|
|
146
|
+
},
|
|
147
|
+
dragAndDrop(source, target, options = {}) {
|
|
148
|
+
const sourceLocator = convertToLocator(source);
|
|
149
|
+
const targetLocator = convertToLocator(target);
|
|
150
|
+
return sourceLocator.dropTo(targetLocator, processDragAndDropOptions(options));
|
|
152
151
|
}
|
|
153
|
-
|
|
154
|
-
});
|
|
152
|
+
};
|
|
155
153
|
}
|
|
154
|
+
const userEvent = createUserEvent();
|
|
156
155
|
function cdp() {
|
|
157
|
-
return
|
|
156
|
+
return getBrowserState().cdp;
|
|
158
157
|
}
|
|
159
158
|
const screenshotIds = {};
|
|
160
159
|
const page = {
|
|
161
|
-
get config() {
|
|
162
|
-
return runner().config;
|
|
163
|
-
},
|
|
164
160
|
viewport(width, height) {
|
|
165
|
-
const id =
|
|
161
|
+
const id = getBrowserState().iframeId;
|
|
166
162
|
channel.postMessage({ type: "viewport", width, height, id });
|
|
167
163
|
return new Promise((resolve, reject) => {
|
|
168
164
|
channel.addEventListener("message", function handler(e) {
|
|
@@ -178,7 +174,7 @@ const page = {
|
|
|
178
174
|
});
|
|
179
175
|
},
|
|
180
176
|
async screenshot(options = {}) {
|
|
181
|
-
const currentTest =
|
|
177
|
+
const currentTest = getWorkerState().current;
|
|
182
178
|
if (!currentTest) {
|
|
183
179
|
throw new Error("Cannot take a screenshot outside of a test.");
|
|
184
180
|
}
|
|
@@ -195,12 +191,165 @@ const page = {
|
|
|
195
191
|
const name = options.path || `${taskName.replace(/[^a-z0-9]/gi, "-")}-${number}.png`;
|
|
196
192
|
return triggerCommand("__vitest_screenshot", name, {
|
|
197
193
|
...options,
|
|
198
|
-
element: options.element ?
|
|
194
|
+
element: options.element ? convertToSelector(options.element) : void 0
|
|
199
195
|
});
|
|
196
|
+
},
|
|
197
|
+
getByRole() {
|
|
198
|
+
throw new Error('Method "getByRole" is not implemented in the current provider.');
|
|
199
|
+
},
|
|
200
|
+
getByLabelText() {
|
|
201
|
+
throw new Error('Method "getByLabelText" is not implemented in the current provider.');
|
|
202
|
+
},
|
|
203
|
+
getByTestId() {
|
|
204
|
+
throw new Error('Method "getByTestId" is not implemented in the current provider.');
|
|
205
|
+
},
|
|
206
|
+
getByAltText() {
|
|
207
|
+
throw new Error('Method "getByAltText" is not implemented in the current provider.');
|
|
208
|
+
},
|
|
209
|
+
getByPlaceholder() {
|
|
210
|
+
throw new Error('Method "getByPlaceholder" is not implemented in the current provider.');
|
|
211
|
+
},
|
|
212
|
+
getByText() {
|
|
213
|
+
throw new Error('Method "getByText" is not implemented in the current provider.');
|
|
214
|
+
},
|
|
215
|
+
getByTitle() {
|
|
216
|
+
throw new Error('Method "getByTitle" is not implemented in the current provider.');
|
|
217
|
+
},
|
|
218
|
+
elementLocator() {
|
|
219
|
+
throw new Error('Method "elementLocator" is not implemented in the current provider.');
|
|
220
|
+
},
|
|
221
|
+
extend(methods) {
|
|
222
|
+
for (const key in methods) {
|
|
223
|
+
page[key] = methods[key];
|
|
224
|
+
}
|
|
225
|
+
return page;
|
|
200
226
|
}
|
|
201
227
|
};
|
|
228
|
+
function convertToLocator(element) {
|
|
229
|
+
if (element instanceof Element) {
|
|
230
|
+
return page.elementLocator(element);
|
|
231
|
+
}
|
|
232
|
+
return element;
|
|
233
|
+
}
|
|
234
|
+
function convertToSelector(elementOrLocator) {
|
|
235
|
+
if (!elementOrLocator) {
|
|
236
|
+
throw new Error("Expected element or locator to be defined.");
|
|
237
|
+
}
|
|
238
|
+
if (elementOrLocator instanceof Element) {
|
|
239
|
+
return convertElementToCssSelector(elementOrLocator);
|
|
240
|
+
}
|
|
241
|
+
if ("selector" in elementOrLocator) {
|
|
242
|
+
return elementOrLocator.selector;
|
|
243
|
+
}
|
|
244
|
+
throw new Error("Expected element or locator to be an instance of Element or Locator.");
|
|
245
|
+
}
|
|
202
246
|
function getTaskFullName(task) {
|
|
203
247
|
return task.suite ? `${getTaskFullName(task.suite)} ${task.name}` : task.name;
|
|
204
248
|
}
|
|
249
|
+
function processClickOptions(options_) {
|
|
250
|
+
if (!options_ || !state().config.browser.ui) {
|
|
251
|
+
return options_;
|
|
252
|
+
}
|
|
253
|
+
if (provider === "playwright") {
|
|
254
|
+
const options = options_;
|
|
255
|
+
if (options.position) {
|
|
256
|
+
options.position = processPlaywrightPosition(options.position);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (provider === "webdriverio") {
|
|
260
|
+
const options = options_;
|
|
261
|
+
if (options.x != null || options.y != null) {
|
|
262
|
+
const cache = {};
|
|
263
|
+
if (options.x != null) {
|
|
264
|
+
options.x = scaleCoordinate(options.x, cache);
|
|
265
|
+
}
|
|
266
|
+
if (options.y != null) {
|
|
267
|
+
options.y = scaleCoordinate(options.y, cache);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return options_;
|
|
272
|
+
}
|
|
273
|
+
function processHoverOptions(options_) {
|
|
274
|
+
if (!options_ || !state().config.browser.ui) {
|
|
275
|
+
return options_;
|
|
276
|
+
}
|
|
277
|
+
if (provider === "playwright") {
|
|
278
|
+
const options = options_;
|
|
279
|
+
if (options.position) {
|
|
280
|
+
options.position = processPlaywrightPosition(options.position);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (provider === "webdriverio") {
|
|
284
|
+
const options = options_;
|
|
285
|
+
const cache = {};
|
|
286
|
+
if (options.xOffset != null) {
|
|
287
|
+
options.xOffset = scaleCoordinate(options.xOffset, cache);
|
|
288
|
+
}
|
|
289
|
+
if (options.yOffset != null) {
|
|
290
|
+
options.yOffset = scaleCoordinate(options.yOffset, cache);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return options_;
|
|
294
|
+
}
|
|
295
|
+
function processDragAndDropOptions(options_) {
|
|
296
|
+
if (!options_ || !state().config.browser.ui) {
|
|
297
|
+
return options_;
|
|
298
|
+
}
|
|
299
|
+
if (provider === "playwright") {
|
|
300
|
+
const options = options_;
|
|
301
|
+
if (options.sourcePosition) {
|
|
302
|
+
options.sourcePosition = processPlaywrightPosition(options.sourcePosition);
|
|
303
|
+
}
|
|
304
|
+
if (options.targetPosition) {
|
|
305
|
+
options.targetPosition = processPlaywrightPosition(options.targetPosition);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (provider === "webdriverio") {
|
|
309
|
+
const cache = {};
|
|
310
|
+
const options = options_;
|
|
311
|
+
if (options.sourceX != null) {
|
|
312
|
+
options.sourceX = scaleCoordinate(options.sourceX, cache);
|
|
313
|
+
}
|
|
314
|
+
if (options.sourceY != null) {
|
|
315
|
+
options.sourceY = scaleCoordinate(options.sourceY, cache);
|
|
316
|
+
}
|
|
317
|
+
if (options.targetX != null) {
|
|
318
|
+
options.targetX = scaleCoordinate(options.targetX, cache);
|
|
319
|
+
}
|
|
320
|
+
if (options.targetY != null) {
|
|
321
|
+
options.targetY = scaleCoordinate(options.targetY, cache);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return options_;
|
|
325
|
+
}
|
|
326
|
+
function scaleCoordinate(coordinate, cache) {
|
|
327
|
+
return Math.round(coordinate * getCachedScale(cache));
|
|
328
|
+
}
|
|
329
|
+
function getCachedScale(cache) {
|
|
330
|
+
return cache.scale ??= getIframeScale();
|
|
331
|
+
}
|
|
332
|
+
function processPlaywrightPosition(position) {
|
|
333
|
+
const scale = getIframeScale();
|
|
334
|
+
if (position.x != null) {
|
|
335
|
+
position.x *= scale;
|
|
336
|
+
}
|
|
337
|
+
if (position.y != null) {
|
|
338
|
+
position.y *= scale;
|
|
339
|
+
}
|
|
340
|
+
return position;
|
|
341
|
+
}
|
|
342
|
+
function getIframeScale() {
|
|
343
|
+
const testerUi = window.parent.document.querySelector("#tester-ui");
|
|
344
|
+
if (!testerUi) {
|
|
345
|
+
throw new Error(`Cannot find Tester element. This is a bug in Vitest. Please, open a new issue with reproduction.`);
|
|
346
|
+
}
|
|
347
|
+
const scaleAttribute = testerUi.getAttribute("data-scale");
|
|
348
|
+
const scale = Number(scaleAttribute);
|
|
349
|
+
if (Number.isNaN(scale)) {
|
|
350
|
+
throw new TypeError(`Cannot parse scale value from Tester element (${scaleAttribute}). This is a bug in Vitest. Please, open a new issue with reproduction.`);
|
|
351
|
+
}
|
|
352
|
+
return scale;
|
|
353
|
+
}
|
|
205
354
|
|
|
206
355
|
export { cdp, page, userEvent };
|