@vitest/browser 4.0.0-beta.5 → 4.0.0-beta.6

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.
@@ -23,7 +23,7 @@
23
23
  })();
24
24
  </script>
25
25
  <!-- !LOAD_METADATA! -->
26
- <script type="module" src="./assets/index-Co-EY0lY.js"></script>
26
+ <script type="module" src="./assets/index-B3LybwKR.js"></script>
27
27
  <link rel="stylesheet" href="./assets/index-KbpJLW--.css">
28
28
  </head>
29
29
  <body>
@@ -425,20 +425,7 @@ function inspectSymbol(value) {
425
425
  }
426
426
  return value.toString();
427
427
  }
428
- let getPromiseValue = () => "Promise{…}";
429
- try {
430
- const { getPromiseDetails, kPending, kRejected } = process.binding("util");
431
- if (Array.isArray(getPromiseDetails(Promise.resolve()))) {
432
- getPromiseValue = (value, options) => {
433
- const [state, innerValue] = getPromiseDetails(value);
434
- if (state === kPending) {
435
- return "Promise{<pending>}";
436
- }
437
- return `Promise${state === kRejected ? "!" : ""}{${options.inspect(innerValue, options)}}`;
438
- };
439
- }
440
- } catch (notNode) {
441
- }
428
+ const getPromiseValue = () => "Promise{…}";
442
429
  function inspectObject$1(object, options) {
443
430
  const properties = Object.getOwnPropertyNames(object);
444
431
  const symbols = Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(object) : [];
@@ -1749,18 +1749,42 @@ function mockObject(options, object2, mockExports = {}) {
1749
1749
  return false;
1750
1750
  }
1751
1751
  };
1752
+ const createMock = (currentValue) => {
1753
+ if (!options.createMockInstance) {
1754
+ throw new Error("[@vitest/mocker] `createMockInstance` is not defined. This is a Vitest error. Please open a new issue with reproduction.");
1755
+ }
1756
+ const createMockInstance = options.createMockInstance;
1757
+ const prototypeMembers = currentValue.prototype ? collectFunctionProperties(currentValue.prototype) : [];
1758
+ return createMockInstance({
1759
+ name: currentValue.name,
1760
+ prototypeMembers,
1761
+ originalImplementation: options.type === "autospy" ? currentValue : void 0,
1762
+ keepMembersImplementation: options.type === "autospy"
1763
+ });
1764
+ };
1752
1765
  const mockPropertiesOf = (container, newContainer) => {
1753
1766
  const containerType = getType(container);
1754
1767
  const isModule = containerType === "Module" || !!container.__esModule;
1755
1768
  for (const { key: property, descriptor } of getAllMockableProperties(container, isModule, options.globalConstructors)) {
1756
1769
  if (!isModule && descriptor.get) {
1757
1770
  try {
1758
- Object.defineProperty(newContainer, property, descriptor);
1771
+ if (options.type === "autospy") {
1772
+ Object.defineProperty(newContainer, property, descriptor);
1773
+ } else {
1774
+ Object.defineProperty(newContainer, property, {
1775
+ configurable: descriptor.configurable,
1776
+ enumerable: descriptor.enumerable,
1777
+ get: () => {
1778
+ },
1779
+ set: descriptor.set ? () => {
1780
+ } : void 0
1781
+ });
1782
+ }
1759
1783
  } catch {
1760
1784
  }
1761
1785
  continue;
1762
1786
  }
1763
- if (isSpecialProp(property, containerType)) {
1787
+ if (isReadonlyProp(container[property], property)) {
1764
1788
  continue;
1765
1789
  }
1766
1790
  const value = container[property];
@@ -1771,7 +1795,22 @@ function mockObject(options, object2, mockExports = {}) {
1771
1795
  }
1772
1796
  const type = getType(value);
1773
1797
  if (Array.isArray(value)) {
1774
- define(newContainer, property, []);
1798
+ if (options.type === "automock") {
1799
+ define(newContainer, property, []);
1800
+ } else {
1801
+ const array = value.map((value2) => {
1802
+ if (value2 && typeof value2 === "object") {
1803
+ const newObject = {};
1804
+ mockPropertiesOf(value2, newObject);
1805
+ return newObject;
1806
+ }
1807
+ if (typeof value2 === "function") {
1808
+ return createMock(value2);
1809
+ }
1810
+ return value2;
1811
+ });
1812
+ define(newContainer, property, array);
1813
+ }
1775
1814
  continue;
1776
1815
  }
1777
1816
  const isFunction = type.includes("Function") && typeof value === "function";
@@ -1779,47 +1818,12 @@ function mockObject(options, object2, mockExports = {}) {
1779
1818
  define(newContainer, property, value);
1780
1819
  continue;
1781
1820
  }
1782
- if (!define(newContainer, property, isFunction ? value : {})) {
1821
+ if (!define(newContainer, property, isFunction || options.type === "autospy" ? value : {})) {
1783
1822
  continue;
1784
1823
  }
1785
1824
  if (isFunction) {
1786
- let mockFunction = function() {
1787
- if (this instanceof newContainer[property]) {
1788
- for (const { key, descriptor: descriptor2 } of getAllMockableProperties(this, false, options.globalConstructors)) {
1789
- if (descriptor2.get) {
1790
- continue;
1791
- }
1792
- const value2 = this[key];
1793
- const type2 = getType(value2);
1794
- const isFunction2 = type2.includes("Function") && typeof value2 === "function";
1795
- if (isFunction2) {
1796
- const original = this[key];
1797
- const mock2 = spyOn(this, key).mockImplementation(original);
1798
- const origMockReset = mock2.mockReset;
1799
- mock2.mockRestore = mock2.mockReset = () => {
1800
- origMockReset.call(mock2);
1801
- mock2.mockImplementation(original);
1802
- return mock2;
1803
- };
1804
- }
1805
- }
1806
- }
1807
- };
1808
- if (!options.spyOn) {
1809
- throw new Error("[@vitest/mocker] `spyOn` is not defined. This is a Vitest error. Please open a new issue with reproduction.");
1810
- }
1811
- const spyOn = options.spyOn;
1812
- const mock = spyOn(newContainer, property);
1813
- if (options.type === "automock") {
1814
- mock.mockImplementation(mockFunction);
1815
- const origMockReset = mock.mockReset;
1816
- mock.mockRestore = mock.mockReset = () => {
1817
- origMockReset.call(mock);
1818
- mock.mockImplementation(mockFunction);
1819
- return mock;
1820
- };
1821
- }
1822
- Object.defineProperty(newContainer[property], "length", { value: 0 });
1825
+ const mock = createMock(newContainer[property]);
1826
+ newContainer[property] = mock;
1823
1827
  }
1824
1828
  refs.track(value, newContainer[property]);
1825
1829
  mockPropertiesOf(value, newContainer[property]);
@@ -1853,14 +1857,15 @@ class RefTracker {
1853
1857
  function getType(value) {
1854
1858
  return Object.prototype.toString.apply(value).slice(8, -1);
1855
1859
  }
1856
- function isSpecialProp(prop, parentType) {
1857
- return parentType.includes("Function") && typeof prop === "string" && [
1858
- "arguments",
1859
- "callee",
1860
- "caller",
1861
- "length",
1862
- "name"
1863
- ].includes(prop);
1860
+ function isReadonlyProp(object2, prop) {
1861
+ if (prop === "arguments" || prop === "caller" || prop === "callee" || prop === "name" || prop === "length") {
1862
+ const typeName = getType(object2);
1863
+ return typeName === "Function" || typeName === "AsyncFunction" || typeName === "GeneratorFunction" || typeName === "AsyncGeneratorFunction";
1864
+ }
1865
+ if (prop === "source" || prop === "global" || prop === "ignoreCase" || prop === "multiline") {
1866
+ return getType(object2) === "RegExp";
1867
+ }
1868
+ return false;
1864
1869
  }
1865
1870
  function getAllMockableProperties(obj, isModule, constructors) {
1866
1871
  const { Map: Map2, Object: Object2, Function: Function2, RegExp: RegExp2, Array: Array2 } = constructors;
@@ -1896,6 +1901,20 @@ function collectOwnProperties(obj, collector) {
1896
1901
  Object.getOwnPropertyNames(obj).forEach(collect);
1897
1902
  Object.getOwnPropertySymbols(obj).forEach(collect);
1898
1903
  }
1904
+ function collectFunctionProperties(prototype) {
1905
+ const properties = /* @__PURE__ */ new Set();
1906
+ collectOwnProperties(prototype, (prop) => {
1907
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, prop);
1908
+ if (!descriptor || descriptor.get) {
1909
+ return;
1910
+ }
1911
+ const type = getType(descriptor.value);
1912
+ if (type.includes("Function") && !isReadonlyProp(descriptor.value, prop)) {
1913
+ properties.add(prop);
1914
+ }
1915
+ });
1916
+ return Array.from(properties);
1917
+ }
1899
1918
  const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
1900
1919
  function normalizeWindowsPath(input = "") {
1901
1920
  if (!input) {
@@ -2378,20 +2397,6 @@ const reactIsMethods = [
2378
2397
  "isValidElementType"
2379
2398
  ];
2380
2399
  Object.fromEntries(reactIsMethods.map((m) => [m, (v) => ReactIs18[m](v) || ReactIs19[m](v)]));
2381
- let getPromiseValue = () => "Promise{…}";
2382
- try {
2383
- const { getPromiseDetails, kPending, kRejected } = process.binding("util");
2384
- if (Array.isArray(getPromiseDetails(Promise.resolve()))) {
2385
- getPromiseValue = (value, options) => {
2386
- const [state, innerValue] = getPromiseDetails(value);
2387
- if (state === kPending) {
2388
- return "Promise{<pending>}";
2389
- }
2390
- return `Promise${state === kRejected ? "!" : ""}{${options.inspect(innerValue, options)}}`;
2391
- };
2392
- }
2393
- } catch (notNode) {
2394
- }
2395
2400
  var jsTokens_1;
2396
2401
  var hasRequiredJsTokens;
2397
2402
  function requireJsTokens() {
@@ -2856,13 +2861,13 @@ var UrlType;
2856
2861
  })(UrlType || (UrlType = {}));
2857
2862
  const { now } = Date;
2858
2863
  class ModuleMocker {
2859
- constructor(interceptor, rpc2, spyOn, config) {
2864
+ constructor(interceptor, rpc2, createMockInstance, config) {
2860
2865
  __publicField(this, "registry", new MockerRegistry());
2861
2866
  __publicField(this, "queue", /* @__PURE__ */ new Set());
2862
2867
  __publicField(this, "mockedIds", /* @__PURE__ */ new Set());
2863
2868
  this.interceptor = interceptor;
2864
2869
  this.rpc = rpc2;
2865
- this.spyOn = spyOn;
2870
+ this.createMockInstance = createMockInstance;
2866
2871
  this.config = config;
2867
2872
  }
2868
2873
  async prepare() {
@@ -2960,7 +2965,7 @@ class ModuleMocker {
2960
2965
  Map,
2961
2966
  RegExp
2962
2967
  },
2963
- spyOn: this.spyOn,
2968
+ createMockInstance: this.createMockInstance,
2964
2969
  type: moduleType
2965
2970
  }, object2);
2966
2971
  }
@@ -3161,7 +3166,7 @@ async function prepareTestEnvironment(options) {
3161
3166
  const mocker = new VitestBrowserClientMocker(
3162
3167
  interceptor,
3163
3168
  rpc2,
3164
- SpyModule.spyOn,
3169
+ SpyModule.createMockInstance,
3165
3170
  {
3166
3171
  root: getBrowserState().viteConfig.root
3167
3172
  }
@@ -26,7 +26,7 @@
26
26
  {__VITEST_INJECTOR__}
27
27
  {__VITEST_ERROR_CATCHER__}
28
28
  {__VITEST_SCRIPTS__}
29
- <script type="module" crossorigin src="/__vitest_browser__/orchestrator-CmUsRING.js"></script>
29
+ <script type="module" crossorigin src="/__vitest_browser__/orchestrator-C2rrmv36.js"></script>
30
30
  <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-FY_Qin7d.js">
31
31
  </head>
32
32
  <body>
@@ -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-1ooObZUu.js"></script>
8
+ <script type="module" crossorigin src="/__vitest_browser__/tester-DSNROWDQ.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-FY_Qin7d.js">
10
10
  </head>
11
11
  <body>
package/dist/context.js CHANGED
@@ -149,6 +149,18 @@ function processTimeoutOptions(options_) {
149
149
  options_.timeout = remainingTime - 100;
150
150
  return options_;
151
151
  }
152
+ function convertToSelector(elementOrLocator) {
153
+ if (!elementOrLocator) {
154
+ throw new Error("Expected element or locator to be defined.");
155
+ }
156
+ if (elementOrLocator instanceof Element) {
157
+ return convertElementToCssSelector(elementOrLocator);
158
+ }
159
+ if ("selector" in elementOrLocator) {
160
+ return elementOrLocator.selector;
161
+ }
162
+ throw new Error("Expected element or locator to be an instance of Element or Locator.");
163
+ }
152
164
 
153
165
  // this file should not import anything directly, only types and utils
154
166
  // @ts-expect-error not typed global
@@ -374,9 +386,13 @@ const page = {
374
386
  screenshotIds[repeatCount] ??= {};
375
387
  screenshotIds[repeatCount][taskName] = number + 1;
376
388
  const name = options.path || `${taskName.replace(/[^a-z0-9]/gi, "-")}-${number}.png`;
389
+ const normalizedOptions = "mask" in options ? {
390
+ ...options,
391
+ mask: options.mask.map(convertToSelector)
392
+ } : options;
377
393
  return ensureAwaited((error) => triggerCommand("__vitest_screenshot", [name, processTimeoutOptions(
378
394
  {
379
- ...options,
395
+ ...normalizedOptions,
380
396
  element: options.element ? convertToSelector(options.element) : undefined
381
397
  }
382
398
  /** TODO */
@@ -422,18 +438,6 @@ function convertToLocator(element) {
422
438
  }
423
439
  return element;
424
440
  }
425
- function convertToSelector(elementOrLocator) {
426
- if (!elementOrLocator) {
427
- throw new Error("Expected element or locator to be defined.");
428
- }
429
- if (elementOrLocator instanceof Element) {
430
- return convertElementToCssSelector(elementOrLocator);
431
- }
432
- if ("selector" in elementOrLocator) {
433
- return elementOrLocator.selector;
434
- }
435
- throw new Error("Expected element or locator to be an instance of Element or Locator.");
436
- }
437
441
  function getTaskFullName(task) {
438
442
  return task.suite ? `${getTaskFullName(task.suite)} ${task.name}` : task.name;
439
443
  }
@@ -1,4 +1,4 @@
1
- import{expect,chai}from"vitest";import{k as kAriaCheckedRoles,i as getAriaChecked,j as getAriaRole,l as getAriaDisabled,m as beginAriaCaches,n as endAriaCaches,o as isElementVisible$1,p as getElementAccessibleDescription,q as getElementAccessibleErrorMessage,r as getElementAccessibleName,s as cssEscape}from"./public-utils-Kx5DUGWa.js";import{L as Locator,b as getWorkerState,a as getBrowserState,c as convertElementToCssSelector,p as processTimeoutOptions}from"./index-D_g_FMM5.js";import{server}from"@vitest/browser/context";import"vitest/internal/browser";function getAriaCheckedRoles(){return[...kAriaCheckedRoles]}function getElementFromUserInput(_,K,q){if(_ instanceof Locator&&(_=_.element()),_ instanceof HTMLElement||_ instanceof SVGElement)return _;throw new UserInputElementTypeError(_,K,q)}function getNodeFromUserInput(_,K,q){if(_ instanceof Locator&&(_=_.element()),_ instanceof Node)return _;throw new UserInputNodeTypeError(_,K,q)}function getMessage(_,K,q,J,Y,X){return[`${K}\n`,`${q}:\n${_.utils.EXPECTED_COLOR(redent(display(_,J),2))}`,`${Y}:\n${_.utils.RECEIVED_COLOR(redent(display(_,X),2))}`].join(`
1
+ import{expect,chai}from"vitest";import{k as kAriaCheckedRoles,i as getAriaChecked,j as getAriaRole,l as getAriaDisabled,m as beginAriaCaches,n as endAriaCaches,o as isElementVisible$1,p as getElementAccessibleDescription,q as getElementAccessibleErrorMessage,r as getElementAccessibleName,s as cssEscape}from"./public-utils-Kx5DUGWa.js";import{L as Locator,b as getWorkerState,d as convertToSelector,a as getBrowserState,p as processTimeoutOptions}from"./index-B7Hfmz-h.js";import{server}from"@vitest/browser/context";import"vitest/internal/browser";function getAriaCheckedRoles(){return[...kAriaCheckedRoles]}function getElementFromUserInput(_,K,q){if(_ instanceof Locator&&(_=_.element()),_ instanceof HTMLElement||_ instanceof SVGElement)return _;throw new UserInputElementTypeError(_,K,q)}function getNodeFromUserInput(_,K,q){if(_ instanceof Locator&&(_=_.element()),_ instanceof Node)return _;throw new UserInputNodeTypeError(_,K,q)}function getMessage(_,K,q,J,Y,X){return[`${K}\n`,`${q}:\n${_.utils.EXPECTED_COLOR(redent(display(_,J),2))}`,`${Y}:\n${_.utils.RECEIVED_COLOR(redent(display(_,X),2))}`].join(`
2
2
  `)}function redent(_,K){return indentString(stripIndent(_),K)}function indentString(_,K){let q=/^(?!\s*$)/gm;return _.replace(q,` `.repeat(K))}function minIndent(_){let K=_.match(/^[ \t]*(?=\S)/gm);return K?K.reduce((_,K)=>Math.min(_,K.length),1/0):0}function stripIndent(_){let K=minIndent(_);if(K===0)return _;let q=RegExp(`^[ \\t]{${K}}`,`gm`);return _.replace(q,``)}function display(_,K){return typeof K==`string`?K:_.utils.stringify(K)}function toSentence(_,{wordConnector:K=`, `,lastWordConnector:q=` and `}={}){return[_.slice(0,-1).join(K),_[_.length-1]].join(_.length>1?q:``)}class GenericTypeError extends Error{constructor(_,K,q,J){super(),Error.captureStackTrace&&Error.captureStackTrace(this,q);let Y=``;try{Y=J.utils.printWithType(`Received`,K,J.utils.printReceived)}catch{}this.message=[J.utils.matcherHint(`${J.isNot?`.not`:``}.${q.name}`,`received`,``),``,`${J.utils.RECEIVED_COLOR(`received`)} value must ${_} or a Locator that returns ${_}.`,Y].join(`
3
3
  `)}}class UserInputElementTypeError extends GenericTypeError{constructor(_,K,q){super(`an HTMLElement or an SVGElement`,_,K,q)}}class UserInputNodeTypeError extends GenericTypeError{constructor(_,K,q){super(`a Node`,_,K,q)}}function getTag(_){return _ instanceof HTMLFormElement?`FORM`:_.tagName.toUpperCase()}function isInputElement(_){return getTag(_)===`INPUT`}function getSingleElementValue(_){if(_)switch(getTag(_)){case`INPUT`:return getInputValue(_);case`SELECT`:return getSelectValue(_);default:return _.value??getAccessibleValue(_)}}function getSelectValue({multiple:_,options:K}){let q=[...K].filter(_=>_.selected);if(_)return[...q].map(_=>_.value);if(q.length!==0)return q[0].value}function getInputValue(_){switch(_.type){case`number`:return _.value===``?null:Number(_.value);case`checkbox`:return _.checked;default:return _.value}}const rolesSupportingValues=[`meter`,`progressbar`,`slider`,`spinbutton`];function getAccessibleValue(_){if(rolesSupportingValues.includes(_.getAttribute(`role`)||``))return Number(_.getAttribute(`aria-valuenow`))}function normalize(_){return _.replace(/\s+/g,` `).trim()}function matches(_,K){return K instanceof RegExp?K.test(_):_.includes(String(K))}function arrayAsSetComparison(_,K){if(Array.isArray(_)&&Array.isArray(K)){let q=new Set(K);for(let K of new Set(_))if(!q.has(K))return!1;return!0}}const supportedRoles=getAriaCheckedRoles();function toBeChecked(_){let K=getElementFromUserInput(_,toBeChecked,this),q=()=>isInputElement(K)&&[`checkbox`,`radio`].includes(K.type),X=()=>supportedRoles.includes(getAriaRole(K)||``)&&[`true`,`false`].includes(K.getAttribute(`aria-checked`)||``);if(!q()&&!X())return{pass:!1,message:()=>`only inputs with type="checkbox" or type="radio" or elements with ${supportedRolesSentence()} and a valid aria-checked attribute can be used with .toBeChecked(). Use .toHaveValue() instead`};let Z=getAriaChecked(K),Q=Z===!0;return{pass:Q,message:()=>{let _=Q?`is`:`is not`;return[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeChecked`,`element`,``),``,`Received element ${_} checked:`,` ${this.utils.printReceived(K.cloneNode(!1))}`].join(`
4
4
  `)}}}function supportedRolesSentence(){return toSentence(supportedRoles.map(_=>`role="${_}"`),{lastWordConnector:` or `})}function toBeEmptyDOMElement(_){let K=getElementFromUserInput(_,toBeEmptyDOMElement,this);return{pass:isEmptyElement(K),message:()=>[this.utils.matcherHint(`${this.isNot?`.not`:``}.toBeEmptyDOMElement`,`element`,``),``,`Received:`,` ${this.utils.printReceived(K.innerHTML)}`].join(`
@@ -23,5 +23,5 @@ import{expect,chai}from"vitest";import{k as kAriaCheckedRoles,i as getAriaChecke
23
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(`
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,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=await getBrowserState().commands.triggerCommand(`__vitest_screenshotMatcher`,[Z,this.currentTestName,{element:convertElementToCssSelector(getElementFromUserInput(_,toMatchScreenshot,this)),...q}]);if(Q.pass===!1&&`context`in J){let{annotate:_}=J.context,K=[];Q.reference&&K.push(_(`Reference screenshot`,{path:Q.reference})),Q.actual&&K.push(_(`Actual screenshot`,{path:Q.actual})),Q.diff&&K.push(_(`Diff`,{path:Q.diff})),await Promise.all(K)}return{pass:Q.pass,message:()=>Q.pass?``:[this.utils.matcherHint(`toMatchScreenshot`,`element`,``),``,Q.message,Q.reference?`\nReference screenshot:\n ${this.utils.EXPECTED_COLOR(Q.reference)}`:null,Q.actual?`\nActual screenshot:\n ${this.utils.RECEIVED_COLOR(Q.actual)}`:null,Q.diff?this.utils.DIM_COLOR(`\nDiff image:\n ${Q.diff}`):null].filter(_=>_!==null).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
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};function element(q,J){if(q!=null&&!(q instanceof Element)&&!(`element`in q))throw Error(`Invalid element or locator: ${q}. Expected an instance of Element or Locator, received ${typeof q}`);return expect.poll(function(){if(q instanceof Element||q==null)return q;chai.util.flag(this,`_poll.element`,!0);let _=chai.util.flag(this,`negate`),J=chai.util.flag(this,`_name`),Y=chai.util.flag(this,`_isLastPollAttempt`);if(_&&J===`toBeInTheDocument`)return q.query();if(Y)return q.element();let X=q.query();if(!X)throw Error(`Cannot find element with locator: ${JSON.stringify(q)}`);return X},processTimeoutOptions(J))}expect.extend(matchers),Object.assign(expect,{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-Kx5DUGWa.js";function ensureAwaited(e){let x=getWorkerState().current;if(!x||x.type!==`test`)return e();let S=!1,C=Error(`STACK_TRACE_ERROR`);x.onFinished??=[],x.onFinished.push(()=>{if(!S){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=C.stack?.replace(C.message,e.message),e}});let w;return{then(x,T){return S=!0,(w||=e(C)).then(x,T)},catch(x){return(w||=e(C)).catch(x)},finally(x){return(w||=e(C)).finally(x)},[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 x=e.charCodeAt(0);return e===` `||e===`#`||e===`.`||e===`:`||e===`[`||e===`]`||e===`>`||e===`+`||e===`~`||e===`\\`?`\\${e}`:x>=65536?`\\${x.toString(16).toUpperCase().padStart(6,`0`)} `:x<32||x===127||x>=128?`\\${x.toString(16).toUpperCase().padStart(2,`0`)} `:e}).join(``)}function getUniqueCssSelector(e){let x=[],S,C=!1;for(;S=getParent(e);){S.shadowRoot&&(C=!0);let w=e.tagName;if(e.id)x.push(`#${escapeIdForCSSSelector(e.id)}`);else if(!e.nextElementSibling&&!e.previousElementSibling)x.push(w.toLowerCase());else{let C=0,T=0,E=0;for(let x of S.children)C++,x.tagName===w&&T++,x===e&&(E=C);T>1?x.push(`${w.toLowerCase()}:nth-child(${E})`):x.push(w.toLowerCase())}e=S}return`${getBrowserState().provider===`webdriverio`&&C?`>>>`:``}${x.reverse().join(` > `)}`}function getParent(e){let x=e.parentNode;return x instanceof ShadowRoot?x.host:x}const now=Date.now;function processTimeoutOptions(e){if(e&&e.timeout!=null||provider!==`playwright`||getWorkerState().config.browser.providerOptions.actionTimeout!=null)return e;let x=getBrowserState().runner,S=x._currentTaskStartTime;if(!S)return e;let C=x._currentTaskTimeout;if(C===0||C==null||C===1/0)return e;e||={};let w=now(),T=S+C,E=T-w;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 x=e.getAttribute(`data-scale`),S=Number(x);if(Number.isNaN(S))throw TypeError(`Cannot parse scale value from Tester element (${x}). This is a bug in Vitest. Please, open a new issue with reproduction.`);return S}function escapeRegexForSelector(e){return e.unicode||e.unicodeSets?String(e):String(e).replace(/(^|[^\\])(\\\\)*(["'`])/g,`$1$2\\$3`).replace(/>>/g,`\\>\\>`)}function escapeForTextSelector(e,x){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});class Locator{_parsedSelector;_container;_pwSelector;click(e={}){return this.triggerCommand(`__vitest_click`,this.selector,e)}dblClick(e={}){return this.triggerCommand(`__vitest_dblClick`,this.selector,e)}tripleClick(e={}){return this.triggerCommand(`__vitest_tripleClick`,this.selector,e)}clear(e){return this.triggerCommand(`__vitest_clear`,this.selector,e)}hover(e){return this.triggerCommand(`__vitest_hover`,this.selector,e)}unhover(e){return this.triggerCommand(`__vitest_hover`,`html > body`,e)}fill(e,x){return this.triggerCommand(`__vitest_fill`,this.selector,e,x)}async upload(e,x){let S=(Array.isArray(e)?e:[e]).map(async e=>{if(typeof e==`string`)return e;let x=await new Promise((x,S)=>{let C=new FileReader;C.onload=()=>x(C.result),C.onerror=()=>S(Error(`Failed to read file: ${e.name}`)),C.readAsDataURL(e)});return{name:e.name,mimeType:e.type,base64:x}});return this.triggerCommand(`__vitest_upload`,this.selector,await Promise.all(S),x)}dropTo(e,x={}){return this.triggerCommand(`__vitest_dragAndDrop`,this.selector,e.selector,x)}selectOptions(e,x){let S=(Array.isArray(e)?e:[e]).map(e=>{if(typeof e!=`string`){let x=`element`in e?e.selector:selectorEngine.generateSelectorSimple(e);return{element:x}}return e});return this.triggerCommand(`__vitest_selectOptions`,this.selector,S,x)}screenshot(e){return page.screenshot({...e,element:this})}getByRole(e,x){return this.locator(getByRoleSelector(e,x))}getByAltText(e,x){return this.locator(getByAltTextSelector(e,x))}getByLabelText(e,x){return this.locator(getByLabelSelector(e,x))}getByPlaceholder(e,x){return this.locator(getByPlaceholderSelector(e,x))}getByTestId(x){return this.locator(getByTestIdSelector(server.config.browser.locators.testIdAttribute,x))}getByText(e,x){return this.locator(getByTextSelector(e,x))}getByTitle(e,x){return this.locator(getByTitleSelector(e,x))}filter(e){let x=[];if(e?.hasText&&x.push(`internal:has-text=${escapeForTextSelector(e.hasText)}`),e?.hasNotText&&x.push(`internal:has-not-text=${escapeForTextSelector(e.hasNotText)}`),e?.has){let S=e.has;x.push(`internal:has=${JSON.stringify(S._pwSelector||S.selector)}`)}if(e?.hasNot){let S=e.hasNot;x.push(`internal:has-not=${JSON.stringify(S._pwSelector||S.selector)}`)}if(!x.length)throw Error(`Locator.filter expects at least one filter. None provided.`);return this.locator(x.join(` >> `))}and(e){return this.locator(`internal:and=${JSON.stringify(e._pwSelector||e.selector)}`)}or(e){return this.locator(`internal:or=${JSON.stringify(e._pwSelector||e.selector)}`)}query(){let e=this._parsedSelector||=selectorEngine.parseSelector(this._pwSelector||this.selector);return selectorEngine.querySelector(e,document.documentElement,!0)}element(){let e=this.query();if(!e)throw getElementError(this._pwSelector||this.selector,this._container||document.body);return e}elements(){let e=this._parsedSelector||=selectorEngine.parseSelector(this._pwSelector||this.selector);return selectorEngine.querySelectorAll(e,document.documentElement)}all(){return this.elements().map(e=>this.elementLocator(e))}nth(e){return this.locator(`nth=${e}`)}first(){return this.nth(0)}last(){return this.nth(-1)}toString(){return this.selector}toJSON(){return this.selector}triggerCommand(e,...x){let S=getBrowserState().commands;return ensureAwaited(C=>S.triggerCommand(e,x,C))}}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
@@ -22,7 +22,7 @@ import pm from 'pixelmatch';
22
22
  import { WebSocketServer } from 'ws';
23
23
  import { performance } from 'node:perf_hooks';
24
24
 
25
- var version = "4.0.0-beta.5";
25
+ var version = "4.0.0-beta.6";
26
26
 
27
27
  const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
28
28
  function normalizeWindowsPath(input = "") {
@@ -2403,11 +2403,13 @@ async function takeScreenshot(context, name, options) {
2403
2403
  const savePath = normalize$1(path);
2404
2404
  await mkdir(dirname(path), { recursive: true });
2405
2405
  if (context.provider instanceof PlaywrightBrowserProvider) {
2406
+ const mask = options.mask?.map((selector) => context.iframe.locator(selector));
2406
2407
  if (options.element) {
2407
2408
  const { element: selector,...config } = options;
2408
- const element = context.iframe.locator(`${selector}`);
2409
+ const element = context.iframe.locator(selector);
2409
2410
  const buffer = await element.screenshot({
2410
2411
  ...config,
2412
+ mask,
2411
2413
  path: options.save ? savePath : undefined
2412
2414
  });
2413
2415
  return {
@@ -2417,6 +2419,7 @@ async function takeScreenshot(context, name, options) {
2417
2419
  }
2418
2420
  const buffer = await context.iframe.locator("body").screenshot({
2419
2421
  ...options,
2422
+ mask,
2420
2423
  path: options.save ? savePath : undefined
2421
2424
  });
2422
2425
  return {
@@ -1 +1 @@
1
- import"@vitest/browser/context";import"../public-utils-Kx5DUGWa.js";export{L as Locator,s as selectorEngine}from"../index-D_g_FMM5.js";import"vitest/internal/browser";
1
+ import"@vitest/browser/context";import"../public-utils-Kx5DUGWa.js";export{L as Locator,s as selectorEngine}from"../index-B7Hfmz-h.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-D_g_FMM5.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)}});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-Kx5DUGWa.js";import{s as selectorEngine,L as Locator,p as processTimeoutOptions,g as getIframeScale}from"../index-B7Hfmz-h.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)}});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-D_g_FMM5.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-Kx5DUGWa.js";import{s as selectorEngine,L as Locator,c as convertElementToCssSelector}from"../index-B7Hfmz-h.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-D_g_FMM5.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-Kx5DUGWa.js";import{s as selectorEngine,L as Locator,c as convertElementToCssSelector,a as getBrowserState,g as getIframeScale}from"../index-B7Hfmz-h.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,6 +1,9 @@
1
1
  import type { ScreenshotComparatorRegistry, ScreenshotMatcherOptions } from "../../../context.js";
2
2
  export type ScreenshotMatcherArguments<ComparatorName extends keyof ScreenshotComparatorRegistry = keyof ScreenshotComparatorRegistry> = [name: string, testName: string, options: ScreenshotMatcherOptions<ComparatorName> & {
3
3
  element: string;
4
+ screenshotOptions?: ScreenshotMatcherOptions<ComparatorName>["screenshotOptions"] & {
5
+ mask?: readonly string[];
6
+ };
4
7
  }];
5
8
  export type ScreenshotMatcherOutput = Promise<{
6
9
  pass: false;
package/dist/types.d.ts CHANGED
@@ -39,7 +39,6 @@ export interface WebSocketBrowserHandlers {
39
39
  export type Awaitable<T> = T | PromiseLike<T>;
40
40
  export interface WebSocketEvents {
41
41
  onCollected?: (files: RunnerTestFile[]) => Awaitable<void>;
42
- onFinished?: (files: File[], errors: unknown[], coverage?: unknown) => Awaitable<void>;
43
42
  onTaskUpdate?: (packs: TaskResultPack[]) => Awaitable<void>;
44
43
  onUserConsoleLog?: (log: UserConsoleLog) => Awaitable<void>;
45
44
  onPathsCollected?: (paths?: string[]) => Awaitable<void>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/browser",
3
3
  "type": "module",
4
- "version": "4.0.0-beta.5",
4
+ "version": "4.0.0-beta.6",
5
5
  "description": "Browser running for Vitest",
6
6
  "license": "MIT",
7
7
  "funding": "https://opencollective.com/vitest",
@@ -66,7 +66,7 @@
66
66
  "peerDependencies": {
67
67
  "playwright": "*",
68
68
  "webdriverio": "^7.0.0 || ^8.0.0 || ^9.0.0",
69
- "vitest": "4.0.0-beta.5"
69
+ "vitest": "4.0.0-beta.6"
70
70
  },
71
71
  "peerDependenciesMeta": {
72
72
  "playwright": {
@@ -80,7 +80,7 @@
80
80
  }
81
81
  },
82
82
  "dependencies": {
83
- "@testing-library/dom": "^10.4.0",
83
+ "@testing-library/dom": "^10.4.1",
84
84
  "@testing-library/user-event": "^14.6.1",
85
85
  "magic-string": "^0.30.17",
86
86
  "pixelmatch": "7.1.0",
@@ -88,8 +88,8 @@
88
88
  "sirv": "^3.0.1",
89
89
  "tinyrainbow": "^2.0.0",
90
90
  "ws": "^8.18.3",
91
- "@vitest/mocker": "4.0.0-beta.5",
92
- "@vitest/utils": "4.0.0-beta.5"
91
+ "@vitest/mocker": "4.0.0-beta.6",
92
+ "@vitest/utils": "4.0.0-beta.6"
93
93
  },
94
94
  "devDependencies": {
95
95
  "@types/pngjs": "^6.0.5",
@@ -105,11 +105,11 @@
105
105
  "playwright": "^1.54.1",
106
106
  "playwright-core": "^1.54.1",
107
107
  "safaridriver": "^1.0.0",
108
- "webdriverio": "^9.18.1",
109
- "@vitest/runner": "4.0.0-beta.5",
110
- "@vitest/ui": "4.0.0-beta.5",
111
- "@vitest/ws-client": "4.0.0-beta.5",
112
- "vitest": "4.0.0-beta.5"
108
+ "webdriverio": "^9.18.4",
109
+ "@vitest/runner": "4.0.0-beta.6",
110
+ "@vitest/ui": "4.0.0-beta.6",
111
+ "@vitest/ws-client": "4.0.0-beta.6",
112
+ "vitest": "4.0.0-beta.6"
113
113
  },
114
114
  "scripts": {
115
115
  "typecheck": "tsc -p ./src/client/tsconfig.json --noEmit",
@@ -12,6 +12,7 @@ import { Protocol } from 'playwright-core/types/protocol'
12
12
  import '../matchers.js'
13
13
  import type {} from "vitest/node"
14
14
  import type {
15
+ Locator,
15
16
  ScreenshotComparatorRegistry,
16
17
  ScreenshotMatcherOptions,
17
18
  } from "@vitest/browser/context"
@@ -71,7 +72,9 @@ declare module '@vitest/browser/context' {
71
72
  export interface UserEventDragAndDropOptions extends PWDragAndDropOptions {}
72
73
  export interface UserEventUploadOptions extends PWSetInputFiles {}
73
74
 
74
- export interface ScreenshotOptions extends PWScreenshotOptions {}
75
+ export interface ScreenshotOptions extends Omit<PWScreenshotOptions, 'mask'> {
76
+ mask?: ReadonlyArray<Element | Locator> | undefined
77
+ }
75
78
 
76
79
  export interface CDPSession {
77
80
  send<T extends keyof Protocol.CommandParameters>(
@@ -1 +0,0 @@
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-Kx5DUGWa.js";function ensureAwaited(e){let b=getWorkerState().current;if(!b||b.type!==`test`)return e();let x=!1,S=Error(`STACK_TRACE_ERROR`);b.onFinished??=[],b.onFinished.push(()=>{if(!x){let e=Error(`The call was not awaited. This method is asynchronous and must be awaited; otherwise, the call will not start to avoid unhandled rejections.`);throw e.stack=S.stack?.replace(S.message,e.message),e}});let C;return{then(b,w){return x=!0,(C||=e(S)).then(b,w)},catch(b){return(C||=e(S)).catch(b)},finally(b){return(C||=e(S)).finally(b)},[Symbol.toStringTag]:`Promise`}}function getBrowserState(){return window.__vitest_browser_runner__}function getWorkerState(){let e=window.__vitest_worker__;if(!e)throw Error(`Worker state is not found. This is an issue with Vitest. Please, open an issue.`);return e}const provider=getBrowserState().provider;function convertElementToCssSelector(e){if(!e||!(e instanceof Element))throw Error(`Expected DOM element to be an instance of Element, received ${typeof e}`);return getUniqueCssSelector(e)}function escapeIdForCSSSelector(e){return e.split(``).map(e=>{let b=e.charCodeAt(0);return e===` `||e===`#`||e===`.`||e===`:`||e===`[`||e===`]`||e===`>`||e===`+`||e===`~`||e===`\\`?`\\${e}`:b>=65536?`\\${b.toString(16).toUpperCase().padStart(6,`0`)} `:b<32||b===127||b>=128?`\\${b.toString(16).toUpperCase().padStart(2,`0`)} `:e}).join(``)}function getUniqueCssSelector(e){let b=[],x,S=!1;for(;x=getParent(e);){x.shadowRoot&&(S=!0);let C=e.tagName;if(e.id)b.push(`#${escapeIdForCSSSelector(e.id)}`);else if(!e.nextElementSibling&&!e.previousElementSibling)b.push(C.toLowerCase());else{let S=0,w=0,T=0;for(let b of x.children)S++,b.tagName===C&&w++,b===e&&(T=S);w>1?b.push(`${C.toLowerCase()}:nth-child(${T})`):b.push(C.toLowerCase())}e=x}return`${getBrowserState().provider===`webdriverio`&&S?`>>>`:``}${b.reverse().join(` > `)}`}function getParent(e){let b=e.parentNode;return b instanceof ShadowRoot?b.host:b}const now=Date.now;function processTimeoutOptions(e){if(e&&e.timeout!=null||provider!==`playwright`||getWorkerState().config.browser.providerOptions.actionTimeout!=null)return e;let b=getBrowserState().runner,x=b._currentTaskStartTime;if(!x)return e;let S=b._currentTaskTimeout;if(S===0||S==null||S===1/0)return e;e||={};let C=now(),w=x+S,T=w-C;return T<=0||(e.timeout=T-100),e}function getIframeScale(){let e=window.parent.document.querySelector(`iframe[data-vitest]`)?.parentElement;if(!e)throw Error(`Cannot find Tester element. This is a bug in Vitest. Please, open a new issue with reproduction.`);let b=e.getAttribute(`data-scale`),x=Number(b);if(Number.isNaN(x))throw TypeError(`Cannot parse scale value from Tester element (${b}). This is a bug in Vitest. Please, open a new issue with reproduction.`);return x}function escapeRegexForSelector(e){return e.unicode||e.unicodeSets?String(e):String(e).replace(/(^|[^\\])(\\\\)*(["'`])/g,`$1$2\\$3`).replace(/>>/g,`\\>\\>`)}function escapeForTextSelector(e,b){return typeof e==`string`?`${JSON.stringify(e)}i`:escapeRegexForSelector(e)}const selectorEngine=Ivya.create({browser:(e=>{switch(e){case`edge`:case`chrome`:return`chromium`;case`safari`:return`webkit`;default:return e}})(server.config.browser.name),testIdAttribute:server.config.browser.locators.testIdAttribute});class Locator{_parsedSelector;_container;_pwSelector;click(e={}){return this.triggerCommand(`__vitest_click`,this.selector,e)}dblClick(e={}){return this.triggerCommand(`__vitest_dblClick`,this.selector,e)}tripleClick(e={}){return this.triggerCommand(`__vitest_tripleClick`,this.selector,e)}clear(e){return this.triggerCommand(`__vitest_clear`,this.selector,e)}hover(e){return this.triggerCommand(`__vitest_hover`,this.selector,e)}unhover(e){return this.triggerCommand(`__vitest_hover`,`html > body`,e)}fill(e,b){return this.triggerCommand(`__vitest_fill`,this.selector,e,b)}async upload(e,b){let x=(Array.isArray(e)?e:[e]).map(async e=>{if(typeof e==`string`)return e;let b=await new Promise((b,x)=>{let S=new FileReader;S.onload=()=>b(S.result),S.onerror=()=>x(Error(`Failed to read file: ${e.name}`)),S.readAsDataURL(e)});return{name:e.name,mimeType:e.type,base64:b}});return this.triggerCommand(`__vitest_upload`,this.selector,await Promise.all(x),b)}dropTo(e,b={}){return this.triggerCommand(`__vitest_dragAndDrop`,this.selector,e.selector,b)}selectOptions(e,b){let x=(Array.isArray(e)?e:[e]).map(e=>{if(typeof e!=`string`){let b=`element`in e?e.selector:selectorEngine.generateSelectorSimple(e);return{element:b}}return e});return this.triggerCommand(`__vitest_selectOptions`,this.selector,x,b)}screenshot(e){return page.screenshot({...e,element:this})}getByRole(e,b){return this.locator(getByRoleSelector(e,b))}getByAltText(e,b){return this.locator(getByAltTextSelector(e,b))}getByLabelText(e,b){return this.locator(getByLabelSelector(e,b))}getByPlaceholder(e,b){return this.locator(getByPlaceholderSelector(e,b))}getByTestId(b){return this.locator(getByTestIdSelector(server.config.browser.locators.testIdAttribute,b))}getByText(e,b){return this.locator(getByTextSelector(e,b))}getByTitle(e,b){return this.locator(getByTitleSelector(e,b))}filter(e){let b=[];if(e?.hasText&&b.push(`internal:has-text=${escapeForTextSelector(e.hasText)}`),e?.hasNotText&&b.push(`internal:has-not-text=${escapeForTextSelector(e.hasNotText)}`),e?.has){let x=e.has;b.push(`internal:has=${JSON.stringify(x._pwSelector||x.selector)}`)}if(e?.hasNot){let x=e.hasNot;b.push(`internal:has-not=${JSON.stringify(x._pwSelector||x.selector)}`)}if(!b.length)throw Error(`Locator.filter expects at least one filter. None provided.`);return this.locator(b.join(` >> `))}and(e){return this.locator(`internal:and=${JSON.stringify(e._pwSelector||e.selector)}`)}or(e){return this.locator(`internal:or=${JSON.stringify(e._pwSelector||e.selector)}`)}query(){let e=this._parsedSelector||=selectorEngine.parseSelector(this._pwSelector||this.selector);return selectorEngine.querySelector(e,document.documentElement,!0)}element(){let e=this.query();if(!e)throw getElementError(this._pwSelector||this.selector,this._container||document.body);return e}elements(){let e=this._parsedSelector||=selectorEngine.parseSelector(this._pwSelector||this.selector);return selectorEngine.querySelectorAll(e,document.documentElement)}all(){return this.elements().map(e=>this.elementLocator(e))}nth(e){return this.locator(`nth=${e}`)}first(){return this.nth(0)}last(){return this.nth(-1)}toString(){return this.selector}toJSON(){return this.selector}triggerCommand(e,...b){let x=getBrowserState().commands;return ensureAwaited(S=>x.triggerCommand(e,b,S))}}export{Locator as L,getBrowserState as a,getWorkerState as b,convertElementToCssSelector as c,getIframeScale as g,processTimeoutOptions as p,selectorEngine as s};