@vitest/browser 3.1.1 → 3.1.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/dist/client/.vite/manifest.json +6 -6
- package/dist/client/__vitest__/assets/index-Cv3XDLXs.js +52 -0
- package/dist/client/__vitest__/assets/{index-B0KEk_KY.css → index-D6BhetW8.css} +1 -1
- package/dist/client/__vitest__/index.html +2 -2
- package/dist/client/__vitest_browser__/orchestrator-CuTjqoE1.js +287 -0
- package/dist/client/__vitest_browser__/{tester-DiLSqOx4.js → tester-D8qCxA_3.js} +3172 -3084
- package/dist/client/__vitest_browser__/{utils-CNTxSNQV.js → utils-Owv5OOOf.js} +2 -2
- package/dist/client/error-catcher.js +1 -14
- package/dist/client/esm-client-injector.js +0 -1
- package/dist/client/orchestrator.html +2 -2
- package/dist/client/tester/tester.html +2 -2
- package/dist/client.js +63 -23
- package/dist/context.js +4 -4
- package/dist/expect-element.js +1 -1
- package/dist/index-C3ICQ6zz.js +1 -0
- package/dist/index.d.ts +8 -8
- package/dist/index.js +364 -244
- package/dist/locators/index.js +1 -1
- package/dist/locators/playwright.js +1 -1
- package/dist/locators/preview.js +1 -1
- package/dist/locators/webdriverio.js +1 -1
- package/dist/providers.js +2 -1
- package/dist/{public-utils-xf4CCUzp.js → public-utils-DUr23h1p.js} +2 -2
- package/dist/state.js +2 -67
- package/dist/utils.js +1 -1
- package/dist/{webdriver-2iYWIzBv.js → webdriver-BH7t2pDp.js} +63 -9
- package/package.json +16 -16
- package/dist/client/__vitest__/assets/index-BLZJq7cG.js +0 -52
- package/dist/client/__vitest_browser__/orchestrator-CqPXjvQE.js +0 -241
- package/dist/index-DjDyxzt8.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { client } from '@vitest/browser/client'
|
|
2
2
|
|
|
3
3
|
function serializeError(unhandledError) {
|
|
4
4
|
const state = globalThis.__vitest_worker__
|
|
@@ -69,19 +69,6 @@ async function reportUnexpectedError(
|
|
|
69
69
|
await client.waitForConnection().then(() => {
|
|
70
70
|
return client.rpc.onUnhandledError(processedError, type)
|
|
71
71
|
}).catch(console.error)
|
|
72
|
-
const state = __vitest_browser_runner__
|
|
73
|
-
|
|
74
|
-
if (state.type === 'orchestrator') {
|
|
75
|
-
return
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (!state.runTests || !__vitest_worker__.current) {
|
|
79
|
-
channel.postMessage({
|
|
80
|
-
type: 'done',
|
|
81
|
-
filenames: state.files,
|
|
82
|
-
id: state.iframeId,
|
|
83
|
-
})
|
|
84
|
-
}
|
|
85
72
|
}
|
|
86
73
|
|
|
87
74
|
registerUnexpectedErrors()
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
{__VITEST_INJECTOR__}
|
|
27
27
|
{__VITEST_ERROR_CATCHER__}
|
|
28
28
|
{__VITEST_SCRIPTS__}
|
|
29
|
-
<script type="module" crossorigin src="/__vitest_browser__/orchestrator-
|
|
30
|
-
<link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-
|
|
29
|
+
<script type="module" crossorigin src="/__vitest_browser__/orchestrator-CuTjqoE1.js"></script>
|
|
30
|
+
<link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-Owv5OOOf.js">
|
|
31
31
|
</head>
|
|
32
32
|
<body>
|
|
33
33
|
<div id="vitest-tester"></div>
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" href="{__VITEST_FAVICON__}" type="image/svg+xml">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>Vitest Browser Tester</title>
|
|
8
|
-
<script type="module" crossorigin src="/__vitest_browser__/tester-
|
|
9
|
-
<link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-
|
|
8
|
+
<script type="module" crossorigin src="/__vitest_browser__/tester-D8qCxA_3.js"></script>
|
|
9
|
+
<link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-Owv5OOOf.js">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
</body>
|
package/dist/client.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const TYPE_REQUEST = "q";
|
|
2
|
+
const TYPE_RESPONSE = "s";
|
|
1
3
|
const DEFAULT_TIMEOUT = 6e4;
|
|
2
4
|
function defaultSerialize(i) {
|
|
3
5
|
return i;
|
|
@@ -30,7 +32,7 @@ function createBirpc(functions, options) {
|
|
|
30
32
|
if (method === "then" && !eventNames.includes("then") && !("then" in functions))
|
|
31
33
|
return void 0;
|
|
32
34
|
const sendEvent = (...args) => {
|
|
33
|
-
post(serialize({ m: method, a: args, t:
|
|
35
|
+
post(serialize({ m: method, a: args, t: TYPE_REQUEST }));
|
|
34
36
|
};
|
|
35
37
|
if (eventNames.includes(method)) {
|
|
36
38
|
sendEvent.asEvent = sendEvent;
|
|
@@ -52,8 +54,9 @@ function createBirpc(functions, options) {
|
|
|
52
54
|
if (timeout >= 0) {
|
|
53
55
|
timeoutId = setTimeout$1(() => {
|
|
54
56
|
try {
|
|
55
|
-
options.onTimeoutError?.(method, args);
|
|
56
|
-
|
|
57
|
+
const handleResult = options.onTimeoutError?.(method, args);
|
|
58
|
+
if (handleResult !== true)
|
|
59
|
+
throw new Error(`[birpc] timeout on calling "${method}"`);
|
|
57
60
|
} catch (e) {
|
|
58
61
|
reject(e);
|
|
59
62
|
}
|
|
@@ -70,17 +73,24 @@ function createBirpc(functions, options) {
|
|
|
70
73
|
return sendCall;
|
|
71
74
|
}
|
|
72
75
|
});
|
|
73
|
-
function close() {
|
|
76
|
+
function close(error) {
|
|
74
77
|
closed = true;
|
|
75
78
|
rpcPromiseMap.forEach(({ reject, method }) => {
|
|
76
|
-
reject(new Error(`[birpc] rpc is closed, cannot call "${method}"`));
|
|
79
|
+
reject(error || new Error(`[birpc] rpc is closed, cannot call "${method}"`));
|
|
77
80
|
});
|
|
78
81
|
rpcPromiseMap.clear();
|
|
79
82
|
off(onMessage);
|
|
80
83
|
}
|
|
81
84
|
async function onMessage(data, ...extra) {
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
let msg;
|
|
86
|
+
try {
|
|
87
|
+
msg = deserialize(data);
|
|
88
|
+
} catch (e) {
|
|
89
|
+
if (options.onGeneralError?.(e) !== true)
|
|
90
|
+
throw e;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (msg.t === TYPE_REQUEST) {
|
|
84
94
|
const { m: method, a: args } = msg;
|
|
85
95
|
let result, error;
|
|
86
96
|
const fn = resolver ? resolver(method, functions[method]) : functions[method];
|
|
@@ -96,7 +106,26 @@ function createBirpc(functions, options) {
|
|
|
96
106
|
if (msg.i) {
|
|
97
107
|
if (error && options.onError)
|
|
98
108
|
options.onError(error, method, args);
|
|
99
|
-
|
|
109
|
+
if (error && options.onFunctionError) {
|
|
110
|
+
if (options.onFunctionError(error, method, args) === true)
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (!error) {
|
|
114
|
+
try {
|
|
115
|
+
post(serialize({ t: TYPE_RESPONSE, i: msg.i, r: result }), ...extra);
|
|
116
|
+
return;
|
|
117
|
+
} catch (e) {
|
|
118
|
+
error = e;
|
|
119
|
+
if (options.onGeneralError?.(e, method, args) !== true)
|
|
120
|
+
throw e;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
post(serialize({ t: TYPE_RESPONSE, i: msg.i, e: error }), ...extra);
|
|
125
|
+
} catch (e) {
|
|
126
|
+
if (options.onGeneralError?.(e, method, args) !== true)
|
|
127
|
+
throw e;
|
|
128
|
+
}
|
|
100
129
|
}
|
|
101
130
|
} else {
|
|
102
131
|
const { i: ack, r: result, e: error } = msg;
|
|
@@ -237,15 +266,6 @@ function getBrowserState() {
|
|
|
237
266
|
|
|
238
267
|
const channel = new BroadcastChannel(`vitest:${getBrowserState().sessionId}`);
|
|
239
268
|
const globalChannel = new BroadcastChannel("vitest:global");
|
|
240
|
-
function waitForChannel(event) {
|
|
241
|
-
return new Promise((resolve) => {
|
|
242
|
-
channel.addEventListener("message", (e) => {
|
|
243
|
-
if (e.data?.type === event) {
|
|
244
|
-
resolve();
|
|
245
|
-
}
|
|
246
|
-
}, { once: true });
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
269
|
|
|
250
270
|
const PAGE_TYPE = getBrowserState().type;
|
|
251
271
|
const PORT = location.port;
|
|
@@ -257,6 +277,23 @@ let setCancel = (_) => {};
|
|
|
257
277
|
const onCancel = new Promise((resolve) => {
|
|
258
278
|
setCancel = resolve;
|
|
259
279
|
});
|
|
280
|
+
function waitForOrchestrator() {
|
|
281
|
+
return new Promise((resolve, reject) => {
|
|
282
|
+
const type = getBrowserState().type;
|
|
283
|
+
if (type !== "orchestrator") {
|
|
284
|
+
reject(new TypeError("Only orchestrator can create testers."));
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
function check() {
|
|
288
|
+
const orchestrator = getBrowserState().orchestrator;
|
|
289
|
+
if (orchestrator) {
|
|
290
|
+
return resolve(orchestrator);
|
|
291
|
+
}
|
|
292
|
+
setTimeout(check);
|
|
293
|
+
}
|
|
294
|
+
check();
|
|
295
|
+
});
|
|
296
|
+
}
|
|
260
297
|
function createClient() {
|
|
261
298
|
const reconnectInterval = 2e3;
|
|
262
299
|
const reconnectTries = 10;
|
|
@@ -269,11 +306,13 @@ function createClient() {
|
|
|
269
306
|
let onMessage;
|
|
270
307
|
ctx.rpc = createBirpc({
|
|
271
308
|
onCancel: setCancel,
|
|
272
|
-
async createTesters(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
309
|
+
async createTesters(options) {
|
|
310
|
+
const orchestrator = await waitForOrchestrator();
|
|
311
|
+
return orchestrator.createTesters(options);
|
|
312
|
+
},
|
|
313
|
+
async cleanupTesters() {
|
|
314
|
+
const orchestrator = await waitForOrchestrator();
|
|
315
|
+
return orchestrator.cleanupTesters();
|
|
277
316
|
},
|
|
278
317
|
cdpEvent(event, payload) {
|
|
279
318
|
const cdp = getBrowserState().cdp;
|
|
@@ -303,6 +342,7 @@ function createClient() {
|
|
|
303
342
|
}, {
|
|
304
343
|
post: (msg) => ctx.ws.send(msg),
|
|
305
344
|
on: (fn) => onMessage = fn,
|
|
345
|
+
timeout: -1,
|
|
306
346
|
serialize: (e) => stringify(e, (_, v) => {
|
|
307
347
|
if (v instanceof Error) {
|
|
308
348
|
return {
|
|
@@ -358,4 +398,4 @@ function createClient() {
|
|
|
358
398
|
}
|
|
359
399
|
const client = createClient();
|
|
360
400
|
|
|
361
|
-
export { ENTRY_URL, HOST, PORT, RPC_ID, channel, client, globalChannel, onCancel
|
|
401
|
+
export { ENTRY_URL, HOST, PORT, RPC_ID, channel, client, globalChannel, onCancel };
|
package/dist/context.js
CHANGED
|
@@ -323,18 +323,18 @@ const page = {
|
|
|
323
323
|
viewport(width, height) {
|
|
324
324
|
const id = getBrowserState().iframeId;
|
|
325
325
|
channel.postMessage({
|
|
326
|
-
|
|
326
|
+
event: "viewport",
|
|
327
327
|
width,
|
|
328
328
|
height,
|
|
329
|
-
id
|
|
329
|
+
iframeId: id
|
|
330
330
|
});
|
|
331
331
|
return new Promise((resolve, reject) => {
|
|
332
332
|
channel.addEventListener("message", function handler(e) {
|
|
333
|
-
if (e.data.
|
|
333
|
+
if (e.data.event === "viewport:done" && e.data.iframeId === id) {
|
|
334
334
|
channel.removeEventListener("message", handler);
|
|
335
335
|
resolve();
|
|
336
336
|
}
|
|
337
|
-
if (e.data.
|
|
337
|
+
if (e.data.event === "viewport:fail" && e.data.iframeId === id) {
|
|
338
338
|
channel.removeEventListener("message", handler);
|
|
339
339
|
reject(new Error(e.data.error));
|
|
340
340
|
}
|
package/dist/expect-element.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{expect,chai}from"vitest";import{k as kAriaCheckedRoles,i as getAriaChecked,j as getAriaRole,l as getAriaDisabled,m as beginAriaCaches,n as endAriaCaches,o as isElementVisible$1,p as getElementAccessibleDescription,q as getElementAccessibleErrorMessage,r as getElementAccessibleName,s as cssEscape}from"./public-utils-
|
|
1
|
+
import{expect,chai}from"vitest";import{k as kAriaCheckedRoles,i as getAriaChecked,j as getAriaRole,l as getAriaDisabled,m as beginAriaCaches,n as endAriaCaches,o as isElementVisible$1,p as getElementAccessibleDescription,q as getElementAccessibleErrorMessage,r as getElementAccessibleName,s as cssEscape}from"./public-utils-DUr23h1p.js";import{L as Locator,p as processTimeoutOptions}from"./index-C3ICQ6zz.js";import{server}from"@vitest/browser/context";import"vitest/utils";function getAriaCheckedRoles(){return[...kAriaCheckedRoles]}function getElementFromUserInput(_,K,q){if(_ instanceof Locator&&(_=_.element()),_ instanceof HTMLElement||_ instanceof SVGElement)return _;throw new UserInputElementTypeError(_,K,q)}function getNodeFromUserInput(_,K,q){if(_ instanceof Locator&&(_=_.element()),_ instanceof Node)return _;throw new UserInputNodeTypeError(_,K,q)}function getMessage(_,K,q,J,Y,X){return[`${K}\n`,`${q}:\n${_.utils.EXPECTED_COLOR(redent(display(_,J),2))}`,`${Y}:\n${_.utils.RECEIVED_COLOR(redent(display(_,X),2))}`].join(`
|
|
2
2
|
`)}function redent(_,K){return indentString(stripIndent(_),K)}function indentString(_,K){let q=/^(?!\s*$)/gm;return _.replace(q,` `.repeat(K))}function minIndent(_){let K=_.match(/^[ \t]*(?=\S)/gm);return K?K.reduce((_,K)=>Math.min(_,K.length),1/0):0}function stripIndent(_){let K=minIndent(_);if(K===0)return _;let q=RegExp(`^[ \\t]{${K}}`,`gm`);return _.replace(q,``)}function display(_,K){return typeof K==`string`?K:_.utils.stringify(K)}function toSentence(_,{wordConnector:K=`, `,lastWordConnector:q=` and `}={}){return[_.slice(0,-1).join(K),_[_.length-1]].join(_.length>1?q:``)}class GenericTypeError extends Error{constructor(_,K,q,J){super(),Error.captureStackTrace&&Error.captureStackTrace(this,q);let Y=``;try{Y=J.utils.printWithType(`Received`,K,J.utils.printReceived)}catch{}this.message=[J.utils.matcherHint(`${J.isNot?`.not`:``}.${q.name}`,`received`,``),``,`${J.utils.RECEIVED_COLOR(`received`)} value must ${_} or a Locator that returns ${_}.`,Y].join(`
|
|
3
3
|
`)}}class UserInputElementTypeError extends GenericTypeError{constructor(_,K,q){super(`an HTMLElement or an SVGElement`,_,K,q)}}class UserInputNodeTypeError extends GenericTypeError{constructor(_,K,q){super(`a Node`,_,K,q)}}function getTag(_){return _ instanceof HTMLFormElement?`FORM`:_.tagName.toUpperCase()}function isInputElement(_){return getTag(_)===`INPUT`}function getSingleElementValue(_){if(_)switch(getTag(_)){case`INPUT`:return getInputValue(_);case`SELECT`:return getSelectValue(_);default:return _.value??getAccessibleValue(_)}}function getSelectValue({multiple:_,options:K}){let q=[...K].filter(_=>_.selected);if(_)return[...q].map(_=>_.value);if(q.length!==0)return q[0].value}function getInputValue(_){switch(_.type){case`number`:return _.value===``?null:Number(_.value);case`checkbox`:return _.checked;default:return _.value}}const rolesSupportingValues=[`meter`,`progressbar`,`slider`,`spinbutton`];function getAccessibleValue(_){if(rolesSupportingValues.includes(_.getAttribute(`role`)||``))return Number(_.getAttribute(`aria-valuenow`))}function normalize(_){return _.replace(/\s+/g,` `).trim()}function matches(_,K){return K instanceof RegExp?K.test(_):_.includes(String(K))}function arrayAsSetComparison(_,K){if(Array.isArray(_)&&Array.isArray(K)){let q=new Set(K);for(let K of new Set(_))if(!q.has(K))return!1;return!0}}const supportedRoles=getAriaCheckedRoles();function toBeChecked(_){let K=getElementFromUserInput(_,toBeChecked,this),q=()=>isInputElement(K)&&[`checkbox`,`radio`].includes(K.type),X=()=>supportedRoles.includes(getAriaRole(K)||``)&&[`true`,`false`].includes(K.getAttribute(`aria-checked`)||``);if(!q()&&!X())return{pass:!1,message:()=>`only inputs with type="checkbox" or type="radio" or elements with ${supportedRolesSentence()} and a valid aria-checked attribute can be used with .toBeChecked(). Use .toHaveValue() instead`};let Z=getAriaChecked(K),Q=Z===!0;return{pass:Q,message:()=>{let _=Q?`is`:`is not`;return[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeChecked`,`element`,``),``,`Received element ${_} checked:`,` ${this.utils.printReceived(K.cloneNode(!1))}`].join(`
|
|
4
4
|
`)}}}function supportedRolesSentence(){return toSentence(supportedRoles.map(_=>`role="${_}"`),{lastWordConnector:` or `})}function toBeEmptyDOMElement(_){let K=getElementFromUserInput(_,toBeEmptyDOMElement,this);return{pass:isEmptyElement(K),message:()=>[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeEmptyDOMElement`,`element`,``),``,`Received:`,` ${this.utils.printReceived(K.innerHTML)}`].join(`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{server,page}from"@vitest/browser/context";import{I as Ivya,e as getByRoleSelector,c as getByAltTextSelector,f as getByLabelSelector,b as getByPlaceholderSelector,d as getByTestIdSelector,a as getByTextSelector,g as getByTitleSelector,h as getElementError}from"./public-utils-DUr23h1p.js";function ensureAwaited(e){let b=getWorkerState().current;if(!b||b.type!==`test`)return e();let x=!1,S=Error(`STACK_TRACE_ERROR`);b.onFinished??=[],b.onFinished.push(()=>{if(!x){let e=Error(`The call was not awaited. This method is asynchronous and must be awaited; otherwise, the call will not start to avoid unhandled rejections.`);throw e.stack=S.stack?.replace(S.message,e.message),e}});let C;return{then(b,w){return x=!0,(C||=e(S)).then(b,w)},catch(b){return(C||=e(S)).catch(b)},finally(b){return(C||=e(S)).finally(b)},[Symbol.toStringTag]:`Promise`}}function getBrowserState(){return window.__vitest_browser_runner__}function getWorkerState(){let e=window.__vitest_worker__;if(!e)throw Error(`Worker state is not found. This is an issue with Vitest. Please, open an issue.`);return e}const provider=getBrowserState().provider;function convertElementToCssSelector(e){if(!e||!(e instanceof Element))throw Error(`Expected DOM element to be an instance of Element, received ${typeof e}`);return getUniqueCssSelector(e)}function escapeIdForCSSSelector(e){return e.split(``).map(e=>{let b=e.charCodeAt(0);return e===` `||e===`#`||e===`.`||e===`:`||e===`[`||e===`]`||e===`>`||e===`+`||e===`~`||e===`\\`?`\\${e}`:b>=65536?`\\${b.toString(16).toUpperCase().padStart(6,`0`)} `:b<32||b===127||b>=128?`\\${b.toString(16).toUpperCase().padStart(2,`0`)} `:e}).join(``)}function getUniqueCssSelector(e){let b=[],x,S=!1;for(;x=getParent(e);){x.shadowRoot&&(S=!0);let C=e.tagName;if(e.id)b.push(`#${escapeIdForCSSSelector(e.id)}`);else if(!e.nextElementSibling&&!e.previousElementSibling)b.push(C.toLowerCase());else{let S=0,w=0,T=0;for(let b of x.children)S++,b.tagName===C&&w++,b===e&&(T=S);w>1?b.push(`${C.toLowerCase()}:nth-child(${T})`):b.push(C.toLowerCase())}e=x}return`${getBrowserState().provider===`webdriverio`&&S?`>>>`:``}${b.reverse().join(` > `)}`}function getParent(e){let b=e.parentNode;return b instanceof ShadowRoot?b.host:b}const now=Date.now;function processTimeoutOptions(e){if(e&&e.timeout!=null||provider!==`playwright`||getWorkerState().config.browser.providerOptions.actionTimeout!=null)return e;let b=getBrowserState().runner,x=b._currentTaskStartTime;if(!x)return e;let S=b._currentTaskTimeout;if(S===0||S==null||S===1/0)return e;e||={};let C=now(),w=x+S,T=w-C;return T<=0||(e.timeout=T-100),e}function getIframeScale(){let e=window.parent.document.querySelector(`iframe[data-vitest]`)?.parentElement;if(!e)throw Error(`Cannot find Tester element. This is a bug in Vitest. Please, open a new issue with reproduction.`);let b=e.getAttribute(`data-scale`),x=Number(b);if(Number.isNaN(x))throw TypeError(`Cannot parse scale value from Tester element (${b}). This is a bug in Vitest. Please, open a new issue with reproduction.`);return x}function escapeRegexForSelector(e){return e.unicode||e.unicodeSets?String(e):String(e).replace(/(^|[^\\])(\\\\)*(["'`])/g,`$1$2\\$3`).replace(/>>/g,`\\>\\>`)}function escapeForTextSelector(e,b){return typeof e==`string`?`${JSON.stringify(e)}i`:escapeRegexForSelector(e)}const selectorEngine=Ivya.create({browser:(e=>{switch(e){case`edge`:case`chrome`:return`chromium`;case`safari`:return`webkit`;default:return e}})(server.config.browser.name),testIdAttribute:server.config.browser.locators.testIdAttribute});class Locator{_parsedSelector;_container;_pwSelector;click(e={}){return this.triggerCommand(`__vitest_click`,this.selector,e)}dblClick(e={}){return this.triggerCommand(`__vitest_dblClick`,this.selector,e)}tripleClick(e={}){return this.triggerCommand(`__vitest_tripleClick`,this.selector,e)}clear(e){return this.triggerCommand(`__vitest_clear`,this.selector,e)}hover(e){return this.triggerCommand(`__vitest_hover`,this.selector,e)}unhover(e){return this.triggerCommand(`__vitest_hover`,`html > body`,e)}fill(e,b){return this.triggerCommand(`__vitest_fill`,this.selector,e,b)}async upload(e,b){let x=(Array.isArray(e)?e:[e]).map(async e=>{if(typeof e==`string`)return e;let b=await new Promise((b,x)=>{let S=new FileReader;S.onload=()=>b(S.result),S.onerror=()=>x(Error(`Failed to read file: ${e.name}`)),S.readAsDataURL(e)});return{name:e.name,mimeType:e.type,base64:b}});return this.triggerCommand(`__vitest_upload`,this.selector,await Promise.all(x),b)}dropTo(e,b={}){return this.triggerCommand(`__vitest_dragAndDrop`,this.selector,e.selector,b)}selectOptions(e,b){let x=(Array.isArray(e)?e:[e]).map(e=>{if(typeof e!=`string`){let b=`element`in e?e.selector:selectorEngine.generateSelectorSimple(e);return{element:b}}return e});return this.triggerCommand(`__vitest_selectOptions`,this.selector,x,b)}screenshot(e){return page.screenshot({...e,element:this})}getByRole(e,b){return this.locator(getByRoleSelector(e,b))}getByAltText(e,b){return this.locator(getByAltTextSelector(e,b))}getByLabelText(e,b){return this.locator(getByLabelSelector(e,b))}getByPlaceholder(e,b){return this.locator(getByPlaceholderSelector(e,b))}getByTestId(b){return this.locator(getByTestIdSelector(server.config.browser.locators.testIdAttribute,b))}getByText(e,b){return this.locator(getByTextSelector(e,b))}getByTitle(e,b){return this.locator(getByTitleSelector(e,b))}filter(e){let b=[];if(e?.hasText&&b.push(`internal:has-text=${escapeForTextSelector(e.hasText)}`),e?.hasNotText&&b.push(`internal:has-not-text=${escapeForTextSelector(e.hasNotText)}`),e?.has){let x=e.has;b.push(`internal:has=${JSON.stringify(x._pwSelector||x.selector)}`)}if(e?.hasNot){let x=e.hasNot;b.push(`internal:has-not=${JSON.stringify(x._pwSelector||x.selector)}`)}if(!b.length)throw Error(`Locator.filter expects at least one filter. None provided.`);return this.locator(b.join(` >> `))}and(e){return this.locator(`internal:and=${JSON.stringify(e._pwSelector||e.selector)}`)}or(e){return this.locator(`internal:or=${JSON.stringify(e._pwSelector||e.selector)}`)}query(){let e=this._parsedSelector||=selectorEngine.parseSelector(this._pwSelector||this.selector);return selectorEngine.querySelector(e,document.documentElement,!0)}element(){let e=this.query();if(!e)throw getElementError(this._pwSelector||this.selector,this._container||document.body);return e}elements(){let e=this._parsedSelector||=selectorEngine.parseSelector(this._pwSelector||this.selector);return selectorEngine.querySelectorAll(e,document.documentElement)}all(){return this.elements().map(e=>this.elementLocator(e))}nth(e){return this.locator(`nth=${e}`)}first(){return this.nth(0)}last(){return this.nth(-1)}toString(){return this.selector}toJSON(){return this.selector}triggerCommand(e,...b){let x=getBrowserState().commands;return ensureAwaited(S=>x.triggerCommand(e,b,S))}}export{Locator as L,getBrowserState as a,convertElementToCssSelector as c,getIframeScale as g,processTimeoutOptions as p,selectorEngine as s};
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Plugin } from 'vitest/config';
|
|
|
2
2
|
import { CDPSession, BrowserServerState as BrowserServerState$1, ProjectBrowser as ProjectBrowser$1, TestProject, BrowserProvider, Vitest, ResolvedConfig, Vite, BrowserCommand, BrowserScript, ProcessPool } from 'vitest/node';
|
|
3
3
|
import { StackTraceParserOptions } from '@vitest/utils/source-map';
|
|
4
4
|
import { ViteDevServer, HtmlTagDescriptor } from 'vite';
|
|
5
|
-
import { CancelReason, RunnerTestFile, AfterSuiteRunMeta, UserConsoleLog, SnapshotResult, SerializedConfig, ErrorWithDiff, ParsedStack } from 'vitest';
|
|
5
|
+
import { CancelReason, BrowserTesterOptions, TestExecutionMethod, RunnerTestFile, AfterSuiteRunMeta, UserConsoleLog, SnapshotResult, SerializedConfig, ErrorWithDiff, ParsedStack } from 'vitest';
|
|
6
6
|
import { MockedModuleSerialized } from '@vitest/mocker';
|
|
7
7
|
import { ServerIdResolution, ServerMockResolution } from '@vitest/mocker/node';
|
|
8
8
|
import { TaskResultPack, TaskEventPack } from '@vitest/runner';
|
|
@@ -20,24 +20,23 @@ type BirpcReturn<RemoteFunctions, LocalFunctions = Record<string, never>> = {
|
|
|
20
20
|
[K in keyof RemoteFunctions]: BirpcFn<RemoteFunctions[K]>;
|
|
21
21
|
} & {
|
|
22
22
|
$functions: LocalFunctions;
|
|
23
|
-
$close: () => void;
|
|
23
|
+
$close: (error?: Error) => void;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
interface WebSocketBrowserHandlers {
|
|
27
27
|
resolveSnapshotPath: (testPath: string) => string;
|
|
28
28
|
resolveSnapshotRawPath: (testPath: string, rawPath: string) => string;
|
|
29
29
|
onUnhandledError: (error: unknown, type: string) => Promise<void>;
|
|
30
|
-
onQueued: (file: RunnerTestFile) => void;
|
|
31
|
-
onCollected: (files: RunnerTestFile[]) => Promise<void>;
|
|
32
|
-
onTaskUpdate: (packs: TaskResultPack[], events: TaskEventPack[]) => void;
|
|
30
|
+
onQueued: (method: TestExecutionMethod, file: RunnerTestFile) => void;
|
|
31
|
+
onCollected: (method: TestExecutionMethod, files: RunnerTestFile[]) => Promise<void>;
|
|
32
|
+
onTaskUpdate: (method: TestExecutionMethod, packs: TaskResultPack[], events: TaskEventPack[]) => void;
|
|
33
33
|
onAfterSuiteRun: (meta: AfterSuiteRunMeta) => void;
|
|
34
34
|
onCancel: (reason: CancelReason) => void;
|
|
35
35
|
getCountOfFailedTests: () => number;
|
|
36
36
|
readSnapshotFile: (id: string) => Promise<string | null>;
|
|
37
37
|
saveSnapshotFile: (id: string, content: string) => Promise<void>;
|
|
38
38
|
removeSnapshotFile: (id: string) => Promise<void>;
|
|
39
|
-
sendLog: (log: UserConsoleLog) => void;
|
|
40
|
-
finishBrowserTests: (sessionId: string) => void;
|
|
39
|
+
sendLog: (method: TestExecutionMethod, log: UserConsoleLog) => void;
|
|
41
40
|
snapshotSaved: (snapshot: SnapshotResult) => void;
|
|
42
41
|
debug: (...args: string[]) => void;
|
|
43
42
|
resolveId: (id: string, importer?: string) => Promise<ServerIdResolution | null>;
|
|
@@ -58,7 +57,8 @@ interface WebSocketBrowserHandlers {
|
|
|
58
57
|
}
|
|
59
58
|
interface WebSocketBrowserEvents {
|
|
60
59
|
onCancel: (reason: CancelReason) => void;
|
|
61
|
-
createTesters: (
|
|
60
|
+
createTesters: (options: BrowserTesterOptions) => Promise<void>;
|
|
61
|
+
cleanupTesters: () => Promise<void>;
|
|
62
62
|
cdpEvent: (event: string, payload: unknown) => void;
|
|
63
63
|
resolveManualMock: (url: string) => Promise<{
|
|
64
64
|
url: string
|