@vitest/browser 2.0.0-beta.11 → 2.0.0-beta.13
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 +26 -5
- package/dist/client/.vite/manifest.json +7 -7
- package/dist/client/__vitest__/assets/index-C-LD6Fid.js +52 -0
- package/dist/client/__vitest__/assets/index-DEM1IsBG.css +1 -0
- package/dist/client/__vitest__/index.html +2 -2
- package/dist/client/__vitest_browser__/{rpc-D6HtJ5Rb.js → client-dLyjuL0K.js} +34 -133
- package/dist/client/__vitest_browser__/{orchestrator-DQ4hbmZ_.js → orchestrator-x0A1t8rC.js} +193 -162
- package/dist/client/__vitest_browser__/tester-BdcP5piS.js +12070 -0
- package/dist/client/orchestrator.html +2 -2
- package/dist/client/tester/tester.html +2 -2
- package/dist/context.js +82 -51
- package/dist/index.d.ts +30 -4
- package/dist/index.js +344 -98
- package/dist/providers.js +2 -2
- package/dist/state.js +1 -1
- package/dist/{webdriver-BRud6NtS.js → webdriver-BdVqnfdE.js} +75 -6
- package/jest-dom.d.ts +816 -0
- package/matchers.d.ts +22 -0
- package/package.json +15 -11
- package/providers/playwright.d.ts +25 -1
- package/providers/webdriverio.d.ts +1 -0
- package/dist/client/__vitest__/assets/index-BfnqOMHY.js +0 -51
- package/dist/client/__vitest__/assets/index-qZYZB8Y3.css +0 -1
- package/dist/client/__vitest_browser__/tester-IF8AbWCS.js +0 -837
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
</style>
|
|
26
26
|
<script>{__VITEST_INJECTOR__}</script>
|
|
27
27
|
{__VITEST_SCRIPTS__}
|
|
28
|
-
<script type="module" crossorigin src="/__vitest_browser__/orchestrator-
|
|
29
|
-
<link rel="modulepreload" crossorigin href="/__vitest_browser__/
|
|
28
|
+
<script type="module" crossorigin src="/__vitest_browser__/orchestrator-x0A1t8rC.js"></script>
|
|
29
|
+
<link rel="modulepreload" crossorigin href="/__vitest_browser__/client-dLyjuL0K.js">
|
|
30
30
|
</head>
|
|
31
31
|
<body>
|
|
32
32
|
<div id="vitest-tester"></div>
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
<script>{__VITEST_INJECTOR__}</script>
|
|
20
20
|
<script>{__VITEST_STATE__}</script>
|
|
21
21
|
{__VITEST_SCRIPTS__}
|
|
22
|
-
<script type="module" crossorigin src="/__vitest_browser__/tester-
|
|
23
|
-
<link rel="modulepreload" crossorigin href="/__vitest_browser__/
|
|
22
|
+
<script type="module" crossorigin src="/__vitest_browser__/tester-BdcP5piS.js"></script>
|
|
23
|
+
<link rel="modulepreload" crossorigin href="/__vitest_browser__/client-dLyjuL0K.js">
|
|
24
24
|
</head>
|
|
25
25
|
<body
|
|
26
26
|
data-vitest-body
|
package/dist/context.js
CHANGED
|
@@ -1,31 +1,3 @@
|
|
|
1
|
-
function convertElementToXPath(element) {
|
|
2
|
-
if (!element || !(element instanceof Element)) {
|
|
3
|
-
throw new Error(
|
|
4
|
-
`Expected DOM element to be an instance of Element, received ${typeof element}`
|
|
5
|
-
);
|
|
6
|
-
}
|
|
7
|
-
return getPathTo(element);
|
|
8
|
-
}
|
|
9
|
-
function getPathTo(element) {
|
|
10
|
-
if (element.id !== "") {
|
|
11
|
-
return `id("${element.id}")`;
|
|
12
|
-
}
|
|
13
|
-
if (!element.parentNode || element === document.documentElement) {
|
|
14
|
-
return element.tagName;
|
|
15
|
-
}
|
|
16
|
-
let ix = 0;
|
|
17
|
-
const siblings = element.parentNode.childNodes;
|
|
18
|
-
for (let i = 0; i < siblings.length; i++) {
|
|
19
|
-
const sibling = siblings[i];
|
|
20
|
-
if (sibling === element) {
|
|
21
|
-
return `${getPathTo(element.parentNode)}/${element.tagName}[${ix + 1}]`;
|
|
22
|
-
}
|
|
23
|
-
if (sibling.nodeType === 1 && sibling.tagName === element.tagName) {
|
|
24
|
-
ix++;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return "invalid xpath";
|
|
28
|
-
}
|
|
29
1
|
const state = () => __vitest_worker__;
|
|
30
2
|
const runner = () => __vitest_browser_runner__;
|
|
31
3
|
function filepath() {
|
|
@@ -38,30 +10,86 @@ function triggerCommand(command, ...args) {
|
|
|
38
10
|
return rpc().triggerCommand(contextId, command, filepath(), args);
|
|
39
11
|
}
|
|
40
12
|
const provider = runner().provider;
|
|
13
|
+
function convertElementToCssSelector(element) {
|
|
14
|
+
if (!element || !(element instanceof Element)) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
`Expected DOM element to be an instance of Element, received ${typeof element}`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
return getUniqueCssSelector(element);
|
|
20
|
+
}
|
|
21
|
+
function getUniqueCssSelector(el) {
|
|
22
|
+
const path = [];
|
|
23
|
+
let parent;
|
|
24
|
+
let hasShadowRoot = false;
|
|
25
|
+
while (parent = getParent(el)) {
|
|
26
|
+
if (parent.shadowRoot) {
|
|
27
|
+
hasShadowRoot = true;
|
|
28
|
+
}
|
|
29
|
+
const tag = el.tagName;
|
|
30
|
+
if (el.id) {
|
|
31
|
+
path.push(`#${el.id}`);
|
|
32
|
+
} else if (!el.nextElementSibling && !el.previousElementSibling) {
|
|
33
|
+
path.push(tag);
|
|
34
|
+
} else {
|
|
35
|
+
let index = 0;
|
|
36
|
+
let sameTagSiblings = 0;
|
|
37
|
+
let elementIndex = 0;
|
|
38
|
+
for (const sibling of parent.children) {
|
|
39
|
+
index++;
|
|
40
|
+
if (sibling.tagName === tag) {
|
|
41
|
+
sameTagSiblings++;
|
|
42
|
+
}
|
|
43
|
+
if (sibling === el) {
|
|
44
|
+
elementIndex = index;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (sameTagSiblings > 1) {
|
|
48
|
+
path.push(`${tag}:nth-child(${elementIndex})`);
|
|
49
|
+
} else {
|
|
50
|
+
path.push(tag);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
el = parent;
|
|
54
|
+
}
|
|
55
|
+
return `${provider === "webdriverio" && hasShadowRoot ? ">>>" : ""}${path.reverse().join(" > ")}`.toLowerCase();
|
|
56
|
+
}
|
|
57
|
+
function getParent(el) {
|
|
58
|
+
const parent = el.parentNode;
|
|
59
|
+
if (parent instanceof ShadowRoot) {
|
|
60
|
+
return parent.host;
|
|
61
|
+
}
|
|
62
|
+
return parent;
|
|
63
|
+
}
|
|
41
64
|
const userEvent = {
|
|
42
65
|
// TODO: actually setup userEvent with config options
|
|
43
66
|
setup() {
|
|
44
67
|
return userEvent;
|
|
45
68
|
},
|
|
46
69
|
click(element, options = {}) {
|
|
47
|
-
const
|
|
48
|
-
return triggerCommand("__vitest_click",
|
|
70
|
+
const css = convertElementToCssSelector(element);
|
|
71
|
+
return triggerCommand("__vitest_click", css, options);
|
|
49
72
|
},
|
|
50
73
|
dblClick(element, options = {}) {
|
|
51
|
-
const
|
|
52
|
-
return triggerCommand("__vitest_dblClick",
|
|
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);
|
|
53
80
|
},
|
|
54
81
|
selectOptions(element, value) {
|
|
55
82
|
const values = provider === "webdriverio" ? getWebdriverioSelectOptions(element, value) : getSimpleSelectOptions(element, value);
|
|
56
|
-
|
|
83
|
+
const css = convertElementToCssSelector(element);
|
|
84
|
+
return triggerCommand("__vitest_selectOptions", css, values);
|
|
57
85
|
},
|
|
58
86
|
type(element, text, options = {}) {
|
|
59
|
-
const
|
|
60
|
-
return triggerCommand("__vitest_type",
|
|
87
|
+
const css = convertElementToCssSelector(element);
|
|
88
|
+
return triggerCommand("__vitest_type", css, text, options);
|
|
61
89
|
},
|
|
62
90
|
clear(element) {
|
|
63
|
-
const
|
|
64
|
-
return triggerCommand("__vitest_clear",
|
|
91
|
+
const css = convertElementToCssSelector(element);
|
|
92
|
+
return triggerCommand("__vitest_clear", css);
|
|
65
93
|
},
|
|
66
94
|
tab(options = {}) {
|
|
67
95
|
return triggerCommand("__vitest_tab", options);
|
|
@@ -70,22 +98,22 @@ const userEvent = {
|
|
|
70
98
|
return triggerCommand("__vitest_keyboard", text);
|
|
71
99
|
},
|
|
72
100
|
hover(element) {
|
|
73
|
-
const
|
|
74
|
-
return triggerCommand("__vitest_hover",
|
|
101
|
+
const css = convertElementToCssSelector(element);
|
|
102
|
+
return triggerCommand("__vitest_hover", css);
|
|
75
103
|
},
|
|
76
104
|
unhover(element) {
|
|
77
|
-
const
|
|
78
|
-
return triggerCommand("__vitest_hover",
|
|
105
|
+
const css = convertElementToCssSelector(element.ownerDocument.body);
|
|
106
|
+
return triggerCommand("__vitest_hover", css);
|
|
79
107
|
},
|
|
80
108
|
// non userEvent events, but still useful
|
|
81
109
|
fill(element, text, options) {
|
|
82
|
-
const
|
|
83
|
-
return triggerCommand("__vitest_fill",
|
|
110
|
+
const css = convertElementToCssSelector(element);
|
|
111
|
+
return triggerCommand("__vitest_fill", css, text, options);
|
|
84
112
|
},
|
|
85
113
|
dragAndDrop(source, target, options = {}) {
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
return triggerCommand("__vitest_dragAndDrop",
|
|
114
|
+
const sourceCss = convertElementToCssSelector(source);
|
|
115
|
+
const targetCss = convertElementToCssSelector(target);
|
|
116
|
+
return triggerCommand("__vitest_dragAndDrop", sourceCss, targetCss, options);
|
|
89
117
|
}
|
|
90
118
|
};
|
|
91
119
|
function getWebdriverioSelectOptions(element, value) {
|
|
@@ -101,7 +129,7 @@ function getWebdriverioSelectOptions(element, value) {
|
|
|
101
129
|
if (typeof optionValue !== "string") {
|
|
102
130
|
const index = options.indexOf(optionValue);
|
|
103
131
|
if (index === -1) {
|
|
104
|
-
throw new Error(`The element ${
|
|
132
|
+
throw new Error(`The element ${convertElementToCssSelector(optionValue)} was not found in the "select" options.`);
|
|
105
133
|
}
|
|
106
134
|
return [{ index }];
|
|
107
135
|
}
|
|
@@ -120,11 +148,14 @@ function getWebdriverioSelectOptions(element, value) {
|
|
|
120
148
|
function getSimpleSelectOptions(element, value) {
|
|
121
149
|
return (Array.isArray(value) ? value : [value]).map((v) => {
|
|
122
150
|
if (typeof v !== "string") {
|
|
123
|
-
return { element:
|
|
151
|
+
return { element: convertElementToCssSelector(v) };
|
|
124
152
|
}
|
|
125
153
|
return v;
|
|
126
154
|
});
|
|
127
155
|
}
|
|
156
|
+
function cdp() {
|
|
157
|
+
return runner().cdp;
|
|
158
|
+
}
|
|
128
159
|
const screenshotIds = {};
|
|
129
160
|
const page = {
|
|
130
161
|
get config() {
|
|
@@ -161,10 +192,10 @@ const page = {
|
|
|
161
192
|
const number = screenshotIds[repeatCount]?.[taskName] ?? 1;
|
|
162
193
|
screenshotIds[repeatCount] ??= {};
|
|
163
194
|
screenshotIds[repeatCount][taskName] = number + 1;
|
|
164
|
-
const name = options.path || `${taskName.replace(/[^a-z0-9]/
|
|
195
|
+
const name = options.path || `${taskName.replace(/[^a-z0-9]/gi, "-")}-${number}.png`;
|
|
165
196
|
return triggerCommand("__vitest_screenshot", name, {
|
|
166
197
|
...options,
|
|
167
|
-
element: options.element ?
|
|
198
|
+
element: options.element ? convertElementToCssSelector(options.element) : void 0
|
|
168
199
|
});
|
|
169
200
|
}
|
|
170
201
|
};
|
|
@@ -172,4 +203,4 @@ function getTaskFullName(task) {
|
|
|
172
203
|
return task.suite ? `${getTaskFullName(task.suite)} ${task.name}` : task.name;
|
|
173
204
|
}
|
|
174
205
|
|
|
175
|
-
export { page, userEvent };
|
|
206
|
+
export { cdp, page, userEvent };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { BrowserServerState as BrowserServerState$1, BrowserServerStateContext, BrowserServer as BrowserServer$1, WorkspaceProject, Vite, BrowserProvider, BrowserScript, Vitest, ProcessPool } from 'vitest/node';
|
|
1
|
+
import { CDPSession, BrowserServerState as BrowserServerState$1, BrowserServerStateContext, BrowserServer as BrowserServer$1, WorkspaceProject, Vite, BrowserProvider, BrowserScript, Vitest, ProcessPool } from 'vitest/node';
|
|
2
2
|
import { Plugin } from 'vitest/config';
|
|
3
|
+
import * as vitest from 'vitest';
|
|
3
4
|
import { File, TaskResultPack, AfterSuiteRunMeta, CancelReason, UserConsoleLog, SnapshotResult, ResolvedConfig } from 'vitest';
|
|
5
|
+
import { ErrorWithDiff } from '@vitest/utils';
|
|
6
|
+
import { StackTraceParserOptions } from '@vitest/utils/source-map';
|
|
4
7
|
|
|
5
8
|
type ArgumentsType<T> = T extends (...args: infer A) => any ? A : never;
|
|
6
9
|
type ReturnType<T> = T extends (...args: any) => infer R ? R : never;
|
|
@@ -41,15 +44,19 @@ interface WebSocketBrowserHandlers {
|
|
|
41
44
|
type: 'factory' | 'redirect' | 'automock';
|
|
42
45
|
mockPath?: string | null;
|
|
43
46
|
resolvedId: string;
|
|
47
|
+
needsInterop?: boolean;
|
|
44
48
|
}>;
|
|
45
49
|
invalidate: (ids: string[]) => void;
|
|
46
50
|
getBrowserFileSourceMap: (id: string) => SourceMap | null | {
|
|
47
51
|
mappings: '';
|
|
48
52
|
} | undefined;
|
|
53
|
+
sendCdpEvent: (contextId: string, event: string, payload?: Record<string, unknown>) => unknown;
|
|
54
|
+
trackCdpEvent: (contextId: string, type: 'on' | 'once' | 'off', event: string, listenerId: string) => void;
|
|
49
55
|
}
|
|
50
56
|
interface WebSocketBrowserEvents {
|
|
51
57
|
onCancel: (reason: CancelReason) => void;
|
|
52
58
|
createTesters: (files: string[]) => Promise<void>;
|
|
59
|
+
cdpEvent: (event: string, payload: unknown) => void;
|
|
53
60
|
}
|
|
54
61
|
type WebSocketBrowserRPC = BirpcReturn<WebSocketBrowserEvents, WebSocketBrowserHandlers>;
|
|
55
62
|
interface SourceMap {
|
|
@@ -63,12 +70,26 @@ interface SourceMap {
|
|
|
63
70
|
toUrl: () => string;
|
|
64
71
|
}
|
|
65
72
|
|
|
73
|
+
declare class BrowserServerCDPHandler {
|
|
74
|
+
private session;
|
|
75
|
+
private tester;
|
|
76
|
+
private listenerIds;
|
|
77
|
+
private listeners;
|
|
78
|
+
constructor(session: CDPSession, tester: WebSocketBrowserRPC);
|
|
79
|
+
send(method: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
80
|
+
on(event: string, id: string, once?: boolean): void;
|
|
81
|
+
off(event: string, id: string): void;
|
|
82
|
+
once(event: string, listener: string): void;
|
|
83
|
+
}
|
|
84
|
+
|
|
66
85
|
declare class BrowserServerState implements BrowserServerState$1 {
|
|
67
|
-
orchestrators: Map<string, WebSocketBrowserRPC>;
|
|
68
|
-
testers: Map<string, WebSocketBrowserRPC>;
|
|
86
|
+
readonly orchestrators: Map<string, WebSocketBrowserRPC>;
|
|
87
|
+
readonly testers: Map<string, WebSocketBrowserRPC>;
|
|
88
|
+
readonly cdps: Map<string, BrowserServerCDPHandler>;
|
|
69
89
|
private contexts;
|
|
70
90
|
getContext(contextId: string): BrowserServerStateContext | undefined;
|
|
71
|
-
createAsyncContext(contextId: string, files: string[]): Promise<void>;
|
|
91
|
+
createAsyncContext(method: 'run' | 'collect', contextId: string, files: string[]): Promise<void>;
|
|
92
|
+
removeCDPHandler(sessionId: string): Promise<void>;
|
|
72
93
|
}
|
|
73
94
|
|
|
74
95
|
declare class BrowserServer implements BrowserServer$1 {
|
|
@@ -86,6 +107,7 @@ declare class BrowserServer implements BrowserServer$1 {
|
|
|
86
107
|
state: BrowserServerState;
|
|
87
108
|
provider: BrowserProvider;
|
|
88
109
|
vite: Vite.ViteDevServer;
|
|
110
|
+
private stackTraceOptions;
|
|
89
111
|
constructor(project: WorkspaceProject, base: string);
|
|
90
112
|
setServer(server: Vite.ViteDevServer): void;
|
|
91
113
|
getSerializableConfig(): ResolvedConfig;
|
|
@@ -95,6 +117,10 @@ declare class BrowserServer implements BrowserServer$1 {
|
|
|
95
117
|
};
|
|
96
118
|
formatScripts(scripts: BrowserScript[] | undefined): Promise<string>;
|
|
97
119
|
initBrowserProvider(): Promise<void>;
|
|
120
|
+
parseErrorStacktrace(e: ErrorWithDiff, options?: StackTraceParserOptions): vitest.ParsedStack[];
|
|
121
|
+
parseStacktrace(trace: string, options?: StackTraceParserOptions): vitest.ParsedStack[];
|
|
122
|
+
private cdpSessions;
|
|
123
|
+
ensureCDPHandler(contextId: string, sessionId: string): Promise<BrowserServerCDPHandler>;
|
|
98
124
|
close(): Promise<void>;
|
|
99
125
|
}
|
|
100
126
|
|