@vitest/browser 4.0.7 → 4.0.9
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 +35 -35
- package/dist/client/.vite/manifest.json +1 -1
- package/dist/client/__vitest__/assets/index-VPnwgb7M.css +1 -0
- package/dist/client/__vitest__/assets/index-zBMt7UWw.js +57 -0
- package/dist/client/__vitest__/index.html +2 -2
- package/dist/client/__vitest_browser__/{tester-C3iDyL-N.js → tester-BLe1dg8x.js} +5 -5
- package/dist/client/tester/tester.html +1 -1
- package/dist/client.js +109 -65
- package/dist/expect-element.js +4 -4
- package/dist/index-hFpxawnd.js +6 -0
- package/dist/index.js +117 -67
- package/dist/locators.js +1 -1
- package/jest-dom.d.ts +29 -29
- package/package.json +8 -8
- package/dist/client/__vitest__/assets/index-COTh6lXR.css +0 -1
- package/dist/client/__vitest__/assets/index-DYO2mJ8d.js +0 -53
- package/dist/index-BnLTaCRv.js +0 -6
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
})();
|
|
24
24
|
</script>
|
|
25
25
|
<!-- !LOAD_METADATA! -->
|
|
26
|
-
<script type="module" src="./assets/index-
|
|
27
|
-
<link rel="stylesheet" href="./assets/index-
|
|
26
|
+
<script type="module" src="./assets/index-zBMt7UWw.js"></script>
|
|
27
|
+
<link rel="stylesheet" href="./assets/index-VPnwgb7M.css">
|
|
28
28
|
</head>
|
|
29
29
|
<body>
|
|
30
30
|
<div id="app"></div>
|
|
@@ -257,7 +257,7 @@ var hasRequiredResolveUri_umd;
|
|
|
257
257
|
function requireResolveUri_umd() {
|
|
258
258
|
if (hasRequiredResolveUri_umd) return resolveUri_umd$1.exports;
|
|
259
259
|
hasRequiredResolveUri_umd = 1;
|
|
260
|
-
(function(module, exports) {
|
|
260
|
+
(function(module, exports$1) {
|
|
261
261
|
(function(global, factory) {
|
|
262
262
|
module.exports = factory();
|
|
263
263
|
})(resolveUri_umd, (function() {
|
|
@@ -1376,18 +1376,18 @@ class ManualMockedModule {
|
|
|
1376
1376
|
if (this.cache) {
|
|
1377
1377
|
return this.cache;
|
|
1378
1378
|
}
|
|
1379
|
-
let exports;
|
|
1379
|
+
let exports$1;
|
|
1380
1380
|
try {
|
|
1381
|
-
exports = await this.factory();
|
|
1381
|
+
exports$1 = await this.factory();
|
|
1382
1382
|
} catch (err) {
|
|
1383
1383
|
const vitestError = new Error('[vitest] There was an error when mocking a module. If you are using "vi.mock" factory, make sure there are no top level variables inside, since this call is hoisted to top of the file. Read more: https://vitest.dev/api/vi.html#vi-mock');
|
|
1384
1384
|
vitestError.cause = err;
|
|
1385
1385
|
throw vitestError;
|
|
1386
1386
|
}
|
|
1387
|
-
if (exports === null || typeof exports !== "object" || Array.isArray(exports)) {
|
|
1387
|
+
if (exports$1 === null || typeof exports$1 !== "object" || Array.isArray(exports$1)) {
|
|
1388
1388
|
throw new TypeError(`[vitest] vi.mock("${this.raw}", factory?: () => unknown) is not returning an object. Did you mean to return an object with a "default" key?`);
|
|
1389
1389
|
}
|
|
1390
|
-
return this.cache = exports;
|
|
1390
|
+
return this.cache = exports$1;
|
|
1391
1391
|
}
|
|
1392
1392
|
static fromJSON(data, factory) {
|
|
1393
1393
|
return new ManualMockedModule(data.raw, data.id, data.url, factory);
|
|
@@ -5,7 +5,7 @@
|
|
|
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-
|
|
8
|
+
<script type="module" crossorigin src="/__vitest_browser__/tester-BLe1dg8x.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-uxqdqUz8.js">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
package/dist/client.js
CHANGED
|
@@ -7,7 +7,7 @@ function defaultSerialize(i) {
|
|
|
7
7
|
const defaultDeserialize = defaultSerialize;
|
|
8
8
|
const { clearTimeout: clearTimeout$1, setTimeout: setTimeout$1 } = globalThis;
|
|
9
9
|
const random = Math.random.bind(Math);
|
|
10
|
-
function createBirpc(functions, options) {
|
|
10
|
+
function createBirpc($functions, options) {
|
|
11
11
|
const {
|
|
12
12
|
post,
|
|
13
13
|
on,
|
|
@@ -20,67 +20,100 @@ function createBirpc(functions, options) {
|
|
|
20
20
|
bind = "rpc",
|
|
21
21
|
timeout = DEFAULT_TIMEOUT
|
|
22
22
|
} = options;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
let
|
|
23
|
+
let $closed = false;
|
|
24
|
+
const _rpcPromiseMap = /* @__PURE__ */ new Map();
|
|
25
|
+
let _promiseInit;
|
|
26
|
+
async function _call(method, args, event, optional) {
|
|
27
|
+
if ($closed)
|
|
28
|
+
throw new Error(`[birpc] rpc is closed, cannot call "${method}"`);
|
|
29
|
+
const req = { m: method, a: args, t: TYPE_REQUEST };
|
|
30
|
+
if (optional)
|
|
31
|
+
req.o = true;
|
|
32
|
+
const send = async (_req) => post(serialize(_req));
|
|
33
|
+
if (event) {
|
|
34
|
+
await send(req);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (_promiseInit) {
|
|
38
|
+
try {
|
|
39
|
+
await _promiseInit;
|
|
40
|
+
} finally {
|
|
41
|
+
_promiseInit = void 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
let { promise, resolve, reject } = createPromiseWithResolvers();
|
|
45
|
+
const id = nanoid();
|
|
46
|
+
req.i = id;
|
|
47
|
+
let timeoutId;
|
|
48
|
+
async function handler(newReq = req) {
|
|
49
|
+
if (timeout >= 0) {
|
|
50
|
+
timeoutId = setTimeout$1(() => {
|
|
51
|
+
try {
|
|
52
|
+
const handleResult = options.onTimeoutError?.(method, args);
|
|
53
|
+
if (handleResult !== true)
|
|
54
|
+
throw new Error(`[birpc] timeout on calling "${method}"`);
|
|
55
|
+
} catch (e) {
|
|
56
|
+
reject(e);
|
|
57
|
+
}
|
|
58
|
+
_rpcPromiseMap.delete(id);
|
|
59
|
+
}, timeout);
|
|
60
|
+
if (typeof timeoutId === "object")
|
|
61
|
+
timeoutId = timeoutId.unref?.();
|
|
62
|
+
}
|
|
63
|
+
_rpcPromiseMap.set(id, { resolve, reject, timeoutId, method });
|
|
64
|
+
await send(newReq);
|
|
65
|
+
return promise;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
if (options.onRequest)
|
|
69
|
+
await options.onRequest(req, handler, resolve);
|
|
70
|
+
else
|
|
71
|
+
await handler();
|
|
72
|
+
} catch (e) {
|
|
73
|
+
if (options.onGeneralError?.(e) !== true)
|
|
74
|
+
throw e;
|
|
75
|
+
return;
|
|
76
|
+
} finally {
|
|
77
|
+
clearTimeout$1(timeoutId);
|
|
78
|
+
_rpcPromiseMap.delete(id);
|
|
79
|
+
}
|
|
80
|
+
return promise;
|
|
81
|
+
}
|
|
82
|
+
const $call = (method, ...args) => _call(method, args, false);
|
|
83
|
+
const $callOptional = (method, ...args) => _call(method, args, false, true);
|
|
84
|
+
const $callEvent = (method, ...args) => _call(method, args, true);
|
|
85
|
+
const $callRaw = (options2) => _call(options2.method, options2.args, options2.event, options2.optional);
|
|
86
|
+
const builtinMethods = {
|
|
87
|
+
$call,
|
|
88
|
+
$callOptional,
|
|
89
|
+
$callEvent,
|
|
90
|
+
$callRaw,
|
|
91
|
+
$rejectPendingCalls,
|
|
92
|
+
get $closed() {
|
|
93
|
+
return $closed;
|
|
94
|
+
},
|
|
95
|
+
$close,
|
|
96
|
+
$functions
|
|
97
|
+
};
|
|
26
98
|
const rpc = new Proxy({}, {
|
|
27
99
|
get(_, method) {
|
|
28
|
-
if (method
|
|
29
|
-
return
|
|
30
|
-
if (method === "
|
|
31
|
-
return close;
|
|
32
|
-
if (method === "$rejectPendingCalls") {
|
|
33
|
-
return rejectPendingCalls;
|
|
34
|
-
}
|
|
35
|
-
if (method === "$closed")
|
|
36
|
-
return closed;
|
|
37
|
-
if (method === "then" && !eventNames.includes("then") && !("then" in functions))
|
|
100
|
+
if (Object.prototype.hasOwnProperty.call(builtinMethods, method))
|
|
101
|
+
return builtinMethods[method];
|
|
102
|
+
if (method === "then" && !eventNames.includes("then") && !("then" in $functions))
|
|
38
103
|
return void 0;
|
|
39
|
-
const sendEvent = (...args) =>
|
|
40
|
-
post(serialize({ m: method, a: args, t: TYPE_REQUEST }));
|
|
41
|
-
};
|
|
104
|
+
const sendEvent = (...args) => _call(method, args, true);
|
|
42
105
|
if (eventNames.includes(method)) {
|
|
43
106
|
sendEvent.asEvent = sendEvent;
|
|
44
107
|
return sendEvent;
|
|
45
108
|
}
|
|
46
|
-
const sendCall =
|
|
47
|
-
if (closed)
|
|
48
|
-
throw new Error(`[birpc] rpc is closed, cannot call "${method}"`);
|
|
49
|
-
if (_promise) {
|
|
50
|
-
try {
|
|
51
|
-
await _promise;
|
|
52
|
-
} finally {
|
|
53
|
-
_promise = void 0;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return new Promise((resolve, reject) => {
|
|
57
|
-
const id = nanoid();
|
|
58
|
-
let timeoutId;
|
|
59
|
-
if (timeout >= 0) {
|
|
60
|
-
timeoutId = setTimeout$1(() => {
|
|
61
|
-
try {
|
|
62
|
-
const handleResult = options.onTimeoutError?.(method, args);
|
|
63
|
-
if (handleResult !== true)
|
|
64
|
-
throw new Error(`[birpc] timeout on calling "${method}"`);
|
|
65
|
-
} catch (e) {
|
|
66
|
-
reject(e);
|
|
67
|
-
}
|
|
68
|
-
rpcPromiseMap.delete(id);
|
|
69
|
-
}, timeout);
|
|
70
|
-
if (typeof timeoutId === "object")
|
|
71
|
-
timeoutId = timeoutId.unref?.();
|
|
72
|
-
}
|
|
73
|
-
rpcPromiseMap.set(id, { resolve, reject, timeoutId, method });
|
|
74
|
-
post(serialize({ m: method, a: args, i: id, t: "q" }));
|
|
75
|
-
});
|
|
76
|
-
};
|
|
109
|
+
const sendCall = (...args) => _call(method, args, false);
|
|
77
110
|
sendCall.asEvent = sendEvent;
|
|
78
111
|
return sendCall;
|
|
79
112
|
}
|
|
80
113
|
});
|
|
81
|
-
function close(customError) {
|
|
82
|
-
closed = true;
|
|
83
|
-
|
|
114
|
+
function $close(customError) {
|
|
115
|
+
$closed = true;
|
|
116
|
+
_rpcPromiseMap.forEach(({ reject, method }) => {
|
|
84
117
|
const error = new Error(`[birpc] rpc is closed, cannot call "${method}"`);
|
|
85
118
|
if (customError) {
|
|
86
119
|
customError.cause ??= error;
|
|
@@ -88,18 +121,18 @@ function createBirpc(functions, options) {
|
|
|
88
121
|
}
|
|
89
122
|
reject(error);
|
|
90
123
|
});
|
|
91
|
-
|
|
124
|
+
_rpcPromiseMap.clear();
|
|
92
125
|
off(onMessage);
|
|
93
126
|
}
|
|
94
|
-
function rejectPendingCalls(handler) {
|
|
95
|
-
const entries = Array.from(
|
|
127
|
+
function $rejectPendingCalls(handler) {
|
|
128
|
+
const entries = Array.from(_rpcPromiseMap.values());
|
|
96
129
|
const handlerResults = entries.map(({ method, reject }) => {
|
|
97
130
|
if (!handler) {
|
|
98
131
|
return reject(new Error(`[birpc]: rejected pending call "${method}".`));
|
|
99
132
|
}
|
|
100
133
|
return handler({ method, reject });
|
|
101
134
|
});
|
|
102
|
-
|
|
135
|
+
_rpcPromiseMap.clear();
|
|
103
136
|
return handlerResults;
|
|
104
137
|
}
|
|
105
138
|
async function onMessage(data, ...extra) {
|
|
@@ -112,14 +145,16 @@ function createBirpc(functions, options) {
|
|
|
112
145
|
return;
|
|
113
146
|
}
|
|
114
147
|
if (msg.t === TYPE_REQUEST) {
|
|
115
|
-
const { m: method, a: args } = msg;
|
|
148
|
+
const { m: method, a: args, o: optional } = msg;
|
|
116
149
|
let result, error;
|
|
117
|
-
|
|
150
|
+
let fn = await (resolver ? resolver(method, $functions[method]) : $functions[method]);
|
|
151
|
+
if (optional)
|
|
152
|
+
fn ||= () => void 0;
|
|
118
153
|
if (!fn) {
|
|
119
154
|
error = new Error(`[birpc] function "${method}" not found`);
|
|
120
155
|
} else {
|
|
121
156
|
try {
|
|
122
|
-
result = await fn.apply(bind === "rpc" ? rpc : functions, args);
|
|
157
|
+
result = await fn.apply(bind === "rpc" ? rpc : $functions, args);
|
|
123
158
|
} catch (e) {
|
|
124
159
|
error = e;
|
|
125
160
|
}
|
|
@@ -133,7 +168,7 @@ function createBirpc(functions, options) {
|
|
|
133
168
|
}
|
|
134
169
|
if (!error) {
|
|
135
170
|
try {
|
|
136
|
-
post(serialize({ t: TYPE_RESPONSE, i: msg.i, r: result }), ...extra);
|
|
171
|
+
await post(serialize({ t: TYPE_RESPONSE, i: msg.i, r: result }), ...extra);
|
|
137
172
|
return;
|
|
138
173
|
} catch (e) {
|
|
139
174
|
error = e;
|
|
@@ -142,7 +177,7 @@ function createBirpc(functions, options) {
|
|
|
142
177
|
}
|
|
143
178
|
}
|
|
144
179
|
try {
|
|
145
|
-
post(serialize({ t: TYPE_RESPONSE, i: msg.i, e: error }), ...extra);
|
|
180
|
+
await post(serialize({ t: TYPE_RESPONSE, i: msg.i, e: error }), ...extra);
|
|
146
181
|
} catch (e) {
|
|
147
182
|
if (options.onGeneralError?.(e, method, args) !== true)
|
|
148
183
|
throw e;
|
|
@@ -150,7 +185,7 @@ function createBirpc(functions, options) {
|
|
|
150
185
|
}
|
|
151
186
|
} else {
|
|
152
187
|
const { i: ack, r: result, e: error } = msg;
|
|
153
|
-
const promise =
|
|
188
|
+
const promise = _rpcPromiseMap.get(ack);
|
|
154
189
|
if (promise) {
|
|
155
190
|
clearTimeout$1(promise.timeoutId);
|
|
156
191
|
if (error)
|
|
@@ -158,12 +193,21 @@ function createBirpc(functions, options) {
|
|
|
158
193
|
else
|
|
159
194
|
promise.resolve(result);
|
|
160
195
|
}
|
|
161
|
-
|
|
196
|
+
_rpcPromiseMap.delete(ack);
|
|
162
197
|
}
|
|
163
198
|
}
|
|
164
|
-
|
|
199
|
+
_promiseInit = on(onMessage);
|
|
165
200
|
return rpc;
|
|
166
201
|
}
|
|
202
|
+
function createPromiseWithResolvers() {
|
|
203
|
+
let resolve;
|
|
204
|
+
let reject;
|
|
205
|
+
const promise = new Promise((res, rej) => {
|
|
206
|
+
resolve = res;
|
|
207
|
+
reject = rej;
|
|
208
|
+
});
|
|
209
|
+
return { promise, resolve, reject };
|
|
210
|
+
}
|
|
167
211
|
const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
|
|
168
212
|
function nanoid(size = 21) {
|
|
169
213
|
let id = "";
|
|
@@ -358,8 +402,8 @@ function createClient() {
|
|
|
358
402
|
responseId
|
|
359
403
|
};
|
|
360
404
|
}
|
|
361
|
-
const exports = await mocker.resolveFactoryModule(url);
|
|
362
|
-
const keys = Object.keys(exports);
|
|
405
|
+
const exports$1 = await mocker.resolveFactoryModule(url);
|
|
406
|
+
const keys = Object.keys(exports$1);
|
|
363
407
|
return {
|
|
364
408
|
url,
|
|
365
409
|
keys,
|
package/dist/expect-element.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{expect,chai}from"vitest";import{getType}from"vitest/internal/browser";import{k as kAriaCheckedRoles,L as Locator,g as getAriaChecked,a as getAriaRole,b as getAriaDisabled,c as beginAriaCaches,e as endAriaCaches,i as isElementVisible$1,d as getElementAccessibleDescription,f as getElementAccessibleErrorMessage,h as getElementAccessibleName,j as cssEscape,l as getWorkerState,m as convertToSelector,n as getBrowserState,p as processTimeoutOptions}from"./index-
|
|
1
|
+
import{expect,chai}from"vitest";import{getType}from"vitest/internal/browser";import{k as kAriaCheckedRoles,L as Locator,g as getAriaChecked,a as getAriaRole,b as getAriaDisabled,c as beginAriaCaches,e as endAriaCaches,i as isElementVisible$1,d as getElementAccessibleDescription,f as getElementAccessibleErrorMessage,h as getElementAccessibleName,j as cssEscape,l as getWorkerState,m as convertToSelector,n as getBrowserState,p as processTimeoutOptions}from"./index-hFpxawnd.js";import{server}from"vitest/browser";function getAriaCheckedRoles(){return[...kAriaCheckedRoles]}function queryElementFromUserInput(_,K,q){return _ instanceof Locator&&(_=_.query()),_==null?null:getElementFromUserInput(_,K,q)}function getElementFromUserInput(_,K,q){_ instanceof Locator&&(_=_.element());let J=_?.ownerDocument?.defaultView||window;if(_ instanceof J.HTMLElement||_ instanceof J.SVGElement)return _;throw new UserInputElementTypeError(_,K,q)}function getNodeFromUserInput(_,K,q){_ instanceof Locator&&(_=_.element());let J=_.ownerDocument?.defaultView||window;if(_ instanceof J.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){return _.replace(/^(?!\s*$)/gm,` `.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),_.at(-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);if(!(()=>isInputElement(K)&&[`checkbox`,`radio`].includes(K.type))()&&!(()=>supportedRoles.includes(getAriaRole(K)||``)&&[`true`,`false`].includes(K.getAttribute(`aria-checked`)||``))())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 q=getAriaChecked(K)===!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(`
|
|
@@ -18,10 +18,10 @@ import{expect,chai}from"vitest";import{getType}from"vitest/internal/browser";imp
|
|
|
18
18
|
|
|
19
19
|
`):getMessage(this,this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveAccessibleErrorMessage`,`element`,``),`Expected element ${_} have accessible error message`,K,`Received`,J)}}}function toHaveAccessibleName(_,K){let q=getElementFromUserInput(_,toHaveAccessibleName,this),J=getElementAccessibleName(q,!1),Y=arguments.length===1,X=q.ownerDocument.defaultView||window,Z=!1;return Z=Y?J!==``:K instanceof X.RegExp?K.test(J):this.equals(J,K,this.customTesters),{pass:Z,message:()=>{let _=this.isNot?`not to`:`to`;return getMessage(this,this.utils.matcherHint(`${this.isNot?`.not`:``}.${toHaveAccessibleName.name}`,`element`,``),`Expected element ${_} have accessible name`,K,`Received`,J)}}}function toHaveAttribute(_,K,q){let J=getElementFromUserInput(_,toHaveAttribute,this),Y=q!==void 0,X=J.hasAttribute(K),Z=J.getAttribute(K);return{pass:Y?X&&this.equals(Z,q,this.customTesters):X,message:()=>{let _=this.isNot?`not to`:`to`,J=X?printAttribute(this.utils.stringify,K,Z):null,Q=this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveAttribute`,`element`,this.utils.printExpected(K),{secondArgument:Y?this.utils.printExpected(q):void 0,comment:getAttributeComment(this.utils.stringify,K,q)});return getMessage(this,Q,`Expected the element ${_} have attribute`,printAttribute(this.utils.stringify,K,q),`Received`,J)}}}function printAttribute(_,K,q){return q===void 0?K:`${K}=${_(q)}`}function getAttributeComment(_,K,q){return q===void 0?`element.hasAttribute(${_(K)})`:`element.getAttribute(${_(K)}) === ${_(q)}`}function toHaveClass(_,...K){let q=getElementFromUserInput(_,toHaveClass,this),{expectedClassNames:J,options:Y}=getExpectedClassNamesAndOptions(K),X=splitClassNames(q.getAttribute(`class`)),Z=J.reduce((_,K)=>_.concat(typeof K==`string`||!K?splitClassNames(K):K),[]),Q=Z.some(_=>_ instanceof RegExp);if(Y.exact&&Q)throw Error(`Exact option does not support RegExp expected class names`);return Y.exact?{pass:isSubset$1(Z,X)&&Z.length===X.length,message:()=>{let _=this.isNot?`not to`:`to`;return getMessage(this,this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveClass`,`element`,this.utils.printExpected(Z.join(` `))),`Expected the element ${_} have EXACTLY defined classes`,Z.join(` `),`Received`,X.join(` `))}}:Z.length>0?{pass:isSubset$1(Z,X),message:()=>{let _=this.isNot?`not to`:`to`;return getMessage(this,this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveClass`,`element`,this.utils.printExpected(Z.join(` `))),`Expected the element ${_} have class`,Z.join(` `),`Received`,X.join(` `))}}:{pass:this.isNot?X.length>0:!1,message:()=>this.isNot?getMessage(this,this.utils.matcherHint(`.not.toHaveClass`,`element`,``),`Expected the element to have classes`,`(none)`,`Received`,X.join(` `)):[this.utils.matcherHint(`.toHaveClass`,`element`),`At least one expected class must be provided.`].join(`
|
|
20
20
|
`)}}function getExpectedClassNamesAndOptions(_){let K=_.pop(),q,J;return typeof K==`object`&&!(K instanceof RegExp)?(q=_,J=K):(q=_.concat(K),J={exact:!1}),{expectedClassNames:q,options:J}}function splitClassNames(_){return _?_.split(/\s+/).filter(_=>_.length>0):[]}function isSubset$1(_,K){return _.every(_=>typeof _==`string`?K.includes(_):K.some(K=>_.test(K)))}function toHaveDisplayValue(_,K){let q=getElementFromUserInput(_,toHaveDisplayValue,this),J=getTag(q);if(![`SELECT`,`INPUT`,`TEXTAREA`].includes(J))throw Error(`.toHaveDisplayValue() currently supports only input, textarea or select elements, try with another matcher instead.`);if(isInputElement(q)&&[`radio`,`checkbox`].includes(q.type))throw Error(`.toHaveDisplayValue() currently does not support input[type="${q.type}"], try with another matcher instead.`);let Y=getValues(J,q),X=getExpectedValues(K),Z=X.filter(_=>Y.some(K=>_ instanceof RegExp?_.test(K):this.equals(K,String(_),this.customTesters))).length,Q=Z===Y.length,$=Z===X.length;return{pass:Q&&$,message:()=>getMessage(this,this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveDisplayValue`,`element`,``),`Expected element ${this.isNot?`not `:``}to have display value`,K,`Received`,Y)}}function getValues(_,K){return _===`SELECT`?Array.from(K).filter(_=>_.selected).map(_=>_.textContent||``):[K.value]}function getExpectedValues(_){return Array.isArray(_)?_:[_]}function toHaveFocus(_){let K=getElementFromUserInput(_,toHaveFocus,this);return{pass:K.ownerDocument.activeElement===K,message:()=>[this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveFocus`,`element`,``),``,...this.isNot?[`Received element is focused:`,` ${this.utils.printReceived(K)}`]:[`Expected element with focus:`,` ${this.utils.printExpected(K)}`,`Received element with focus:`,` ${this.utils.printReceived(K.ownerDocument.activeElement)}`]].join(`
|
|
21
|
-
`)}}function toHaveFormValues(_,K){let q=getElementFromUserInput(_,toHaveFormValues,this),J=q.ownerDocument.defaultView||window;if(!(q instanceof J.HTMLFieldSetElement)&&!(q instanceof J.HTMLFormElement))throw TypeError(`toHaveFormValues must be called on a form or a fieldset, instead got ${getTag(q)}`);if(!K||typeof K!=`object`)throw TypeError(`toHaveFormValues must be called with an object of expected form values. Got ${K}`);let Y=getAllFormValues(q);return{pass:Object.entries(K).every(([_,K])=>this.equals(Y[_],K,[arrayAsSetComparison,...this.customTesters])),message:()=>{let _=this.isNot?`not to`:`to`,q=`${this.isNot?`.not`:``}.toHaveFormValues`,J={};for(let _ in Y)
|
|
21
|
+
`)}}function toHaveFormValues(_,K){let q=getElementFromUserInput(_,toHaveFormValues,this),J=q.ownerDocument.defaultView||window;if(!(q instanceof J.HTMLFieldSetElement)&&!(q instanceof J.HTMLFormElement))throw TypeError(`toHaveFormValues must be called on a form or a fieldset, instead got ${getTag(q)}`);if(!K||typeof K!=`object`)throw TypeError(`toHaveFormValues must be called with an object of expected form values. Got ${K}`);let Y=getAllFormValues(q);return{pass:Object.entries(K).every(([_,K])=>this.equals(Y[_],K,[arrayAsSetComparison,...this.customTesters])),message:()=>{let _=this.isNot?`not to`:`to`,q=`${this.isNot?`.not`:``}.toHaveFormValues`,J={};for(let _ in Y)Object.hasOwn(K,_)&&(J[_]=Y[_]);return[this.utils.matcherHint(q,`element`,``),`Expected the element ${_} have form values`,this.utils.diff(K,J)].join(`
|
|
22
22
|
|
|
23
|
-
`)}}}function getMultiElementValue(_){let K=``;for(let q of _){if(K&&K!==q.type)throw Error(`Multiple form elements with the same name must be of the same type`);K=q.type}switch(K){case`radio`:{let K=_.find(_=>_.checked);return K?K.value:void 0}case`checkbox`:return _.filter(_=>_.checked).map(_=>_.value);default:return _.map(_=>_.value)}}function getFormValue(_,K){let q=[..._.querySelectorAll(`[name="${cssEscape(K)}"]`)];if(q.length!==0)switch(q.length){case 1:return getSingleElementValue(q[0]);default:return getMultiElementValue(q)}}function getPureName(_){return/\[\]$/.test(_)?_.slice(0,-2):_}function getAllFormValues(_){let K={};for(let q of _.elements){if(!(`name`in q))continue;let J=q.name;K[getPureName(J)]=getFormValue(_,J)}return K}function toHaveRole(_,K){let q=getElementFromUserInput(_,toHaveRole,this);beginAriaCaches();let J=getAriaRole(q);return endAriaCaches(),{pass:J===K,message:()=>{let _=this.isNot?`not to`:`to`;return getMessage(this,this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveRole`,`element`,``),`Expected element ${_} have role`,K,`Received`,J)}}}function toHaveSelection(_,K){let q=getElementFromUserInput(_,toHaveSelection,this),J=K!==void 0;if(J&&typeof K!=`string`)throw Error(`expected selection must be a string or undefined`);let Y=getSelection(q);return{pass:J?this.equals(Y,K,[arrayAsSetComparison,...this.customTesters]):!!Y,message:()=>{let _=this.isNot?`not to`:`to`,q=this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveSelection`,`element`,K);return getMessage(this,q,`Expected the element ${_} have selection`,J?K:`(any)`,`Received`,Y)}}}function getSelection(_){let K=_.ownerDocument.getSelection();if(!K)return``;if([`INPUT`,`TEXTAREA`].includes(getTag(_))){let K=_;return[`radio`,`checkbox`].includes(K.type)||K.selectionStart==null||K.selectionEnd==null?``:K.value.toString().substring(K.selectionStart,K.selectionEnd)}if(K.anchorNode===null||K.focusNode===null)return``;let q=K.getRangeAt(0),J=_.ownerDocument.createRange();if(K.containsNode(_,!1))J.selectNodeContents(_),K.removeAllRanges(),K.addRange(J);else if(!(_.contains(K.anchorNode)&&_.contains(K.focusNode))){let Y=_===q.startContainer||_.contains(q.startContainer),X=_===q.endContainer||_.contains(q.endContainer);K.removeAllRanges(),(Y||X)&&(J.selectNodeContents(_),Y&&J.setStart(q.startContainer,q.startOffset),X&&J.setEnd(q.endContainer,q.endOffset),K.addRange(J))}let Y=K.toString();return K.removeAllRanges(),K.addRange(q),Y}const browser=server.config.browser.name,usedValuesProps=new Set(`backgroundPosition.background-position.bottom.left.right.top.height.width.margin-bottom.marginBottom.margin-left.marginLeft.margin-right.marginRight.margin-top.marginTop.min-height.minHeight.min-width.minWidth.padding-bottom.padding-left.padding-right.padding-top.text-indent.paddingBottom.paddingLeft.paddingRight.paddingTop.textIndent`.split(`.`));function toHaveStyle(_,K){let q=getElementFromUserInput(_,toHaveStyle,this),{getComputedStyle:J}=q.ownerDocument.defaultView,Y=typeof K==`object`?getStyleFromObjectCSS(K):computeCSSStyleDeclaration(K),X=J(q),Z=new Set(Array.from(q.style));return{pass:isSubset(Y,q,X,Z),message:()=>{let _=`${this.isNot?`.not`:``}.toHaveStyle`,K=new Set(Object.keys(Y)),J=Array.from(X).filter(_=>K.has(_)).reduce((_,K)=>(_[K]=(Z.has(K)&&usedValuesProps.has(K)?q.style:X)[K],_),{}),Q=
|
|
23
|
+
`)}}}function getMultiElementValue(_){let K=``;for(let q of _){if(K&&K!==q.type)throw Error(`Multiple form elements with the same name must be of the same type`);K=q.type}switch(K){case`radio`:{let K=_.find(_=>_.checked);return K?K.value:void 0}case`checkbox`:return _.filter(_=>_.checked).map(_=>_.value);default:return _.map(_=>_.value)}}function getFormValue(_,K){let q=[..._.querySelectorAll(`[name="${cssEscape(K)}"]`)];if(q.length!==0)switch(q.length){case 1:return getSingleElementValue(q[0]);default:return getMultiElementValue(q)}}function getPureName(_){return/\[\]$/.test(_)?_.slice(0,-2):_}function getAllFormValues(_){let K={};for(let q of _.elements){if(!(`name`in q))continue;let J=q.name;K[getPureName(J)]=getFormValue(_,J)}return K}function toHaveRole(_,K){let q=getElementFromUserInput(_,toHaveRole,this);beginAriaCaches();let J=getAriaRole(q);return endAriaCaches(),{pass:J===K,message:()=>{let _=this.isNot?`not to`:`to`;return getMessage(this,this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveRole`,`element`,``),`Expected element ${_} have role`,K,`Received`,J)}}}function toHaveSelection(_,K){let q=getElementFromUserInput(_,toHaveSelection,this),J=K!==void 0;if(J&&typeof K!=`string`)throw Error(`expected selection must be a string or undefined`);let Y=getSelection(q);return{pass:J?this.equals(Y,K,[arrayAsSetComparison,...this.customTesters]):!!Y,message:()=>{let _=this.isNot?`not to`:`to`,q=this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveSelection`,`element`,K);return getMessage(this,q,`Expected the element ${_} have selection`,J?K:`(any)`,`Received`,Y)}}}function getSelection(_){let K=_.ownerDocument.getSelection();if(!K)return``;if([`INPUT`,`TEXTAREA`].includes(getTag(_))){let K=_;return[`radio`,`checkbox`].includes(K.type)||K.selectionStart==null||K.selectionEnd==null?``:K.value.toString().substring(K.selectionStart,K.selectionEnd)}if(K.anchorNode===null||K.focusNode===null)return``;let q=K.getRangeAt(0),J=_.ownerDocument.createRange();if(K.containsNode(_,!1))J.selectNodeContents(_),K.removeAllRanges(),K.addRange(J);else if(!(_.contains(K.anchorNode)&&_.contains(K.focusNode))){let Y=_===q.startContainer||_.contains(q.startContainer),X=_===q.endContainer||_.contains(q.endContainer);K.removeAllRanges(),(Y||X)&&(J.selectNodeContents(_),Y&&J.setStart(q.startContainer,q.startOffset),X&&J.setEnd(q.endContainer,q.endOffset),K.addRange(J))}let Y=K.toString();return K.removeAllRanges(),K.addRange(q),Y}const browser=server.config.browser.name,usedValuesProps=new Set(`backgroundPosition.background-position.bottom.left.right.top.height.width.margin-bottom.marginBottom.margin-left.marginLeft.margin-right.marginRight.margin-top.marginTop.min-height.minHeight.min-width.minWidth.padding-bottom.padding-left.padding-right.padding-top.text-indent.paddingBottom.paddingLeft.paddingRight.paddingTop.textIndent`.split(`.`));function toHaveStyle(_,K){let q=getElementFromUserInput(_,toHaveStyle,this),{getComputedStyle:J}=q.ownerDocument.defaultView,Y=typeof K==`object`?getStyleFromObjectCSS(K):computeCSSStyleDeclaration(K),X=J(q),Z=new Set(Array.from(q.style));return{pass:isSubset(Y,q,X,Z),message:()=>{let _=`${this.isNot?`.not`:``}.toHaveStyle`,K=new Set(Object.keys(Y)),J=printoutObjectStyles(Array.from(X).filter(_=>K.has(_)).reduce((_,K)=>(_[K]=(Z.has(K)&&usedValuesProps.has(K)?q.style:X)[K],_),{})),Q=J===``?`Expected styles could not be parsed by the browser. Did you make a typo?`:this.utils.diff(printoutObjectStyles(Y),J);return[this.utils.matcherHint(_,`element`,``),Q].join(`
|
|
24
24
|
|
|
25
25
|
`)}}}function getStyleFromObjectCSS(_){let K=browser===`chrome`||browser===`chromium`?document:document.implementation.createHTMLDocument(``),q=K.createElement(`div`);K.body.appendChild(q);let J=Object.keys(_);J.forEach(K=>{q.style[K]=_[K]});let Y={},X=window.getComputedStyle(q);return J.forEach(_=>{let K=(usedValuesProps.has(_)?q.style:X)[_];K!=null&&(Y[_]=K)}),q.remove(),Y}function computeCSSStyleDeclaration(_){let K=browser===`chrome`||browser===`chromium`||browser===`webkit`?document:document.implementation.createHTMLDocument(``),q=K.createElement(`div`);q.setAttribute(`style`,_.replace(/\n/g,``)),K.body.appendChild(q);let J=window.getComputedStyle(q),Y=Array.from(q.style).reduce((_,K)=>(_[K]=usedValuesProps.has(K)?q.style.getPropertyValue(K):J.getPropertyValue(K),_),{});return q.remove(),Y}function printoutObjectStyles(_){return Object.keys(_).sort().map(K=>`${K}: ${_[K]};`).join(`
|
|
26
26
|
`)}function isSubset(_,K,q,J){let Y=Object.keys(_);return Y.length?Y.every(Y=>{let X=_[Y],Z=Y.startsWith(`--`),Q=[Y];return Z||Q.push(Y.toLowerCase()),Q.some(_=>{let Z=J.has(Y)&&usedValuesProps.has(Y)?K.style:q;return Z[_]===X||Z.getPropertyValue(_)===X})}):!1}function toHaveTextContent(_,K,q={normalizeWhitespace:!0}){let J=getNodeFromUserInput(_,toHaveTextContent,this),Y=q.normalizeWhitespace?normalize(J.textContent||``):(J.textContent||``).replace(/\u00A0/g,` `),X=Y!==``&&K===``;return{pass:!X&&matches(Y,K),message:()=>{let _=this.isNot?`not to`:`to`;return getMessage(this,this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveTextContent`,`element`,``),X?`Checking with empty string will always match, use .toBeEmptyDOMElement() instead`:`Expected element ${_} have text content`,K,`Received`,Y)}}}function toHaveValue(_,K){let q=getElementFromUserInput(_,toHaveValue,this);if(isInputElement(q)&&[`checkbox`,`radio`].includes(q.type))throw Error(`input with type=checkbox or type=radio cannot be used with .toHaveValue(). Use .toBeChecked() for type=checkbox or .toHaveFormValues() instead`);let J=getSingleElementValue(q),Y=K!==void 0,X=K,Z=J;return K==J&&K!==J&&(X=`${K} (${typeof K})`,Z=`${J} (${typeof J})`),{pass:Y?this.equals(J,K,[arrayAsSetComparison,...this.customTesters]):!!J,message:()=>{let _=this.isNot?`not to`:`to`,q=this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveValue`,`element`,K);return getMessage(this,q,`Expected the element ${_} have value`,Y?X:`(any)`,`Received`,Z)}}}const counters=new Map([]);async function toMatchScreenshot(_,K,q=typeof K==`object`?K:{}){if(this.isNot)throw Error(`'toMatchScreenshot' cannot be used with "not"`);let J=getWorkerState().current;if(J===void 0||this.currentTestName===void 0)throw Error(`'toMatchScreenshot' cannot be used without test context`);let Y=`${J.result?.repeatCount??0}${this.testPath}${this.currentTestName}`,X=counters.get(Y);X===void 0&&(X={current:0},counters.set(Y,X)),X.current+=1;let Z=typeof K==`string`?K:`${this.currentTestName} ${X.current}`,Q=q.screenshotOptions&&`mask`in q.screenshotOptions?{...q,screenshotOptions:{...q.screenshotOptions,mask:q.screenshotOptions.mask.map(convertToSelector)}}:q,$=await getBrowserState().commands.triggerCommand(`__vitest_screenshotMatcher`,[Z,this.currentTestName,{element:convertToSelector(_),...Q}]);if($.pass===!1&&`context`in J){let{annotate:_}=J.context,K=[];$.reference&&K.push(_(`Reference screenshot`,{path:$.reference})),$.actual&&K.push(_(`Actual screenshot`,{path:$.actual})),$.diff&&K.push(_(`Diff`,{path:$.diff})),await Promise.all(K)}return{pass:$.pass,message:()=>$.pass?``:[this.utils.matcherHint(`toMatchScreenshot`,`element`,``),``,$.message,$.reference?`\nReference screenshot:\n ${this.utils.EXPECTED_COLOR($.reference)}`:null,$.actual?`\nActual screenshot:\n ${this.utils.RECEIVED_COLOR($.actual)}`:null,$.diff?this.utils.DIM_COLOR(`\nDiff image:\n ${$.diff}`):null].filter(_=>_!==null).join(`
|
|
27
|
-
`)}}const matchers={toBeDisabled,toBeEnabled,toBeEmptyDOMElement,toBeInTheDocument,toBeInViewport,toBeInvalid,toBeRequired,toBeValid,toBeVisible,toContainElement,toContainHTML,toHaveAccessibleDescription,toHaveAccessibleErrorMessage,toHaveAccessibleName,toHaveAttribute,toHaveClass,toHaveFocus,toHaveFormValues,toHaveStyle,toHaveTextContent,toHaveValue,toHaveDisplayValue,toBeChecked,toBePartiallyChecked,toHaveRole,toHaveSelection,toMatchScreenshot},kLocator=Symbol.for(`$$vitest:locator`);function element(J,Y){if(J!=null&&!(J instanceof HTMLElement)&&!(J instanceof SVGElement)&&!(kLocator in J))throw Error(`Invalid element or locator: ${J}. Expected an instance of HTMLElement, SVGElement or Locator, received ${getType(J)}`);
|
|
27
|
+
`)}}const matchers={toBeDisabled,toBeEnabled,toBeEmptyDOMElement,toBeInTheDocument,toBeInViewport,toBeInvalid,toBeRequired,toBeValid,toBeVisible,toContainElement,toContainHTML,toHaveAccessibleDescription,toHaveAccessibleErrorMessage,toHaveAccessibleName,toHaveAttribute,toHaveClass,toHaveFocus,toHaveFormValues,toHaveStyle,toHaveTextContent,toHaveValue,toHaveDisplayValue,toBeChecked,toBePartiallyChecked,toHaveRole,toHaveSelection,toMatchScreenshot},kLocator=Symbol.for(`$$vitest:locator`);function element(J,Y){if(J!=null&&!(J instanceof HTMLElement)&&!(J instanceof SVGElement)&&!(kLocator in J))throw Error(`Invalid element or locator: ${J}. Expected an instance of HTMLElement, SVGElement or Locator, received ${getType(J)}`);let X=expect.poll(function(){if(J instanceof Element||J==null)return J;let _=chai.util.flag(this,`negate`),q=chai.util.flag(this,`_name`);if(_&&q===`toBeInTheDocument`)return J.query();if(q===`toHaveLength`)return J.elements();if(chai.util.flag(this,`_isLastPollAttempt`))return J.element();let Y=J.query();if(!Y)throw Error(`Cannot find element with locator: ${JSON.stringify(J)}`);return Y},processTimeoutOptions(Y));return chai.util.flag(X,`_poll.element`,!0),X}expect.extend(matchers),expect.element=element;
|