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

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.
Files changed (42) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +3 -15
  3. package/context.d.ts +153 -3
  4. package/dist/client/.vite/manifest.json +6 -6
  5. package/dist/client/__vitest__/assets/index-DFDJV2DF.js +53 -0
  6. package/dist/client/__vitest__/index.html +1 -1
  7. package/dist/client/__vitest_browser__/orchestrator-BXX6oamz.js +296 -0
  8. package/dist/client/__vitest_browser__/{tester-BScMoGFI.js → tester-CMhJ1E1W.js} +294 -570
  9. package/dist/client/__vitest_browser__/{utils-Owv5OOOf.js → utils-CPmDBIKG.js} +3 -3
  10. package/dist/client/error-catcher.js +7 -3
  11. package/dist/client/esm-client-injector.js +1 -0
  12. package/dist/client/orchestrator.html +2 -2
  13. package/dist/client/tester/tester.html +2 -2
  14. package/dist/client.js +24 -8
  15. package/dist/context.js +29 -22
  16. package/dist/expect-element.js +10 -8
  17. package/dist/index-CwoiDq7G.js +6 -0
  18. package/dist/index-DDlvjJVO.js +1 -0
  19. package/dist/index.d.ts +16 -10
  20. package/dist/index.js +550 -98
  21. package/dist/locators/index.d.ts +8 -7
  22. package/dist/locators/index.js +1 -1
  23. package/dist/locators/playwright.js +1 -1
  24. package/dist/locators/preview.js +1 -1
  25. package/dist/locators/webdriverio.js +1 -1
  26. package/dist/providers/playwright.d.ts +103 -0
  27. package/dist/{webdriver-KA1WiV0q.js → providers/playwright.js} +37 -180
  28. package/dist/providers/preview.d.ts +16 -0
  29. package/dist/{providers.js → providers/preview.js} +17 -21
  30. package/dist/providers/webdriverio.d.ts +50 -0
  31. package/dist/providers/webdriverio.js +171 -0
  32. package/dist/shared/screenshotMatcher/types.d.ts +16 -0
  33. package/dist/state.js +4 -2
  34. package/dist/types.d.ts +5 -7
  35. package/jest-dom.d.ts +95 -1
  36. package/package.json +20 -30
  37. package/utils.d.ts +1 -1
  38. package/dist/client/__vitest__/assets/index-BjtzXzAw.js +0 -58
  39. package/dist/client/__vitest_browser__/orchestrator-CQgVbcQq.js +0 -3213
  40. package/dist/index-W1MM53zC.js +0 -1
  41. package/providers/playwright.d.ts +0 -81
  42. package/providers/webdriverio.d.ts +0 -22
@@ -279,13 +279,13 @@ interface SelectorEngine {
279
279
  queryAll: (root: SelectorRoot, selector: string | any) => Element[];
280
280
  }
281
281
 
282
- // we prefer using playwright locators because they are more powerful and support Shadow DOM
283
282
  declare const selectorEngine: Ivya;
284
283
  declare abstract class Locator {
285
284
  abstract selector: string;
286
285
  private _parsedSelector;
287
286
  protected _container?: Element | undefined;
288
287
  protected _pwSelector?: string | undefined;
288
+ constructor();
289
289
  click(options?: UserEventClickOptions): Promise<void>;
290
290
  dblClick(options?: UserEventClickOptions): Promise<void>;
291
291
  tripleClick(options?: UserEventClickOptions): Promise<void>;
@@ -297,10 +297,10 @@ declare abstract class Locator {
297
297
  dropTo(target: Locator, options?: UserEventDragAndDropOptions): Promise<void>;
298
298
  selectOptions(value: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[], options?: UserEventSelectOptions): Promise<void>;
299
299
  screenshot(options: Omit<LocatorScreenshotOptions, "base64"> & {
300
- base64: true
300
+ base64: true;
301
301
  }): Promise<{
302
- path: string
303
- base64: string
302
+ path: string;
303
+ base64: string;
304
304
  }>;
305
305
  screenshot(options?: LocatorScreenshotOptions): Promise<string>;
306
306
  protected abstract locator(selector: string): Locator;
@@ -315,9 +315,10 @@ declare abstract class Locator {
315
315
  filter(filter: LocatorOptions): Locator;
316
316
  and(locator: Locator): Locator;
317
317
  or(locator: Locator): Locator;
318
- query(): Element | null;
319
- element(): Element;
320
- elements(): Element[];
318
+ query(): HTMLElement | SVGElement | null;
319
+ element(): HTMLElement | SVGElement;
320
+ elements(): (HTMLElement | SVGElement)[];
321
+ get length(): number;
321
322
  all(): Locator[];
322
323
  nth(index: number): Locator;
323
324
  first(): Locator;
@@ -1 +1 @@
1
- import"@vitest/browser/context";import"../public-utils-Kx5DUGWa.js";export{L as Locator,s as selectorEngine}from"../index-W1MM53zC.js";import"vitest/internal/browser";
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 +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-W1MM53zC.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-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 +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-W1MM53zC.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-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 +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-W1MM53zC.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);return e.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-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()}
@@ -0,0 +1,103 @@
1
+ import { ScreenshotMatcherOptions, ScreenshotComparatorRegistry } from '@vitest/browser/context';
2
+ import { Page, Frame, FrameLocator, BrowserContext, LaunchOptions, ConnectOptions, BrowserContextOptions, Browser } from 'playwright';
3
+ import { Protocol } from 'playwright-core/types/protocol';
4
+ import { BrowserProviderOption, BrowserProvider, BrowserModuleMocker, TestProject, CDPSession } from 'vitest/node';
5
+
6
+ declare const playwrightBrowsers: readonly ["firefox", "webkit", "chromium"];
7
+ type PlaywrightBrowser = (typeof playwrightBrowsers)[number];
8
+ interface PlaywrightProviderOptions {
9
+ /**
10
+ * The options passed down to [`playwright.connect`](https://playwright.dev/docs/api/class-browsertype#browser-type-launch) method.
11
+ * @see {@link https://playwright.dev/docs/api/class-browsertype#browser-type-launch}
12
+ */
13
+ launchOptions?: LaunchOptions;
14
+ /**
15
+ * The options passed down to [`playwright.connect`](https://playwright.dev/docs/api/class-browsertype#browser-type-connect) method.
16
+ *
17
+ * This is used only if you connect remotely to the playwright instance via a WebSocket connection.
18
+ * @see {@link https://playwright.dev/docs/api/class-browsertype#browser-type-connect}
19
+ */
20
+ connectOptions?: ConnectOptions & {
21
+ wsEndpoint: string;
22
+ };
23
+ /**
24
+ * The options passed down to [`browser.newContext`](https://playwright.dev/docs/api/class-browser#browser-new-context) method.
25
+ * @see {@link https://playwright.dev/docs/api/class-browser#browser-new-context}
26
+ */
27
+ contextOptions?: Omit<BrowserContextOptions, "ignoreHTTPSErrors" | "serviceWorkers">;
28
+ /**
29
+ * The maximum time in milliseconds to wait for `userEvent` action to complete.
30
+ * @default 0 (no timeout)
31
+ */
32
+ actionTimeout?: number;
33
+ }
34
+ declare function playwright(options?: PlaywrightProviderOptions): BrowserProviderOption;
35
+ declare class PlaywrightBrowserProvider implements BrowserProvider {
36
+ private project;
37
+ private options;
38
+ name: "playwright";
39
+ supportsParallelism: boolean;
40
+ browser: Browser | null;
41
+ contexts: Map<string, BrowserContext>;
42
+ pages: Map<string, Page>;
43
+ mocker: BrowserModuleMocker;
44
+ browserName: PlaywrightBrowser;
45
+ private browserPromise;
46
+ private closing;
47
+ constructor(project: TestProject, options: PlaywrightProviderOptions);
48
+ private openBrowser;
49
+ private createMocker;
50
+ private createContext;
51
+ getPage(sessionId: string): Page;
52
+ getCommandsContext(sessionId: string): {
53
+ page: Page;
54
+ context: BrowserContext;
55
+ frame: () => Promise<Frame>;
56
+ readonly iframe: FrameLocator;
57
+ };
58
+ private openBrowserPage;
59
+ openPage(sessionId: string, url: string, beforeNavigate?: () => Promise<void>): Promise<void>;
60
+ private _throwIfClosing;
61
+ getCDPSession(sessionid: string): Promise<CDPSession>;
62
+ close(): Promise<void>;
63
+ }
64
+ declare module "vitest/node" {
65
+ interface BrowserCommandContext {
66
+ page: Page;
67
+ frame(): Promise<Frame>;
68
+ iframe: FrameLocator;
69
+ context: BrowserContext;
70
+ }
71
+ interface ToMatchScreenshotOptions extends Omit<ScreenshotMatcherOptions, "comparatorName" | "comparatorOptions"> {}
72
+ interface ToMatchScreenshotComparators extends ScreenshotComparatorRegistry {}
73
+ }
74
+ type PWHoverOptions = NonNullable<Parameters<Page["hover"]>[1]>;
75
+ type PWClickOptions = NonNullable<Parameters<Page["click"]>[1]>;
76
+ type PWDoubleClickOptions = NonNullable<Parameters<Page["dblclick"]>[1]>;
77
+ type PWFillOptions = NonNullable<Parameters<Page["fill"]>[2]>;
78
+ type PWScreenshotOptions = NonNullable<Parameters<Page["screenshot"]>[0]>;
79
+ type PWSelectOptions = NonNullable<Parameters<Page["selectOption"]>[2]>;
80
+ type PWDragAndDropOptions = NonNullable<Parameters<Page["dragAndDrop"]>[2]>;
81
+ type PWSetInputFiles = NonNullable<Parameters<Page["setInputFiles"]>[2]>;
82
+ declare module "@vitest/browser/context" {
83
+ interface UserEventHoverOptions extends PWHoverOptions {}
84
+ interface UserEventClickOptions extends PWClickOptions {}
85
+ interface UserEventDoubleClickOptions extends PWDoubleClickOptions {}
86
+ interface UserEventTripleClickOptions extends PWClickOptions {}
87
+ interface UserEventFillOptions extends PWFillOptions {}
88
+ interface UserEventSelectOptions extends PWSelectOptions {}
89
+ interface UserEventDragAndDropOptions extends PWDragAndDropOptions {}
90
+ interface UserEventUploadOptions extends PWSetInputFiles {}
91
+ interface ScreenshotOptions extends Omit<PWScreenshotOptions, "mask"> {
92
+ mask?: ReadonlyArray<Element | Locator> | undefined;
93
+ }
94
+ interface CDPSession {
95
+ send<T extends keyof Protocol.CommandParameters>(method: T, params?: Protocol.CommandParameters[T]): Promise<Protocol.CommandReturnValues[T]>;
96
+ on<T extends keyof Protocol.Events>(event: T, listener: (payload: Protocol.Events[T]) => void): this;
97
+ once<T extends keyof Protocol.Events>(event: T, listener: (payload: Protocol.Events[T]) => void): this;
98
+ off<T extends keyof Protocol.Events>(event: T, listener: (payload: Protocol.Events[T]) => void): this;
99
+ }
100
+ }
101
+
102
+ export { PlaywrightBrowserProvider, playwright };
103
+ export type { PlaywrightProviderOptions };
@@ -2,60 +2,64 @@ import { createManualModuleSource } from '@vitest/mocker/node';
2
2
  import c from 'tinyrainbow';
3
3
  import { createDebugger, isCSSRequest } from 'vitest/node';
4
4
 
5
- const debug$1 = createDebugger("vitest:browser:playwright");
5
+ const debug = createDebugger("vitest:browser:playwright");
6
6
  const playwrightBrowsers = [
7
7
  "firefox",
8
8
  "webkit",
9
9
  "chromium"
10
10
  ];
11
+ function playwright(options = {}) {
12
+ return {
13
+ name: "playwright",
14
+ supportedBrowser: playwrightBrowsers,
15
+ factory(project) {
16
+ return new PlaywrightBrowserProvider(project, options);
17
+ },
18
+ _cli: true
19
+ };
20
+ }
11
21
  class PlaywrightBrowserProvider {
12
22
  name = "playwright";
13
23
  supportsParallelism = true;
14
24
  browser = null;
15
- browserName;
16
- project;
17
- options;
18
25
  contexts = new Map();
19
26
  pages = new Map();
20
- browserPromise = null;
21
27
  mocker;
28
+ browserName;
29
+ browserPromise = null;
22
30
  closing = false;
23
- getSupportedBrowsers() {
24
- return playwrightBrowsers;
25
- }
26
- initialize(project, { browser, options }) {
27
- this.closing = false;
31
+ constructor(project, options) {
28
32
  this.project = project;
29
- this.browserName = browser;
30
33
  this.options = options;
34
+ this.browserName = project.config.browser.name;
31
35
  this.mocker = this.createMocker();
32
36
  }
33
37
  async openBrowser() {
34
38
  await this._throwIfClosing();
35
39
  if (this.browserPromise) {
36
- debug$1?.("[%s] the browser is resolving, reusing the promise", this.browserName);
40
+ debug?.("[%s] the browser is resolving, reusing the promise", this.browserName);
37
41
  return this.browserPromise;
38
42
  }
39
43
  if (this.browser) {
40
- debug$1?.("[%s] the browser is resolved, reusing it", this.browserName);
44
+ debug?.("[%s] the browser is resolved, reusing it", this.browserName);
41
45
  return this.browser;
42
46
  }
43
47
  this.browserPromise = (async () => {
44
48
  const options = this.project.config.browser;
45
49
  const playwright = await import('playwright');
46
- if (this.options?.connect) {
47
- if (this.options.launch) {
50
+ if (this.options.connectOptions) {
51
+ if (this.options.launchOptions) {
48
52
  this.project.vitest.logger.warn(c.yellow(`Found both ${c.bold(c.italic(c.yellow("connect")))} and ${c.bold(c.italic(c.yellow("launch")))} options in browser instance configuration.
49
53
  Ignoring ${c.bold(c.italic(c.yellow("launch")))} options and using ${c.bold(c.italic(c.yellow("connect")))} mode.
50
54
  You probably want to remove one of the two options and keep only the one you want to use.`));
51
55
  }
52
- const browser = await playwright[this.browserName].connect(this.options.connect.wsEndpoint, this.options.connect.options);
56
+ const browser = await playwright[this.browserName].connect(this.options.connectOptions.wsEndpoint, this.options.connectOptions);
53
57
  this.browser = browser;
54
58
  this.browserPromise = null;
55
59
  return this.browser;
56
60
  }
57
61
  const launchOptions = {
58
- ...this.options?.launch,
62
+ ...this.options.launchOptions,
59
63
  headless: options.headless
60
64
  };
61
65
  if (this.project.config.inspector.enabled) {
@@ -76,7 +80,7 @@ class PlaywrightBrowserProvider {
76
80
  launchOptions.args.push("--start-maximized");
77
81
  }
78
82
  }
79
- debug$1?.("[%s] initializing the browser with launch options: %O", this.browserName, launchOptions);
83
+ debug?.("[%s] initializing the browser with launch options: %O", this.browserName, launchOptions);
80
84
  this.browser = await playwright[this.browserName].launch(launchOptions);
81
85
  this.browserPromise = null;
82
86
  return this.browser;
@@ -200,12 +204,13 @@ class PlaywrightBrowserProvider {
200
204
  async createContext(sessionId) {
201
205
  await this._throwIfClosing();
202
206
  if (this.contexts.has(sessionId)) {
203
- debug$1?.("[%s][%s] the context already exists, reusing it", sessionId, this.browserName);
207
+ debug?.("[%s][%s] the context already exists, reusing it", sessionId, this.browserName);
204
208
  return this.contexts.get(sessionId);
205
209
  }
206
210
  const browser = await this.openBrowser();
207
211
  await this._throwIfClosing(browser);
208
- const { actionTimeout,...contextOptions } = this.options?.context ?? {};
212
+ const actionTimeout = this.options.actionTimeout;
213
+ const contextOptions = this.options.contextOptions ?? {};
209
214
  const options = {
210
215
  ...contextOptions,
211
216
  ignoreHTTPSErrors: true
@@ -215,10 +220,10 @@ class PlaywrightBrowserProvider {
215
220
  }
216
221
  const context = await browser.newContext(options);
217
222
  await this._throwIfClosing(context);
218
- if (actionTimeout) {
223
+ if (actionTimeout != null) {
219
224
  context.setDefaultTimeout(actionTimeout);
220
225
  }
221
- debug$1?.("[%s][%s] the context is ready", sessionId, this.browserName);
226
+ debug?.("[%s][%s] the context is ready", sessionId, this.browserName);
222
227
  this.contexts.set(sessionId, context);
223
228
  return context;
224
229
  }
@@ -258,14 +263,14 @@ class PlaywrightBrowserProvider {
258
263
  async openBrowserPage(sessionId) {
259
264
  await this._throwIfClosing();
260
265
  if (this.pages.has(sessionId)) {
261
- debug$1?.("[%s][%s] the page already exists, closing the old one", sessionId, this.browserName);
266
+ debug?.("[%s][%s] the page already exists, closing the old one", sessionId, this.browserName);
262
267
  const page = this.pages.get(sessionId);
263
268
  await page.close();
264
269
  this.pages.delete(sessionId);
265
270
  }
266
271
  const context = await this.createContext(sessionId);
267
272
  const page = await context.newPage();
268
- debug$1?.("[%s][%s] the page is ready", sessionId, this.browserName);
273
+ debug?.("[%s][%s] the page is ready", sessionId, this.browserName);
269
274
  await this._throwIfClosing(page);
270
275
  this.pages.set(sessionId, page);
271
276
  if (process.env.VITEST_PW_DEBUG) {
@@ -276,16 +281,16 @@ class PlaywrightBrowserProvider {
276
281
  return page;
277
282
  }
278
283
  async openPage(sessionId, url, beforeNavigate) {
279
- debug$1?.("[%s][%s] creating the browser page for %s", sessionId, this.browserName, url);
284
+ debug?.("[%s][%s] creating the browser page for %s", sessionId, this.browserName, url);
280
285
  const browserPage = await this.openBrowserPage(sessionId);
281
286
  await beforeNavigate?.();
282
- debug$1?.("[%s][%s] browser page is created, opening %s", sessionId, this.browserName, url);
287
+ debug?.("[%s][%s] browser page is created, opening %s", sessionId, this.browserName, url);
283
288
  await browserPage.goto(url, { timeout: 0 });
284
289
  await this._throwIfClosing(browserPage);
285
290
  }
286
291
  async _throwIfClosing(disposable) {
287
292
  if (this.closing) {
288
- debug$1?.("[%s] provider was closed, cannot perform the action on %s", this.browserName, String(disposable));
293
+ debug?.("[%s] provider was closed, cannot perform the action on %s", this.browserName, String(disposable));
289
294
  await disposable?.close();
290
295
  this.pages.clear();
291
296
  this.contexts.clear();
@@ -314,20 +319,20 @@ class PlaywrightBrowserProvider {
314
319
  };
315
320
  }
316
321
  async close() {
317
- debug$1?.("[%s] closing provider", this.browserName);
322
+ debug?.("[%s] closing provider", this.browserName);
318
323
  this.closing = true;
319
- const browser = this.browser;
320
- this.browser = null;
321
324
  if (this.browserPromise) {
322
325
  await this.browserPromise;
323
326
  this.browserPromise = null;
324
327
  }
328
+ const browser = this.browser;
329
+ this.browser = null;
325
330
  await Promise.all([...this.pages.values()].map((p) => p.close()));
326
331
  this.pages.clear();
327
332
  await Promise.all([...this.contexts.values()].map((c) => c.close()));
328
333
  this.contexts.clear();
329
334
  await browser?.close();
330
- debug$1?.("[%s] provider is closed", this.browserName);
335
+ debug?.("[%s] provider is closed", this.browserName);
331
336
  }
332
337
  }
333
338
  function getHeaders(config) {
@@ -356,152 +361,4 @@ function isDirectCSSRequest(request) {
356
361
  return isCSSRequest(request) && directRequestRE.test(request);
357
362
  }
358
363
 
359
- const debug = createDebugger("vitest:browser:wdio");
360
- const webdriverBrowsers = [
361
- "firefox",
362
- "chrome",
363
- "edge",
364
- "safari"
365
- ];
366
- class WebdriverBrowserProvider {
367
- name = "webdriverio";
368
- supportsParallelism = false;
369
- browser = null;
370
- browserName;
371
- project;
372
- options;
373
- closing = false;
374
- iframeSwitched = false;
375
- topLevelContext;
376
- getSupportedBrowsers() {
377
- return webdriverBrowsers;
378
- }
379
- async initialize(ctx, { browser, options }) {
380
- this.closing = false;
381
- this.project = ctx;
382
- this.browserName = browser;
383
- this.options = options;
384
- }
385
- isIframeSwitched() {
386
- return this.iframeSwitched;
387
- }
388
- async switchToTestFrame() {
389
- const page = this.browser;
390
- // support wdio@9
391
- if (page.switchFrame) {
392
- await page.switchFrame(page.$("iframe[data-vitest]"));
393
- } else {
394
- const iframe = await page.findElement("css selector", "iframe[data-vitest]");
395
- await page.switchToFrame(iframe);
396
- }
397
- this.iframeSwitched = true;
398
- }
399
- async switchToMainFrame() {
400
- const page = this.browser;
401
- if (page.switchFrame) {
402
- await page.switchFrame(null);
403
- } else {
404
- await page.switchToParentFrame();
405
- }
406
- this.iframeSwitched = false;
407
- }
408
- async setViewport(options) {
409
- if (this.topLevelContext == null || !this.browser) {
410
- throw new Error(`The browser has no open pages.`);
411
- }
412
- await this.browser.send({
413
- method: "browsingContext.setViewport",
414
- params: {
415
- context: this.topLevelContext,
416
- devicePixelRatio: 1,
417
- viewport: options
418
- }
419
- });
420
- }
421
- getCommandsContext() {
422
- return { browser: this.browser };
423
- }
424
- async openBrowser() {
425
- await this._throwIfClosing("opening the browser");
426
- if (this.browser) {
427
- debug?.("[%s] the browser is already opened, reusing it", this.browserName);
428
- return this.browser;
429
- }
430
- const options = this.project.config.browser;
431
- if (this.browserName === "safari") {
432
- if (options.headless) {
433
- throw new Error("You've enabled headless mode for Safari but it doesn't currently support it.");
434
- }
435
- }
436
- const { remote } = await import('webdriverio');
437
- const remoteOptions = {
438
- ...this.options,
439
- logLevel: "error",
440
- capabilities: this.buildCapabilities()
441
- };
442
- debug?.("[%s] opening the browser with options: %O", this.browserName, remoteOptions);
443
- // TODO: close everything, if browser is closed from the outside
444
- this.browser = await remote(remoteOptions);
445
- await this._throwIfClosing();
446
- return this.browser;
447
- }
448
- buildCapabilities() {
449
- const capabilities = {
450
- ...this.options?.capabilities,
451
- browserName: this.browserName
452
- };
453
- const headlessMap = {
454
- chrome: ["goog:chromeOptions", ["headless", "disable-gpu"]],
455
- firefox: ["moz:firefoxOptions", ["-headless"]],
456
- edge: ["ms:edgeOptions", ["--headless"]]
457
- };
458
- const options = this.project.config.browser;
459
- const browser = this.browserName;
460
- if (browser !== "safari" && options.headless) {
461
- const [key, args] = headlessMap[browser];
462
- const currentValues = (this.options?.capabilities)?.[key] || {};
463
- const newArgs = [...currentValues.args || [], ...args];
464
- capabilities[key] = {
465
- ...currentValues,
466
- args: newArgs
467
- };
468
- }
469
- // start Vitest UI maximized only on supported browsers
470
- if (options.ui && (browser === "chrome" || browser === "edge")) {
471
- const key = browser === "chrome" ? "goog:chromeOptions" : "ms:edgeOptions";
472
- const args = capabilities[key]?.args || [];
473
- if (!args.includes("--start-maximized") && !args.includes("--start-fullscreen")) {
474
- args.push("--start-maximized");
475
- }
476
- capabilities[key] ??= {};
477
- capabilities[key].args = args;
478
- }
479
- return capabilities;
480
- }
481
- async openPage(sessionId, url) {
482
- await this._throwIfClosing("creating the browser");
483
- debug?.("[%s][%s] creating the browser page for %s", sessionId, this.browserName, url);
484
- const browserInstance = await this.openBrowser();
485
- debug?.("[%s][%s] browser page is created, opening %s", sessionId, this.browserName, url);
486
- await browserInstance.url(url);
487
- this.topLevelContext = await browserInstance.getWindowHandle();
488
- await this._throwIfClosing("opening the url");
489
- }
490
- async _throwIfClosing(action) {
491
- if (this.closing) {
492
- debug?.(`[%s] provider was closed, cannot perform the action${action ? ` ${action}` : ""}`, this.browserName);
493
- await (this.browser?.sessionId ? this.browser?.deleteSession?.() : null);
494
- throw new Error(`[vitest] The provider was closed.`);
495
- }
496
- }
497
- async close() {
498
- debug?.("[%s] closing provider", this.browserName);
499
- this.closing = true;
500
- await Promise.all([this.browser?.sessionId ? this.browser?.deleteSession?.() : null]);
501
- // TODO: right now process can only exit with timeout, if we use browser
502
- // needs investigating
503
- process.exit();
504
- }
505
- }
506
-
507
- export { PlaywrightBrowserProvider as P, WebdriverBrowserProvider as W };
364
+ export { PlaywrightBrowserProvider, playwright };
@@ -0,0 +1,16 @@
1
+ import { BrowserProviderOption, BrowserProvider, TestProject } from 'vitest/node';
2
+
3
+ declare function preview(): BrowserProviderOption;
4
+ declare class PreviewBrowserProvider implements BrowserProvider {
5
+ name: "preview";
6
+ supportsParallelism: boolean;
7
+ private project;
8
+ private open;
9
+ constructor(project: TestProject);
10
+ isOpen(): boolean;
11
+ getCommandsContext(): {};
12
+ openPage(_sessionId: string, url: string): Promise<void>;
13
+ close(): Promise<void>;
14
+ }
15
+
16
+ export { PreviewBrowserProvider, preview };
@@ -1,24 +1,18 @@
1
- import { W as WebdriverBrowserProvider, P as PlaywrightBrowserProvider } from './webdriver-KA1WiV0q.js';
2
- import '@vitest/mocker/node';
3
- import 'tinyrainbow';
4
- import 'vitest/node';
5
-
1
+ function preview() {
2
+ return {
3
+ name: "preview",
4
+ factory(project) {
5
+ return new PreviewBrowserProvider(project);
6
+ },
7
+ _cli: true
8
+ };
9
+ }
6
10
  class PreviewBrowserProvider {
7
11
  name = "preview";
8
12
  supportsParallelism = false;
9
13
  project;
10
14
  open = false;
11
- getSupportedBrowsers() {
12
- // `none` is not restricted to certain browsers.
13
- return [];
14
- }
15
- isOpen() {
16
- return this.open;
17
- }
18
- getCommandsContext() {
19
- return {};
20
- }
21
- async initialize(project) {
15
+ constructor(project) {
22
16
  this.project = project;
23
17
  this.open = false;
24
18
  if (project.config.browser.headless) {
@@ -26,6 +20,12 @@ class PreviewBrowserProvider {
26
20
  }
27
21
  project.vitest.logger.printBrowserBanner(project);
28
22
  }
23
+ isOpen() {
24
+ return this.open;
25
+ }
26
+ getCommandsContext() {
27
+ return {};
28
+ }
29
29
  async openPage(_sessionId, url) {
30
30
  this.open = true;
31
31
  if (!this.project.browser) {
@@ -40,8 +40,4 @@ class PreviewBrowserProvider {
40
40
  async close() {}
41
41
  }
42
42
 
43
- const webdriverio = WebdriverBrowserProvider;
44
- const playwright = PlaywrightBrowserProvider;
45
- const preview = PreviewBrowserProvider;
46
-
47
- export { playwright, preview, webdriverio };
43
+ export { PreviewBrowserProvider, preview };
@@ -0,0 +1,50 @@
1
+ import { ScreenshotMatcherOptions, ScreenshotComparatorRegistry } from '@vitest/browser/context';
2
+ import { BrowserProviderOption, BrowserProvider, TestProject } from 'vitest/node';
3
+ import { ClickOptions, DragAndDropOptions, remote } from 'webdriverio';
4
+
5
+ interface WebdriverProviderOptions extends Partial<Parameters<typeof remote>[0]> {}
6
+ declare function webdriverio(options?: WebdriverProviderOptions): BrowserProviderOption;
7
+ declare class WebdriverBrowserProvider implements BrowserProvider {
8
+ name: "webdriverio";
9
+ supportsParallelism: boolean;
10
+ browser: WebdriverIO.Browser | null;
11
+ private browserName;
12
+ private project;
13
+ private options?;
14
+ private closing;
15
+ private iframeSwitched;
16
+ private topLevelContext;
17
+ getSupportedBrowsers(): readonly string[];
18
+ constructor(project: TestProject, options: WebdriverProviderOptions);
19
+ isIframeSwitched(): boolean;
20
+ switchToTestFrame(): Promise<void>;
21
+ switchToMainFrame(): Promise<void>;
22
+ setViewport(options: {
23
+ width: number;
24
+ height: number;
25
+ }): Promise<void>;
26
+ getCommandsContext(): {
27
+ browser: WebdriverIO.Browser | null;
28
+ };
29
+ openBrowser(): Promise<WebdriverIO.Browser>;
30
+ private buildCapabilities;
31
+ openPage(sessionId: string, url: string): Promise<void>;
32
+ private _throwIfClosing;
33
+ close(): Promise<void>;
34
+ }
35
+ declare module "vitest/node" {
36
+ interface UserEventClickOptions extends ClickOptions {}
37
+ interface UserEventDragOptions extends DragAndDropOptions {
38
+ sourceX?: number;
39
+ sourceY?: number;
40
+ targetX?: number;
41
+ targetY?: number;
42
+ }
43
+ interface BrowserCommandContext {
44
+ browser: WebdriverIO.Browser;
45
+ }
46
+ interface ToMatchScreenshotOptions extends Omit<ScreenshotMatcherOptions, "comparatorName" | "comparatorOptions"> {}
47
+ interface ToMatchScreenshotComparators extends ScreenshotComparatorRegistry {}
48
+ }
49
+
50
+ export { WebdriverBrowserProvider, webdriverio };