@vitest/browser 4.0.0-beta.10 → 4.0.0-beta.12

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.
@@ -1,35 +1,27 @@
1
1
  (function polyfill() {
2
2
  const relList = document.createElement("link").relList;
3
- if (relList && relList.supports && relList.supports("modulepreload")) {
4
- return;
5
- }
6
- for (const link of document.querySelectorAll('link[rel="modulepreload"]')) {
7
- processPreload(link);
8
- }
3
+ if (relList && relList.supports && relList.supports("modulepreload")) return;
4
+ for (const link of document.querySelectorAll('link[rel="modulepreload"]')) processPreload(link);
9
5
  new MutationObserver((mutations) => {
10
6
  for (const mutation of mutations) {
11
- if (mutation.type !== "childList") {
12
- continue;
13
- }
14
- for (const node of mutation.addedNodes) {
15
- if (node.tagName === "LINK" && node.rel === "modulepreload")
16
- processPreload(node);
17
- }
7
+ if (mutation.type !== "childList") continue;
8
+ for (const node of mutation.addedNodes) if (node.tagName === "LINK" && node.rel === "modulepreload") processPreload(node);
18
9
  }
19
- }).observe(document, { childList: true, subtree: true });
10
+ }).observe(document, {
11
+ childList: true,
12
+ subtree: true
13
+ });
20
14
  function getFetchOpts(link) {
21
15
  const fetchOpts = {};
22
16
  if (link.integrity) fetchOpts.integrity = link.integrity;
23
17
  if (link.referrerPolicy) fetchOpts.referrerPolicy = link.referrerPolicy;
24
- if (link.crossOrigin === "use-credentials")
25
- fetchOpts.credentials = "include";
18
+ if (link.crossOrigin === "use-credentials") fetchOpts.credentials = "include";
26
19
  else if (link.crossOrigin === "anonymous") fetchOpts.credentials = "omit";
27
20
  else fetchOpts.credentials = "same-origin";
28
21
  return fetchOpts;
29
22
  }
30
23
  function processPreload(link) {
31
- if (link.ep)
32
- return;
24
+ if (link.ep) return;
33
25
  link.ep = true;
34
26
  const fetchOpts = getFetchOpts(link);
35
27
  fetch(link.href, fetchOpts);
@@ -147,6 +139,40 @@ const relative = function(from, to) {
147
139
  }
148
140
  return [..._from.map(() => ".."), ..._to].join("/");
149
141
  };
142
+ // @__NO_SIDE_EFFECTS__
143
+ function generateHash(str) {
144
+ let hash = 0;
145
+ if (str.length === 0) {
146
+ return `${hash}`;
147
+ }
148
+ for (let i = 0; i < str.length; i++) {
149
+ const char = str.charCodeAt(i);
150
+ hash = (hash << 5) - hash + char;
151
+ hash = hash & hash;
152
+ }
153
+ return `${hash}`;
154
+ }
155
+ // @__NO_SIDE_EFFECTS__
156
+ function generateFileHash(file, projectName) {
157
+ return /* @__PURE__ */ generateHash(`${file}${projectName || ""}`);
158
+ }
159
+ function getNames(task) {
160
+ const names = [task.name];
161
+ let current = task;
162
+ while (current === null || current === void 0 ? void 0 : current.suite) {
163
+ current = current.suite;
164
+ if (current === null || current === void 0 ? void 0 : current.name) {
165
+ names.unshift(current.name);
166
+ }
167
+ }
168
+ if (current !== task.file) {
169
+ names.unshift(task.file.name);
170
+ }
171
+ return names;
172
+ }
173
+ function getTestName(task, separator = " > ") {
174
+ return getNames(task).slice(1).join(separator);
175
+ }
150
176
  async function importId(id) {
151
177
  const name = `/@id/${id}`.replace(/\\/g, "/");
152
178
  return (/* @__PURE__ */ getBrowserState()).wrapModule(() => import(
@@ -187,8 +213,10 @@ function getWorkerState() {
187
213
  }
188
214
  export {
189
215
  getConfig as a,
190
- resolve as b,
191
- getWorkerState as c,
216
+ generateFileHash as b,
217
+ resolve as c,
218
+ getWorkerState as d,
219
+ getTestName as e,
192
220
  getBrowserState as g,
193
221
  moduleRunner as m,
194
222
  relative as r
@@ -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-BXX6oamz.js"></script>
30
- <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-CPmDBIKG.js">
29
+ <script type="module" crossorigin src="/__vitest_browser__/orchestrator-Pdu7HCGX.js"></script>
30
+ <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-uxqdqUz8.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-CMhJ1E1W.js"></script>
9
- <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-CPmDBIKG.js">
8
+ <script type="module" crossorigin src="/__vitest_browser__/tester-DYNLfPFH.js"></script>
9
+ <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-uxqdqUz8.js">
10
10
  </head>
11
11
  <body>
12
12
  </body>
@@ -1,15 +1,15 @@
1
- import{expect,chai}from"vitest";import{getType}from"vitest/internal/browser";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-Kx5DUGWa.js";import{L as Locator,b as getWorkerState,d as convertToSelector,a as getBrowserState,p as processTimeoutOptions}from"./index-DDlvjJVO.js";import{server}from"@vitest/browser/context";function getAriaCheckedRoles(){return[...kAriaCheckedRoles]}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
- `)}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),_.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
- `)}}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),J=()=>supportedRoles.includes(getAriaRole(K)||``)&&[`true`,`false`].includes(K.getAttribute(`aria-checked`)||``);if(!q()&&!J())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(`
1
+ import{expect,chai}from"vitest";import{getType}from"vitest/internal/browser";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-B6exS8fl.js";import{L as Locator,b as getWorkerState,d as convertToSelector,a as getBrowserState,p as processTimeoutOptions}from"./index-BPDFwkoW.js";import{server}from"@vitest/browser/context";function getAriaCheckedRoles(){return[...kAriaCheckedRoles]}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
+ `)}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
+ `)}}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(`
5
- `)}}function isEmptyElement(_){let K=[..._.childNodes].filter(_=>_.nodeType!==Node.COMMENT_NODE);return K.length===0}function toBeDisabled(_){let K=getElementFromUserInput(_,toBeDisabled,this),q=isElementDisabled(K);return{pass:q,message:()=>{let _=q?`is`:`is not`;return[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeDisabled`,`element`,``),``,`Received element ${_} disabled:`,` ${this.utils.printReceived(K.cloneNode(!1))}`].join(`
5
+ `)}}function isEmptyElement(_){return[..._.childNodes].filter(_=>_.nodeType!==Node.COMMENT_NODE).length===0}function toBeDisabled(_){let K=getElementFromUserInput(_,toBeDisabled,this),q=isElementDisabled(K);return{pass:q,message:()=>{let _=q?`is`:`is not`;return[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeDisabled`,`element`,``),``,`Received element ${_} disabled:`,` ${this.utils.printReceived(K.cloneNode(!1))}`].join(`
6
6
  `)}}}function toBeEnabled(_){let K=getElementFromUserInput(_,toBeEnabled,this),q=isElementDisabled(K);return{pass:!q,message:()=>{let _=q?`is not`:`is`;return[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeEnabled`,`element`,``),``,`Received element ${_} enabled:`,` ${this.utils.printReceived(K.cloneNode(!1))}`].join(`
7
7
  `)}}}function isElementDisabled(_){return getTag(_).includes(`-`)?_.hasAttribute(`disabled`):getAriaDisabled(_)}function toBeInTheDocument(_){let K=null;(_!==null||!this.isNot)&&(K=getElementFromUserInput(_,toBeInTheDocument,this));let q=K===null?!1:K.ownerDocument===K.getRootNode({composed:!0}),J=()=>`expected document not to contain element, found ${this.utils.stringify(K?.cloneNode(!0))} instead`,Y=()=>`element could not be found in the document`;return{pass:q,message:()=>[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeInTheDocument`,`element`,``),``,this.utils.RECEIVED_COLOR(this.isNot?J():Y())].join(`
8
8
  `)}}const FORM_TAGS$1=[`FORM`,`INPUT`,`SELECT`,`TEXTAREA`];function isElementHavingAriaInvalid(_){return _.hasAttribute(`aria-invalid`)&&_.getAttribute(`aria-invalid`)!==`false`}function isSupportsValidityMethod(_){return FORM_TAGS$1.includes(getTag(_))}function isElementInvalid(_){let K=isElementHavingAriaInvalid(_);return isSupportsValidityMethod(_)?K||!_.checkValidity():K}function toBeInvalid(_){let K=getElementFromUserInput(_,toBeInvalid,this),q=isElementInvalid(K);return{pass:q,message:()=>{let _=q?`is`:`is not`;return[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeInvalid`,`element`,``),``,`Received element ${_} currently invalid:`,` ${this.utils.printReceived(K.cloneNode(!1))}`].join(`
9
9
  `)}}}function toBeValid(_){let K=getElementFromUserInput(_,toBeInvalid,this),q=!isElementInvalid(K);return{pass:q,message:()=>{let _=q?`is`:`is not`;return[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeValid`,`element`,``),``,`Received element ${_} currently valid:`,` ${this.utils.printReceived(K.cloneNode(!1))}`].join(`
10
10
  `)}}}function toBeInViewport(_,K){let q=getElementFromUserInput(_,toBeInViewport,this),J=K?.ratio??0;return getViewportIntersection(q,J).then(({pass:_,ratio:K})=>({pass:_,message:()=>{let Y=_?`is`:`is not`,X=J>0?` with ratio ${J}`:``,Z=K===void 0?``:` (actual ratio: ${K.toFixed(3)})`;return[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeInViewport`,`element`,``),``,`Received element ${Y} in viewport${X}${Z}:`,` ${this.utils.printReceived(q.cloneNode(!1))}`].join(`
11
- `)}}))}async function getViewportIntersection(_,K){let q=await new Promise(K=>{let q=new IntersectionObserver(_=>{_.length>0?K(_[0].intersectionRatio):K(0),q.disconnect()});q.observe(_),requestAnimationFrame(()=>{})}),J=q>0&&q>K-1e-9;return{pass:J,ratio:q}}function toBePartiallyChecked(_){let K=getElementFromUserInput(_,toBePartiallyChecked,this),q=()=>isInputElement(K)&&K.type===`checkbox`,J=()=>K.getAttribute(`role`)===`checkbox`;if(!q()&&!J())return{pass:!1,message:()=>`only inputs with type="checkbox" or elements with role="checkbox" and a valid aria-checked attribute can be used with .toBePartiallyChecked(). Use .toHaveValue() instead`};let Y=isAriaMixed(K);return{pass:Y,message:()=>{let _=Y?`is`:`is not`;return[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBePartiallyChecked`,`element`,``),``,`Received element ${_} partially checked:`,` ${this.utils.printReceived(K.cloneNode(!1))}`].join(`
12
- `)}}}function isAriaMixed(_){let K=getAriaChecked(_)===`mixed`;if(!K&&isInputElement(_)&&[`checkbox`,`radio`].includes(_.type)){let K=_.getAttribute(`aria-checked`);if(K===`mixed`)return!0}return K}const FORM_TAGS=[`SELECT`,`TEXTAREA`],ARIA_FORM_TAGS=[`INPUT`,`SELECT`,`TEXTAREA`],UNSUPPORTED_INPUT_TYPES=[`color`,`hidden`,`range`,`submit`,`image`,`reset`],SUPPORTED_ARIA_ROLES=[`checkbox`,`combobox`,`gridcell`,`listbox`,`radiogroup`,`spinbutton`,`textbox`,`tree`];function isRequiredOnFormTagsExceptInput(_){return FORM_TAGS.includes(getTag(_))&&_.hasAttribute(`required`)}function isRequiredOnSupportedInput(_){return getTag(_)===`INPUT`&&_.hasAttribute(`required`)&&(_.hasAttribute(`type`)&&!UNSUPPORTED_INPUT_TYPES.includes(_.getAttribute(`type`)||``)||!_.hasAttribute(`type`))}function isElementRequiredByARIA(_){return _.hasAttribute(`aria-required`)&&_.getAttribute(`aria-required`)===`true`&&(ARIA_FORM_TAGS.includes(getTag(_))||_.hasAttribute(`role`)&&SUPPORTED_ARIA_ROLES.includes(_.getAttribute(`role`)||``))}function toBeRequired(_){let K=getElementFromUserInput(_,toBeRequired,this),q=isRequiredOnFormTagsExceptInput(K)||isRequiredOnSupportedInput(K)||isElementRequiredByARIA(K);return{pass:q,message:()=>{let _=q?`is`:`is not`;return[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeRequired`,`element`,``),``,`Received element ${_} required:`,` ${this.utils.printReceived(K.cloneNode(!1))}`].join(`
11
+ `)}}))}async function getViewportIntersection(_,K){let q=await new Promise(K=>{let q=new IntersectionObserver(_=>{_.length>0?K(_[0].intersectionRatio):K(0),q.disconnect()});q.observe(_),requestAnimationFrame(()=>{})});return{pass:q>0&&q>K-1e-9,ratio:q}}function toBePartiallyChecked(_){let K=getElementFromUserInput(_,toBePartiallyChecked,this);if(!(()=>isInputElement(K)&&K.type===`checkbox`)()&&!(()=>K.getAttribute(`role`)===`checkbox`)())return{pass:!1,message:()=>`only inputs with type="checkbox" or elements with role="checkbox" and a valid aria-checked attribute can be used with .toBePartiallyChecked(). Use .toHaveValue() instead`};let q=isAriaMixed(K);return{pass:q,message:()=>{let _=q?`is`:`is not`;return[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBePartiallyChecked`,`element`,``),``,`Received element ${_} partially checked:`,` ${this.utils.printReceived(K.cloneNode(!1))}`].join(`
12
+ `)}}}function isAriaMixed(_){let K=getAriaChecked(_)===`mixed`;return!K&&isInputElement(_)&&[`checkbox`,`radio`].includes(_.type)&&_.getAttribute(`aria-checked`)===`mixed`?!0:K}const FORM_TAGS=[`SELECT`,`TEXTAREA`],ARIA_FORM_TAGS=[`INPUT`,`SELECT`,`TEXTAREA`],UNSUPPORTED_INPUT_TYPES=[`color`,`hidden`,`range`,`submit`,`image`,`reset`],SUPPORTED_ARIA_ROLES=[`checkbox`,`combobox`,`gridcell`,`listbox`,`radiogroup`,`spinbutton`,`textbox`,`tree`];function isRequiredOnFormTagsExceptInput(_){return FORM_TAGS.includes(getTag(_))&&_.hasAttribute(`required`)}function isRequiredOnSupportedInput(_){return getTag(_)===`INPUT`&&_.hasAttribute(`required`)&&(_.hasAttribute(`type`)&&!UNSUPPORTED_INPUT_TYPES.includes(_.getAttribute(`type`)||``)||!_.hasAttribute(`type`))}function isElementRequiredByARIA(_){return _.hasAttribute(`aria-required`)&&_.getAttribute(`aria-required`)===`true`&&(ARIA_FORM_TAGS.includes(getTag(_))||_.hasAttribute(`role`)&&SUPPORTED_ARIA_ROLES.includes(_.getAttribute(`role`)||``))}function toBeRequired(_){let K=getElementFromUserInput(_,toBeRequired,this),q=isRequiredOnFormTagsExceptInput(K)||isRequiredOnSupportedInput(K)||isElementRequiredByARIA(K);return{pass:q,message:()=>{let _=q?`is`:`is not`;return[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeRequired`,`element`,``),``,`Received element ${_} required:`,` ${this.utils.printReceived(K.cloneNode(!1))}`].join(`
13
13
  `)}}}function toBeVisible(_){let K=getElementFromUserInput(_,toBeVisible,this),q=K.ownerDocument===K.getRootNode({composed:!0});beginAriaCaches();let J=q&&isElementVisible(K);return endAriaCaches(),{pass:J,message:()=>{let _=J?`is`:`is not`;return[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeVisible`,`element`,``),``,`Received element ${_} visible${q?``:` (element is not in the document)`}:`,` ${this.utils.printReceived(K.cloneNode(!1))}`].join(`
14
14
  `)}}}function isElementVisible(_){let K=isElementVisible$1(_);if(server.browser!==`webkit`)return K;let q=_.closest(`details`);return!q||_===q?K:isElementVisibleInDetails(_)}function isElementVisibleInDetails(_){let K=_;for(;K;){if(K.tagName===`DETAILS`){let q=K.querySelector(`summary`)===_;if(!K.open&&!q)return!1}K=K.parentElement}return _.offsetParent!==null}function toContainElement(_,K){let q=getElementFromUserInput(_,toContainElement,this),J=K===null?null:getElementFromUserInput(K,toContainElement,this);return{pass:q.contains(J),message:()=>[this.utils.matcherHint(`${this.isNot?`.not`:``}.toContainElement`,`element`,`element`),``,this.utils.RECEIVED_COLOR(`${this.utils.stringify(q.cloneNode(!1))} ${this.isNot?`contains:`:`does not contain:`} ${this.utils.stringify(J?J.cloneNode(!1):null)}
15
15
  `)].join(`
@@ -20,8 +20,8 @@ import{expect,chai}from"vitest";import{getType}from"vitest/internal/browser";imp
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
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){if(!Object.hasOwn(K,_))continue;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=[...new Set(_.map(_=>_.type))];if(K.length!==1)throw Error(`Multiple form elements with the same name must be of the same type`);switch(K[0]){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)=>{let J=Z.has(K)&&usedValuesProps.has(K)?q.style:X;return _[K]=J[K],_},{}),Q=printoutObjectStyles(J),$=Q===``?`Expected styles could not be parsed by the browser. Did you make a typo?`:this.utils.diff(printoutObjectStyles(Y),Q);return[this.utils.matcherHint(_,`element`,``),$].join(`
23
+ `)}}}function getMultiElementValue(_){let K=[...new Set(_.map(_=>_.type))];if(K.length!==1)throw Error(`Multiple form elements with the same name must be of the same type`);switch(K[0]){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=printoutObjectStyles(J),$=Q===``?`Expected styles could not be parsed by the browser. Did you make a typo?`:this.utils.diff(printoutObjectStyles(Y),Q);return[this.utils.matcherHint(_,`element`,``),$].join(`
24
24
 
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,J=K[_];J!=null&&(Y[_]=J)}),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
- `)}function isSubset(_,K,q,J){let Y=Object.keys(_);return Y.length?Y.every(Y=>{let X=_[Y],Z=Y.startsWith(`--`),Q=[Y];Z||Q.push(Y.toLowerCase());let $=Q.some(_=>{let Z=J.has(Y)&&usedValuesProps.has(Y)?K.style:q;return Z[_]===X||Z.getPropertyValue(_)===X});return $}):!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)}`);return expect.poll(function(){if(J instanceof Element||J==null)return J;chai.util.flag(this,`_poll.element`,!0);let _=chai.util.flag(this,`negate`),q=chai.util.flag(this,`_name`);if(_&&q===`toBeInTheDocument`)return J.query();if(q===`toHaveLength`)return J.elements();let Y=chai.util.flag(this,`_isLastPollAttempt`);if(Y)return J.element();let X=J.query();if(!X)throw Error(`Cannot find element with locator: ${JSON.stringify(J)}`);return X},processTimeoutOptions(Y))}expect.extend(matchers),Object.assign(expect,{element});
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
+ `)}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)}`);return expect.poll(function(){if(J instanceof Element||J==null)return J;chai.util.flag(this,`_poll.element`,!0);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))}expect.extend(matchers),expect.element=element;
@@ -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-B6exS8fl.js";function ensureAwaited(e){let S=getWorkerState().current;if(!S||S.type!==`test`)return e();let C=!1,w=Error(`STACK_TRACE_ERROR`);S.onFinished??=[],S.onFinished.push(()=>{if(!C){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=w.stack?.replace(w.message,e.message),e}});let T;return{then(S,E){return C=!0,(T||=e(w)).then(S,E)},catch(S){return(T||=e(w)).catch(S)},finally(S){return(T||=e(w)).finally(S)},[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 S=e.charCodeAt(0);return e===` `||e===`#`||e===`.`||e===`:`||e===`[`||e===`]`||e===`>`||e===`+`||e===`~`||e===`\\`?`\\${e}`:S>=65536?`\\${S.toString(16).toUpperCase().padStart(6,`0`)} `:S<32||S===127||S>=128?`\\${S.toString(16).toUpperCase().padStart(2,`0`)} `:e}).join(``)}function getUniqueCssSelector(e){let S=[],C,w=!1;for(;C=getParent(e);){C.shadowRoot&&(w=!0);let T=e.tagName;if(e.id)S.push(`#${escapeIdForCSSSelector(e.id)}`);else if(!e.nextElementSibling&&!e.previousElementSibling)S.push(T.toLowerCase());else{let w=0,E=0,D=0;for(let S of C.children)w++,S.tagName===T&&E++,S===e&&(D=w);E>1?S.push(`${T.toLowerCase()}:nth-child(${D})`):S.push(T.toLowerCase())}e=C}return`${getBrowserState().provider===`webdriverio`&&w?`>>>`:``}${S.reverse().join(` > `)}`}function getParent(e){let S=e.parentNode;return S instanceof ShadowRoot?S.host:S}const now=Date.now;function processTimeoutOptions(e){if(e&&e.timeout!=null||provider!==`playwright`||getWorkerState().config.browser.providerOptions.actionTimeout!=null)return e;let S=getBrowserState().runner,C=S._currentTaskStartTime;if(!C)return e;let w=S._currentTaskTimeout;if(w===0||w==null||w===1/0)return e;e||={};let T=now(),E=C+w-T;return E<=0||(e.timeout=E-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 S=e.getAttribute(`data-scale`),C=Number(S);if(Number.isNaN(C))throw TypeError(`Cannot parse scale value from Tester element (${S}). This is a bug in Vitest. Please, open a new issue with reproduction.`);return C}function escapeRegexForSelector(e){return e.unicode||e.unicodeSets?String(e):String(e).replace(/(^|[^\\])(\\\\)*(["'`])/g,`$1$2\\$3`).replace(/>>/g,`\\>\\>`)}function escapeForTextSelector(e,S){return typeof e==`string`?`${JSON.stringify(e)}i`:escapeRegexForSelector(e)}function convertToSelector(e){if(!e)throw Error(`Expected element or locator to be defined.`);if(e instanceof Element)return convertElementToCssSelector(e);if(`selector`in e)return e.selector;throw Error(`Expected element or locator to be an instance of Element or Locator.`)}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}),kLocator=Symbol.for(`$$vitest:locator`);class Locator{_parsedSelector;_container;_pwSelector;constructor(){Object.defineProperty(this,kLocator,{enumerable:!1,writable:!1,configurable:!1,value:kLocator})}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,S){return this.triggerCommand(`__vitest_fill`,this.selector,e,S)}async upload(e,S){let C=(Array.isArray(e)?e:[e]).map(async e=>{if(typeof e==`string`)return e;let S=await new Promise((S,C)=>{let w=new FileReader;w.onload=()=>S(w.result),w.onerror=()=>C(Error(`Failed to read file: ${e.name}`)),w.readAsDataURL(e)});return{name:e.name,mimeType:e.type,base64:S}});return this.triggerCommand(`__vitest_upload`,this.selector,await Promise.all(C),S)}dropTo(e,S={}){return this.triggerCommand(`__vitest_dragAndDrop`,this.selector,e.selector,S)}selectOptions(e,S){let C=(Array.isArray(e)?e:[e]).map(e=>typeof e==`string`?e:{element:`element`in e?e.selector:selectorEngine.generateSelectorSimple(e)});return this.triggerCommand(`__vitest_selectOptions`,this.selector,C,S)}screenshot(e){return page.screenshot({...e,element:this})}getByRole(e,S){return this.locator(getByRoleSelector(e,S))}getByAltText(e,S){return this.locator(getByAltTextSelector(e,S))}getByLabelText(e,S){return this.locator(getByLabelSelector(e,S))}getByPlaceholder(e,S){return this.locator(getByPlaceholderSelector(e,S))}getByTestId(S){return this.locator(getByTestIdSelector(server.config.browser.locators.testIdAttribute,S))}getByText(e,S){return this.locator(getByTextSelector(e,S))}getByTitle(e,S){return this.locator(getByTitleSelector(e,S))}filter(e){let S=[];if(e?.hasText&&S.push(`internal:has-text=${escapeForTextSelector(e.hasText)}`),e?.hasNotText&&S.push(`internal:has-not-text=${escapeForTextSelector(e.hasNotText)}`),e?.has){let C=e.has;S.push(`internal:has=${JSON.stringify(C._pwSelector||C.selector)}`)}if(e?.hasNot){let C=e.hasNot;S.push(`internal:has-not=${JSON.stringify(C._pwSelector||C.selector)}`)}if(!S.length)throw Error(`Locator.filter expects at least one filter. None provided.`);return this.locator(S.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)}get length(){return this.elements().length}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,...S){let C=getBrowserState().commands;return ensureAwaited(w=>C.triggerCommand(e,S,w))}}export{Locator as L,getBrowserState as a,getWorkerState as b,convertElementToCssSelector as c,convertToSelector as d,getIframeScale as g,processTimeoutOptions as p,selectorEngine as s};
package/dist/index.js CHANGED
@@ -1,17 +1,16 @@
1
1
  import { ManualMockedModule, RedirectedModule, AutomockedModule, AutospiedModule, MockerRegistry } from '@vitest/mocker';
2
2
  import { dynamicImportPlugin, ServerMockResolver, interceptorPlugin } from '@vitest/mocker/node';
3
3
  import c from 'tinyrainbow';
4
- import { isValidApiRequest, isFileServingAllowed, distDir, resolveApiServerConfig, resolveFsAllow, createDebugger, createViteLogger, createViteServer } from 'vitest/node';
4
+ import { isValidApiRequest, isFileServingAllowed, distDir, resolveApiServerConfig, resolveFsAllow, rolldownVersion, createDebugger, createViteLogger, createViteServer } from 'vitest/node';
5
5
  import fs, { readFileSync, lstatSync, createReadStream, promises, existsSync } from 'node:fs';
6
6
  import { createRequire } from 'node:module';
7
- import { slash as slash$1, toArray, deepMerge, createDefer } from '@vitest/utils';
7
+ import { slash as slash$1, toArray, deepMerge, createDefer } from '@vitest/utils/helpers';
8
8
  import MagicString from 'magic-string';
9
9
  import sirv from 'sirv';
10
- import * as vite from 'vite';
11
10
  import { coverageConfigDefaults } from 'vitest/config';
12
11
  import { fileURLToPath } from 'node:url';
13
12
  import crypto from 'node:crypto';
14
- import { mkdir, rm, readFile as readFile$1, writeFile as writeFile$1 } from 'node:fs/promises';
13
+ import { mkdir, rm, readFile as readFile$1, writeFile as writeFile$1, unlink } from 'node:fs/promises';
15
14
  import { parseErrorStacktrace, parseStacktrace } from '@vitest/utils/source-map';
16
15
  import { PlaywrightBrowserProvider } from './providers/playwright.js';
17
16
  import { WebdriverBrowserProvider } from './providers/webdriverio.js';
@@ -23,7 +22,7 @@ import pm from 'pixelmatch';
23
22
  import { WebSocketServer } from 'ws';
24
23
  import { performance } from 'node:perf_hooks';
25
24
 
26
- var version = "4.0.0-beta.10";
25
+ var version = "4.0.0-beta.12";
27
26
 
28
27
  const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
29
28
  function normalizeWindowsPath(input = "") {
@@ -773,10 +772,7 @@ var BrowserPlugin = (parentServer, base = "/") => {
773
772
  const include = [
774
773
  "vitest > expect-type",
775
774
  "vitest > @vitest/snapshot > magic-string",
776
- "vitest > @vitest/runner > strip-literal",
777
775
  "vitest > @vitest/expect > chai",
778
- "vitest > @vitest/expect > chai > loupe",
779
- "vitest > @vitest/utils > loupe",
780
776
  "@vitest/browser > @testing-library/user-event",
781
777
  "@vitest/browser > @testing-library/dom"
782
778
  ];
@@ -1029,7 +1025,7 @@ body {
1029
1025
  });
1030
1026
  }
1031
1027
  };
1032
- return { optimizeDeps: "rolldownVersion" in vite ? { rollupOptions: { plugins: [rolldownPlugin] } } : { esbuildOptions: { plugins: [esbuildPlugin] } } };
1028
+ return { optimizeDeps: rolldownVersion ? { rollupOptions: { plugins: [rolldownPlugin] } } : { esbuildOptions: { plugins: [esbuildPlugin] } } };
1033
1029
  }
1034
1030
  }
1035
1031
  ];
@@ -2909,6 +2905,101 @@ const tab = async (context, options = {}) => {
2909
2905
  throw new Error(`Provider "${provider.name}" doesn't support tab command`);
2910
2906
  };
2911
2907
 
2908
+ const startTracing = async ({ context, project, provider, sessionId }) => {
2909
+ if (provider instanceof PlaywrightBrowserProvider) {
2910
+ if (provider.tracingContexts.has(sessionId)) {
2911
+ return;
2912
+ }
2913
+ provider.tracingContexts.add(sessionId);
2914
+ const options = project.config.browser.trace;
2915
+ await context.tracing.start({
2916
+ screenshots: options.screenshots ?? true,
2917
+ snapshots: options.snapshots ?? true,
2918
+ sources: false
2919
+ }).catch(() => {
2920
+ provider.tracingContexts.delete(sessionId);
2921
+ });
2922
+ return;
2923
+ }
2924
+ throw new TypeError(`The ${provider.name} provider does not support tracing.`);
2925
+ };
2926
+ const startChunkTrace = async (command, { name, title }) => {
2927
+ const { provider, sessionId, testPath, context } = command;
2928
+ if (!testPath) {
2929
+ throw new Error(`stopChunkTrace cannot be called outside of the test file.`);
2930
+ }
2931
+ if (provider instanceof PlaywrightBrowserProvider) {
2932
+ if (!provider.tracingContexts.has(sessionId)) {
2933
+ await startTracing(command);
2934
+ }
2935
+ const path = resolveTracesPath(command, name);
2936
+ provider.pendingTraces.set(path, sessionId);
2937
+ await context.tracing.startChunk({
2938
+ name,
2939
+ title
2940
+ });
2941
+ return;
2942
+ }
2943
+ throw new TypeError(`The ${provider.name} provider does not support tracing.`);
2944
+ };
2945
+ const stopChunkTrace = async (context, { name }) => {
2946
+ if (context.provider instanceof PlaywrightBrowserProvider) {
2947
+ const path = resolveTracesPath(context, name);
2948
+ context.provider.pendingTraces.delete(path);
2949
+ await context.context.tracing.stopChunk({ path });
2950
+ return { tracePath: path };
2951
+ }
2952
+ throw new TypeError(`The ${context.provider.name} provider does not support tracing.`);
2953
+ };
2954
+ function resolveTracesPath({ testPath, project }, name) {
2955
+ if (!testPath) {
2956
+ throw new Error(`This command can only be called inside a test file.`);
2957
+ }
2958
+ const options = project.config.browser.trace;
2959
+ const sanitizedName = `${project.name.replace(/[^a-z0-9]/gi, "-")}-${name}.trace.zip`;
2960
+ if (options.tracesDir) {
2961
+ return resolve(options.tracesDir, sanitizedName);
2962
+ }
2963
+ const dir = dirname(testPath);
2964
+ const base = basename(testPath);
2965
+ return resolve(dir, "__traces__", base, `${project.name.replace(/[^a-z0-9]/gi, "-")}-${name}.trace.zip`);
2966
+ }
2967
+ const deleteTracing = async (context, { traces }) => {
2968
+ if (!context.testPath) {
2969
+ throw new Error(`stopChunkTrace cannot be called outside of the test file.`);
2970
+ }
2971
+ if (context.provider instanceof PlaywrightBrowserProvider) {
2972
+ return Promise.all(traces.map((trace) => unlink(trace).catch((err) => {
2973
+ if (err.code === "ENOENT") {
2974
+ // Ignore the error if the file doesn't exist
2975
+ return;
2976
+ }
2977
+ // Re-throw other errors
2978
+ throw err;
2979
+ })));
2980
+ }
2981
+ throw new Error(`provider ${context.provider.name} is not supported`);
2982
+ };
2983
+ const annotateTraces = async ({ project }, { testId, traces }) => {
2984
+ const vitest = project.vitest;
2985
+ await Promise.all(traces.map((trace) => {
2986
+ const entity = vitest.state.getReportedEntityById(testId);
2987
+ return vitest._testRun.annotate(testId, {
2988
+ message: relative(project.config.root, trace),
2989
+ type: "traces",
2990
+ attachment: {
2991
+ path: trace,
2992
+ contentType: "application/octet-stream"
2993
+ },
2994
+ location: entity?.location ? {
2995
+ file: entity.module.moduleId,
2996
+ line: entity.location.line,
2997
+ column: entity.location.column
2998
+ } : undefined
2999
+ });
3000
+ }));
3001
+ };
3002
+
2912
3003
  const type = async (context, selector, text, options = {}) => {
2913
3004
  const { skipClick = false, skipAutoClose = false } = options;
2914
3005
  const unreleased = new Set(Reflect.get(options, "unreleased") ?? []);
@@ -3001,7 +3092,12 @@ var builtinCommands = {
3001
3092
  __vitest_hover: hover,
3002
3093
  __vitest_cleanup: keyboardCleanup,
3003
3094
  __vitest_viewport: viewport,
3004
- __vitest_screenshotMatcher: screenshotMatcher
3095
+ __vitest_screenshotMatcher: screenshotMatcher,
3096
+ __vitest_deleteTracing: deleteTracing,
3097
+ __vitest_startChunkTrace: startChunkTrace,
3098
+ __vitest_startTracing: startTracing,
3099
+ __vitest_stopChunkTrace: stopChunkTrace,
3100
+ __vitest_annotateTraces: annotateTraces
3005
3101
  };
3006
3102
 
3007
3103
  class BrowserServerState {
@@ -3111,18 +3207,19 @@ class ParentBrowserProject {
3111
3207
  return result?.map;
3112
3208
  },
3113
3209
  getUrlId: (id) => {
3114
- const mod = this.vite.moduleGraph.getModuleById(id);
3210
+ const moduleGraph = this.vite.environments.client.moduleGraph;
3211
+ const mod = moduleGraph.getModuleById(id);
3115
3212
  if (mod) {
3116
3213
  return id;
3117
3214
  }
3118
3215
  const resolvedPath = resolve(this.vite.config.root, id.slice(1));
3119
- const modUrl = this.vite.moduleGraph.getModuleById(resolvedPath);
3216
+ const modUrl = moduleGraph.getModuleById(resolvedPath);
3120
3217
  if (modUrl) {
3121
3218
  return resolvedPath;
3122
3219
  }
3123
3220
  // some browsers (looking at you, safari) don't report queries in stack traces
3124
3221
  // the next best thing is to try the first id that this file resolves to
3125
- const files = this.vite.moduleGraph.getModulesByFile(resolvedPath);
3222
+ const files = moduleGraph.getModulesByFile(resolvedPath);
3126
3223
  if (files && files.size) {
3127
3224
  return files.values().next().value.id;
3128
3225
  }
@@ -1 +1 @@
1
- import"@vitest/browser/context";import"../public-utils-Kx5DUGWa.js";export{L as Locator,s as selectorEngine}from"../index-DDlvjJVO.js";import"vitest/internal/browser";
1
+ import"@vitest/browser/context";import"../public-utils-B6exS8fl.js";export{L as Locator,s as selectorEngine}from"../index-BPDFwkoW.js";import"vitest/internal/browser";
@@ -1 +1 @@
1
- import{page,server}from"@vitest/browser/context";import{g as getByTitleSelector,a as getByTextSelector,b as getByPlaceholderSelector,c as getByAltTextSelector,d as getByTestIdSelector,e as getByRoleSelector,f as getByLabelSelector}from"../public-utils-Kx5DUGWa.js";import{s as selectorEngine,L as Locator,p as processTimeoutOptions,g as getIframeScale}from"../index-DDlvjJVO.js";import"vitest/internal/browser";page.extend({getByLabelText(e,_){return new PlaywrightLocator(getByLabelSelector(e,_))},getByRole(e,_){return new PlaywrightLocator(getByRoleSelector(e,_))},getByTestId(e){return new PlaywrightLocator(getByTestIdSelector(server.config.browser.locators.testIdAttribute,e))},getByAltText(e,_){return new PlaywrightLocator(getByAltTextSelector(e,_))},getByPlaceholder(e,_){return new PlaywrightLocator(getByPlaceholderSelector(e,_))},getByText(e,_){return new PlaywrightLocator(getByTextSelector(e,_))},getByTitle(e,_){return new PlaywrightLocator(getByTitleSelector(e,_))},_createLocator(e){return new PlaywrightLocator(e)},elementLocator(e){return new PlaywrightLocator(selectorEngine.generateSelectorSimple(e),e)},frameLocator(e){return new PlaywrightLocator(`${e.selector} >> internal:control=enter-frame`)}});class PlaywrightLocator extends Locator{constructor(e,_){super(),this.selector=e,this._container=_}click(e){return super.click(processTimeoutOptions(processClickOptions(e)))}dblClick(e){return super.dblClick(processTimeoutOptions(processClickOptions(e)))}tripleClick(e){return super.tripleClick(processTimeoutOptions(processClickOptions(e)))}selectOptions(e,_){return super.selectOptions(e,processTimeoutOptions(_))}clear(e){return super.clear(processTimeoutOptions(e))}hover(e){return super.hover(processTimeoutOptions(processHoverOptions(e)))}upload(e,_){return super.upload(e,processTimeoutOptions(_))}fill(e,_){return super.fill(e,processTimeoutOptions(_))}dropTo(e,_){return super.dropTo(e,processTimeoutOptions(processDragAndDropOptions(_)))}locator(e){return new PlaywrightLocator(`${this.selector} >> ${e}`,this._container)}elementLocator(e){return new PlaywrightLocator(selectorEngine.generateSelectorSimple(e),e)}}function processDragAndDropOptions(e){if(!e)return e;let _=e;return _.sourcePosition&&=processPlaywrightPosition(_.sourcePosition),_.targetPosition&&=processPlaywrightPosition(_.targetPosition),e}function processHoverOptions(e){if(!e)return e;let _=e;return _.position&&=processPlaywrightPosition(_.position),e}function processClickOptions(e){if(!e)return e;let _=e;return _.position&&=processPlaywrightPosition(_.position),_}function processPlaywrightPosition(e){let _=getIframeScale();return e.x!=null&&(e.x*=_),e.y!=null&&(e.y*=_),e}
1
+ import{page,server}from"@vitest/browser/context";import{g as getByTitleSelector,a as getByTextSelector,b as getByPlaceholderSelector,c as getByAltTextSelector,d as getByTestIdSelector,e as getByRoleSelector,f as getByLabelSelector}from"../public-utils-B6exS8fl.js";import{s as selectorEngine,L as Locator,p as processTimeoutOptions,g as getIframeScale}from"../index-BPDFwkoW.js";import"vitest/internal/browser";page.extend({getByLabelText(e,_){return new PlaywrightLocator(getByLabelSelector(e,_))},getByRole(e,_){return new PlaywrightLocator(getByRoleSelector(e,_))},getByTestId(e){return new PlaywrightLocator(getByTestIdSelector(server.config.browser.locators.testIdAttribute,e))},getByAltText(e,_){return new PlaywrightLocator(getByAltTextSelector(e,_))},getByPlaceholder(e,_){return new PlaywrightLocator(getByPlaceholderSelector(e,_))},getByText(e,_){return new PlaywrightLocator(getByTextSelector(e,_))},getByTitle(e,_){return new PlaywrightLocator(getByTitleSelector(e,_))},_createLocator(e){return new PlaywrightLocator(e)},elementLocator(e){return new PlaywrightLocator(selectorEngine.generateSelectorSimple(e),e)},frameLocator(e){return new PlaywrightLocator(`${e.selector} >> internal:control=enter-frame`)}});class PlaywrightLocator extends Locator{constructor(e,_){super(),this.selector=e,this._container=_}click(e){return super.click(processTimeoutOptions(processClickOptions(e)))}dblClick(e){return super.dblClick(processTimeoutOptions(processClickOptions(e)))}tripleClick(e){return super.tripleClick(processTimeoutOptions(processClickOptions(e)))}selectOptions(e,_){return super.selectOptions(e,processTimeoutOptions(_))}clear(e){return super.clear(processTimeoutOptions(e))}hover(e){return super.hover(processTimeoutOptions(processHoverOptions(e)))}upload(e,_){return super.upload(e,processTimeoutOptions(_))}fill(e,_){return super.fill(e,processTimeoutOptions(_))}dropTo(e,_){return super.dropTo(e,processTimeoutOptions(processDragAndDropOptions(_)))}locator(e){return new PlaywrightLocator(`${this.selector} >> ${e}`,this._container)}elementLocator(e){return new PlaywrightLocator(selectorEngine.generateSelectorSimple(e),e)}}function processDragAndDropOptions(e){if(!e)return e;let _=e;return _.sourcePosition&&=processPlaywrightPosition(_.sourcePosition),_.targetPosition&&=processPlaywrightPosition(_.targetPosition),e}function processHoverOptions(e){if(!e)return e;let _=e;return _.position&&=processPlaywrightPosition(_.position),e}function processClickOptions(e){if(!e)return e;let _=e;return _.position&&=processPlaywrightPosition(_.position),_}function processPlaywrightPosition(e){let _=getIframeScale();return e.x!=null&&(e.x*=_),e.y!=null&&(e.y*=_),e}
@@ -1 +1 @@
1
- import{page,server,userEvent}from"@vitest/browser/context";import{g as getByTitleSelector,a as getByTextSelector,b as getByPlaceholderSelector,c as getByAltTextSelector,d as getByTestIdSelector,e as getByRoleSelector,f as getByLabelSelector,h as getElementError}from"../public-utils-Kx5DUGWa.js";import{s as selectorEngine,L as Locator,c as convertElementToCssSelector}from"../index-DDlvjJVO.js";import"vitest/internal/browser";page.extend({getByLabelText(e,m){return new PreviewLocator(getByLabelSelector(e,m))},getByRole(e,m){return new PreviewLocator(getByRoleSelector(e,m))},getByTestId(e){return new PreviewLocator(getByTestIdSelector(server.config.browser.locators.testIdAttribute,e))},getByAltText(e,m){return new PreviewLocator(getByAltTextSelector(e,m))},getByPlaceholder(e,m){return new PreviewLocator(getByPlaceholderSelector(e,m))},getByText(e,m){return new PreviewLocator(getByTextSelector(e,m))},getByTitle(e,m){return new PreviewLocator(getByTitleSelector(e,m))},_createLocator(e){return new PreviewLocator(e)},elementLocator(e){return new PreviewLocator(selectorEngine.generateSelectorSimple(e),e)}});class PreviewLocator extends Locator{constructor(e,m){super(),this._pwSelector=e,this._container=m}get selector(){let e=this.elements().map(e=>convertElementToCssSelector(e));if(!e.length)throw getElementError(this._pwSelector,this._container||document.body);return e.join(`, `)}click(){return userEvent.click(this.element())}dblClick(){return userEvent.dblClick(this.element())}tripleClick(){return userEvent.tripleClick(this.element())}hover(){return userEvent.hover(this.element())}unhover(){return userEvent.unhover(this.element())}async fill(e){return userEvent.fill(this.element(),e)}async upload(e){return userEvent.upload(this.element(),e)}selectOptions(e){return userEvent.selectOptions(this.element(),e)}clear(){return userEvent.clear(this.element())}locator(e){return new PreviewLocator(`${this._pwSelector} >> ${e}`,this._container)}elementLocator(e){return new PreviewLocator(selectorEngine.generateSelectorSimple(e),e)}}
1
+ import{page,server,userEvent}from"@vitest/browser/context";import{g as getByTitleSelector,a as getByTextSelector,b as getByPlaceholderSelector,c as getByAltTextSelector,d as getByTestIdSelector,e as getByRoleSelector,f as getByLabelSelector,h as getElementError}from"../public-utils-B6exS8fl.js";import{s as selectorEngine,L as Locator,c as convertElementToCssSelector}from"../index-BPDFwkoW.js";import"vitest/internal/browser";page.extend({getByLabelText(e,m){return new PreviewLocator(getByLabelSelector(e,m))},getByRole(e,m){return new PreviewLocator(getByRoleSelector(e,m))},getByTestId(e){return new PreviewLocator(getByTestIdSelector(server.config.browser.locators.testIdAttribute,e))},getByAltText(e,m){return new PreviewLocator(getByAltTextSelector(e,m))},getByPlaceholder(e,m){return new PreviewLocator(getByPlaceholderSelector(e,m))},getByText(e,m){return new PreviewLocator(getByTextSelector(e,m))},getByTitle(e,m){return new PreviewLocator(getByTitleSelector(e,m))},_createLocator(e){return new PreviewLocator(e)},elementLocator(e){return new PreviewLocator(selectorEngine.generateSelectorSimple(e),e)}});class PreviewLocator extends Locator{constructor(e,m){super(),this._pwSelector=e,this._container=m}get selector(){let e=this.elements().map(e=>convertElementToCssSelector(e));if(!e.length)throw getElementError(this._pwSelector,this._container||document.body);return e.join(`, `)}click(){return userEvent.click(this.element())}dblClick(){return userEvent.dblClick(this.element())}tripleClick(){return userEvent.tripleClick(this.element())}hover(){return userEvent.hover(this.element())}unhover(){return userEvent.unhover(this.element())}async fill(e){return userEvent.fill(this.element(),e)}async upload(e){return userEvent.upload(this.element(),e)}selectOptions(e){return userEvent.selectOptions(this.element(),e)}clear(){return userEvent.clear(this.element())}locator(e){return new PreviewLocator(`${this._pwSelector} >> ${e}`,this._container)}elementLocator(e){return new PreviewLocator(selectorEngine.generateSelectorSimple(e),e)}}
@@ -1 +1 @@
1
- import{page,server}from"@vitest/browser/context";import{g as getByTitleSelector,a as getByTextSelector,b as getByPlaceholderSelector,c as getByAltTextSelector,d as getByTestIdSelector,e as getByRoleSelector,f as getByLabelSelector,h as getElementError}from"../public-utils-Kx5DUGWa.js";import{s as selectorEngine,L as Locator,c as convertElementToCssSelector,a as getBrowserState,g as getIframeScale}from"../index-DDlvjJVO.js";import"vitest/internal/browser";page.extend({getByLabelText(e,g){return new WebdriverIOLocator(getByLabelSelector(e,g))},getByRole(e,g){return new WebdriverIOLocator(getByRoleSelector(e,g))},getByTestId(e){return new WebdriverIOLocator(getByTestIdSelector(server.config.browser.locators.testIdAttribute,e))},getByAltText(e,g){return new WebdriverIOLocator(getByAltTextSelector(e,g))},getByPlaceholder(e,g){return new WebdriverIOLocator(getByPlaceholderSelector(e,g))},getByText(e,g){return new WebdriverIOLocator(getByTextSelector(e,g))},getByTitle(e,g){return new WebdriverIOLocator(getByTitleSelector(e,g))},_createLocator(e){return new WebdriverIOLocator(e)},elementLocator(e){return new WebdriverIOLocator(selectorEngine.generateSelectorSimple(e))}});class WebdriverIOLocator extends Locator{constructor(e,g){super(),this._pwSelector=e,this._container=g}get selector(){let e=this.elements().map(e=>convertElementToCssSelector(e));if(!e.length)throw getElementError(this._pwSelector,this._container||document.body);let g=!1,_=e.map(e=>e.startsWith(`>>>`)?(g=!0,e.slice(3)):e);return(g?`>>>`:``)+_.join(`, `)}click(e){return super.click(processClickOptions(e))}dblClick(e){return super.dblClick(processClickOptions(e))}tripleClick(e){return super.tripleClick(processClickOptions(e))}selectOptions(e,g){let _=getWebdriverioSelectOptions(this.element(),e);return this.triggerCommand(`__vitest_selectOptions`,this.selector,_,g)}hover(e){return super.hover(processHoverOptions(e))}dropTo(e,g){return super.dropTo(e,processDragAndDropOptions(g))}locator(e){return new WebdriverIOLocator(`${this._pwSelector} >> ${e}`,this._container)}elementLocator(e){return new WebdriverIOLocator(selectorEngine.generateSelectorSimple(e),e)}}function getWebdriverioSelectOptions(e,g){let _=[...e.querySelectorAll(`option`)],v=Array.isArray(g)?g:[g];if(!v.length)return[];if(v.length>1)throw Error(`Provider "webdriverio" doesn't support selecting multiple values at once`);let y=v[0];if(typeof y!=`string`){let e=`element`in y?y.element():y,g=_.indexOf(e);if(g===-1)throw Error(`The element ${selectorEngine.previewNode(e)} was not found in the "select" options.`);return[{index:g}]}let b=_.findIndex(e=>e.value===y);if(b!==-1)return[{index:b}];let x=_.findIndex(e=>e.textContent?.trim()===y||e.ariaLabel===y);if(x===-1)throw Error(`The option "${y}" was not found in the "select" options.`);return[{index:x}]}function processClickOptions(e){if(!e||!getBrowserState().config.browser.ui)return e;let g=e;if(g.x!=null||g.y!=null){let e={};g.x!=null&&(g.x=scaleCoordinate(g.x,e)),g.y!=null&&(g.y=scaleCoordinate(g.y,e))}return e}function processHoverOptions(e){if(!e||!getBrowserState().config.browser.ui)return e;let g=e,_={};return g.xOffset!=null&&(g.xOffset=scaleCoordinate(g.xOffset,_)),g.yOffset!=null&&(g.yOffset=scaleCoordinate(g.yOffset,_)),e}function processDragAndDropOptions(e){if(!e||!getBrowserState().config.browser.ui)return e;let g={},_=e;return _.sourceX!=null&&(_.sourceX=scaleCoordinate(_.sourceX,g)),_.sourceY!=null&&(_.sourceY=scaleCoordinate(_.sourceY,g)),_.targetX!=null&&(_.targetX=scaleCoordinate(_.targetX,g)),_.targetY!=null&&(_.targetY=scaleCoordinate(_.targetY,g)),e}function scaleCoordinate(e,g){return Math.round(e*getCachedScale(g))}function getCachedScale(e){return e.scale??=getIframeScale()}
1
+ import{page,server}from"@vitest/browser/context";import{g as getByTitleSelector,a as getByTextSelector,b as getByPlaceholderSelector,c as getByAltTextSelector,d as getByTestIdSelector,e as getByRoleSelector,f as getByLabelSelector,h as getElementError}from"../public-utils-B6exS8fl.js";import{s as selectorEngine,L as Locator,c as convertElementToCssSelector,a as getBrowserState,g as getIframeScale}from"../index-BPDFwkoW.js";import"vitest/internal/browser";page.extend({getByLabelText(e,g){return new WebdriverIOLocator(getByLabelSelector(e,g))},getByRole(e,g){return new WebdriverIOLocator(getByRoleSelector(e,g))},getByTestId(e){return new WebdriverIOLocator(getByTestIdSelector(server.config.browser.locators.testIdAttribute,e))},getByAltText(e,g){return new WebdriverIOLocator(getByAltTextSelector(e,g))},getByPlaceholder(e,g){return new WebdriverIOLocator(getByPlaceholderSelector(e,g))},getByText(e,g){return new WebdriverIOLocator(getByTextSelector(e,g))},getByTitle(e,g){return new WebdriverIOLocator(getByTitleSelector(e,g))},_createLocator(e){return new WebdriverIOLocator(e)},elementLocator(e){return new WebdriverIOLocator(selectorEngine.generateSelectorSimple(e))}});class WebdriverIOLocator extends Locator{constructor(e,g){super(),this._pwSelector=e,this._container=g}get selector(){let e=this.elements().map(e=>convertElementToCssSelector(e));if(!e.length)throw getElementError(this._pwSelector,this._container||document.body);let g=!1,_=e.map(e=>e.startsWith(`>>>`)?(g=!0,e.slice(3)):e);return(g?`>>>`:``)+_.join(`, `)}click(e){return super.click(processClickOptions(e))}dblClick(e){return super.dblClick(processClickOptions(e))}tripleClick(e){return super.tripleClick(processClickOptions(e))}selectOptions(e,g){let _=getWebdriverioSelectOptions(this.element(),e);return this.triggerCommand(`__vitest_selectOptions`,this.selector,_,g)}hover(e){return super.hover(processHoverOptions(e))}dropTo(e,g){return super.dropTo(e,processDragAndDropOptions(g))}locator(e){return new WebdriverIOLocator(`${this._pwSelector} >> ${e}`,this._container)}elementLocator(e){return new WebdriverIOLocator(selectorEngine.generateSelectorSimple(e),e)}}function getWebdriverioSelectOptions(e,g){let _=[...e.querySelectorAll(`option`)],v=Array.isArray(g)?g:[g];if(!v.length)return[];if(v.length>1)throw Error(`Provider "webdriverio" doesn't support selecting multiple values at once`);let y=v[0];if(typeof y!=`string`){let e=`element`in y?y.element():y,g=_.indexOf(e);if(g===-1)throw Error(`The element ${selectorEngine.previewNode(e)} was not found in the "select" options.`);return[{index:g}]}let b=_.findIndex(e=>e.value===y);if(b!==-1)return[{index:b}];let x=_.findIndex(e=>e.textContent?.trim()===y||e.ariaLabel===y);if(x===-1)throw Error(`The option "${y}" was not found in the "select" options.`);return[{index:x}]}function processClickOptions(e){if(!e||!getBrowserState().config.browser.ui)return e;let g=e;if(g.x!=null||g.y!=null){let e={};g.x!=null&&(g.x=scaleCoordinate(g.x,e)),g.y!=null&&(g.y=scaleCoordinate(g.y,e))}return e}function processHoverOptions(e){if(!e||!getBrowserState().config.browser.ui)return e;let g=e,_={};return g.xOffset!=null&&(g.xOffset=scaleCoordinate(g.xOffset,_)),g.yOffset!=null&&(g.yOffset=scaleCoordinate(g.yOffset,_)),e}function processDragAndDropOptions(e){if(!e||!getBrowserState().config.browser.ui)return e;let g={},_=e;return _.sourceX!=null&&(_.sourceX=scaleCoordinate(_.sourceX,g)),_.sourceY!=null&&(_.sourceY=scaleCoordinate(_.sourceY,g)),_.targetX!=null&&(_.targetX=scaleCoordinate(_.targetX,g)),_.targetY!=null&&(_.targetY=scaleCoordinate(_.targetY,g)),e}function scaleCoordinate(e,g){return Math.round(e*getCachedScale(g))}function getCachedScale(e){return e.scale??=getIframeScale()}
@@ -10,7 +10,7 @@ interface PlaywrightProviderOptions {
10
10
  * The options passed down to [`playwright.connect`](https://playwright.dev/docs/api/class-browsertype#browser-type-launch) method.
11
11
  * @see {@link https://playwright.dev/docs/api/class-browsertype#browser-type-launch}
12
12
  */
13
- launchOptions?: LaunchOptions;
13
+ launchOptions?: Omit<LaunchOptions, "tracesDir">;
14
14
  /**
15
15
  * The options passed down to [`playwright.connect`](https://playwright.dev/docs/api/class-browsertype#browser-type-connect) method.
16
16
  *
@@ -44,6 +44,8 @@ declare class PlaywrightBrowserProvider implements BrowserProvider {
44
44
  browserName: PlaywrightBrowser;
45
45
  private browserPromise;
46
46
  private closing;
47
+ tracingContexts: Set<string>;
48
+ pendingTraces: Map<string, string>;
47
49
  constructor(project: TestProject, options: PlaywrightProviderOptions);
48
50
  private openBrowser;
49
51
  private createMocker;
@@ -28,11 +28,27 @@ class PlaywrightBrowserProvider {
28
28
  browserName;
29
29
  browserPromise = null;
30
30
  closing = false;
31
+ tracingContexts = new Set();
32
+ pendingTraces = new Map();
31
33
  constructor(project, options) {
32
34
  this.project = project;
33
35
  this.options = options;
34
36
  this.browserName = project.config.browser.name;
35
37
  this.mocker = this.createMocker();
38
+ // make sure the traces are finished if the test hangs
39
+ process.on("SIGTERM", () => {
40
+ if (!this.browser) {
41
+ return;
42
+ }
43
+ const promises = [];
44
+ for (const [trace, contextId] of this.pendingTraces.entries()) {
45
+ promises.push(() => {
46
+ const context = this.contexts.get(contextId);
47
+ return context?.tracing.stopChunk({ path: trace });
48
+ });
49
+ }
50
+ return Promise.allSettled(promises);
51
+ });
36
52
  }
37
53
  async openBrowser() {
38
54
  await this._throwIfClosing();
@@ -62,6 +78,9 @@ class PlaywrightBrowserProvider {
62
78
  ...this.options.launchOptions,
63
79
  headless: options.headless
64
80
  };
81
+ if (typeof options.trace === "object" && options.trace.tracesDir) {
82
+ launchOptions.tracesDir = options.trace?.tracesDir;
83
+ }
65
84
  if (this.project.config.inspector.enabled) {
66
85
  // NodeJS equivalent defaults: https://nodejs.org/en/learn/getting-started/debugging#enable-inspector
67
86
  const port = this.project.config.inspector.port || 9229;