UNPKG

webdriverio

Version:

Next-gen browser and mobile automation test framework for Node.js

1,059 lines • 45.3 kB
import type { EventEmitter } from 'node:events'; import type { remote, local, SessionFlags, AttachOptions as WebDriverAttachOptions, BidiHandler, EventMap } from 'webdriver'; import type { Capabilities, Options, ThenArg, CustomCommands } from '@wdio/types'; import type { ElementReference, ProtocolCommands, RectReturn } from '@wdio/protocols'; import type { Browser as PuppeteerBrowser } from 'puppeteer-core'; import type { Dialog as DialogImport } from './session/dialog.js'; import type * as BrowserCommands from './commands/browser.js'; import type * as ElementCommands from './commands/element.js'; import type { Button, ButtonNames } from './utils/actions/pointer.js'; import type WebDriverInterception from './utils/interception/index.js'; import type { Response as MockResponse } from './utils/interception/types.js'; /** * export mock primitives */ export * from './utils/interception/types.js'; /** * re-export action primitives */ export * from './utils/actions/index.js'; /** * re-export command types */ export { InitScript } from './commands/browser/addInitScript.js'; type $BrowserCommands = typeof BrowserCommands; type $ElementCommands = typeof ElementCommands; type ElementQueryCommands = '$' | 'custom$' | 'shadow$' | 'react$'; type ElementsQueryCommands = '$$' | 'custom$$' | 'shadow$$' | 'react$$'; type ChainablePrototype = { [K in ElementQueryCommands]: (...args: Parameters<$ElementCommands[K]>) => ChainablePromiseElement; } & { [K in ElementsQueryCommands]: (...args: Parameters<$ElementCommands[K]>) => ChainablePromiseArray; }; type AsyncElementProto = { [K in keyof Omit<$ElementCommands, keyof ChainablePrototype | 'getSize' | 'getLocation' | 'execute'>]: OmitThisParameter<$ElementCommands[K]>; } & ChainablePrototype & { getSize(prop: keyof RectReturn): Promise<number>; getSize(): Promise<ElementCommands.Size>; getLocation(prop: keyof ElementCommands.Location): Promise<number>; getLocation(): Promise<ElementCommands.Location>; execute<ReturnValue, InnerArguments extends unknown[]>(script: string | ((...innerArgs: TransformElement<[WebdriverIO.Element, ...InnerArguments]>) => ReturnValue | Promise<ReturnValue>), ...args: InnerArguments): Promise<TransformReturn<Awaited<ReturnValue>>>; }; interface ChainablePromiseBaseElement { /** * WebDriver element reference */ elementId: Promise<string>; /** * parent of the element if fetched via `$(parent).$(child)` */ parent: Promise<WebdriverIO.Element | WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser | WebdriverIO.BrowsingContext>; /** * selector used to fetch this element, can be * - undefined if element was created via `$({ 'element-6066-11e4-a52e-4f735466cecf': 'ELEMENT-1' })` * - a string if `findElement` was used and a reference was found * - or a function if element was found via e.g. `$(() => document.body)` */ selector: Promise<Selector>; /** * Error message in case element fetch was not successful */ error?: Promise<Error>; /** * index of the element if fetched with `$$` */ index?: Promise<number>; /** * get the `WebdriverIO.Element` reference */ getElement(): Promise<WebdriverIO.Element>; /** * The chain resolves to the element, so `await $(...)` is a `WebdriverIO.Element`. */ then<TResult1 = WebdriverIO.Element, TResult2 = never>(onfulfilled?: ((value: WebdriverIO.Element) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>; } export interface ChainablePromiseElement extends ChainablePromiseBaseElement, AsyncElementProto, Omit<WebdriverIO.Element, keyof ChainablePromiseBaseElement | keyof AsyncElementProto> { } /** * Asynchronous equivalents of the ES5 `Array` iteration methods, available on * the element list returned by `$$`. * * Every method comes in two flavors: the base method runs its callbacks * **concurrently**, while the `*Series` variant runs **one callback at a time**, * in order. Prefer a `*Series` variant when the callback interacts with the * browser and the order of those interactions matters. */ interface AsyncIterators<T> { /** * Executes the callback once for each element, running the callbacks concurrently. */ forEach: (callback: (currentValue: T, index: number, array: T[]) => unknown, thisArg?: unknown) => Promise<void>; /** * Same as `forEach`, but runs only one callback at a time. */ forEachSeries: (callback: (currentValue: T, index: number, array: T[]) => unknown, thisArg?: unknown) => Promise<void>; /** * Creates a new array with the result of the callback for each element, running * the callbacks concurrently. The result always has the same length as the * element list. */ map: <U>(callback: (currentValue: T, index: number, array: T[]) => U | Promise<U>, thisArg?: unknown) => Promise<U[]>; /** * Same as `map`, but runs only one callback at a time. */ mapSeries: <U>(callback: (currentValue: T, index: number, array: T[]) => U | Promise<U>, thisArg?: unknown) => Promise<U[]>; /** * Returns the first element that satisfies the callback, running the callbacks * concurrently, or `undefined` if none does. "First" means the first match to * resolve, which is not necessarily the earliest element in the list, and every * callback still runs even once a match is found. Use `findSeries` if either * matters. */ find: (callback: (currentValue: T, index: number, array: T[]) => boolean | Promise<boolean>, thisArg?: unknown) => Promise<T>; /** * Same as `find`, but runs only one callback at a time, so the first match in * list order is returned. */ findSeries: (callback: (currentValue: T, index: number, array: T[]) => boolean | Promise<boolean>, thisArg?: unknown) => Promise<T>; /** * Returns the index of the first element that satisfies the callback, running * the callbacks concurrently, or `-1` if none does. "First" means the first * match to resolve, which is not necessarily the earliest element in the list, * and every callback still runs even once a match is found. Use * `findIndexSeries` if either matters. */ findIndex: (callback: (currentValue: T, index: number, array: T[]) => boolean | Promise<boolean>, thisArg?: unknown) => Promise<number>; /** * Same as `findIndex`, but runs only one callback at a time. */ findIndexSeries: (callback: (currentValue: T, index: number, array: T[]) => boolean | Promise<boolean>, thisArg?: unknown) => Promise<number>; /** * Resolves to `true` if at least one element satisfies the callback, running * the callbacks concurrently. */ some: (callback: (currentValue: T, index: number, array: T[]) => boolean | Promise<boolean>, thisArg?: unknown) => Promise<boolean>; /** * Same as `some`, but runs only one callback at a time. */ someSeries: (callback: (currentValue: T, index: number, array: T[]) => boolean | Promise<boolean>, thisArg?: unknown) => Promise<boolean>; /** * Resolves to `true` if every element satisfies the callback, running the * callbacks concurrently. */ every: (callback: (currentValue: T, index: number, array: T[]) => boolean | Promise<boolean>, thisArg?: unknown) => Promise<boolean>; /** * Same as `every`, but runs only one callback at a time. */ everySeries: (callback: (currentValue: T, index: number, array: T[]) => boolean | Promise<boolean>, thisArg?: unknown) => Promise<boolean>; /** * Creates a new array with the elements that satisfy the callback, running the * callbacks concurrently. */ filter: (callback: (currentValue: T, index: number, array: T[]) => boolean | Promise<boolean>, thisArg?: unknown) => Promise<T[]>; /** * Same as `filter`, but runs only one callback at a time. */ filterSeries: (callback: (currentValue: T, index: number, array: T[]) => boolean | Promise<boolean>, thisArg?: unknown) => Promise<T[]>; /** * Reduces the element list to a single value, awaiting the accumulator between * elements. Always runs one callback at a time, since each call depends on the * previous result. */ reduce: <U>(callback: (accumulator: U, currentValue: T, currentIndex: number, array: T[]) => U | Promise<U>, initialValue?: U) => Promise<U>; /** * Returns an async iterator over `[index, element]` pairs. */ entries(): AsyncIterableIterator<[number, T]>; } export interface ChainablePromiseArray extends AsyncIterators<WebdriverIO.Element> { /** * Awaiting the list yields the resolved `ElementArray`. Until then, `length` * is a promise and each index is a chainable element. */ then<TResult1 = WebdriverIO.ElementArray, TResult2 = never>(onfulfilled?: ((value: WebdriverIO.ElementArray) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>; catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | undefined | null): Promise<WebdriverIO.ElementArray | TResult>; finally(onfinally?: (() => void) | undefined | null): Promise<WebdriverIO.ElementArray>; [Symbol.asyncIterator](): AsyncIterableIterator<WebdriverIO.Element>; [Symbol.iterator](): IterableIterator<WebdriverIO.Element>; /** * Amount of elements fetched. This is a promise until the query resolves, * so compare it only after awaiting the list or the property itself. */ length: Promise<number>; /** * Selector used to fetch this list. It is available immediately, before the * query resolves. It can be * - undefined if the list was created via `$$([])`, raw element references, or elements that do not share one selector * - a string if `findElements` was used and a reference was found * - or a function if the elements were found via e.g. `$$(() => document.body)` */ selector: Selector | undefined; /** * Parent of the list if fetched via `$(parent).$$(child)`. Available * immediately, before the query resolves. */ parent: WebdriverIO.Element | WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser | WebdriverIO.BrowsingContext; /** * Command name with which this list was found, e.g. `$$`, `react$$`, `custom$$`, `shadow$$`. * Available immediately, before the query resolves. */ foundWith: string; /** * Extra arguments of the query that fetched this list. Available immediately. */ props: any[]; /** * allow to access a specific index of the element set */ [n: number]: ChainablePromiseElement; /** * get the `WebdriverIO.Element[]` list */ getElements(): Promise<WebdriverIO.ElementArray>; /** * Returns an async iterator of key/value pairs for every index in the array. */ entries(): AsyncIterableIterator<[number, WebdriverIO.Element]>; } export type BrowserCommandsType = Omit<$BrowserCommands, keyof ChainablePrototype> & ChainablePrototype; export type ElementCommandsType = Omit<$ElementCommands, keyof ChainablePrototype> & ChainablePrototype; /** * Multi-remote command definition */ type SingleElementCommandNames = '$' | 'custom$' | 'react$'; type MultiElementCommandNames = '$$' | 'custom$$' | 'react$$'; type ElementCommandNames = SingleElementCommandNames | MultiElementCommandNames; /** * `mock` is wrapped into a `MultiRemoteMock` instead of an array of results. */ type MultiRemoteArrayCommandNames = ElementCommandNames | 'SESSION_MOCKS' | 'CDP_SESSIONS' | 'mock'; /** * `shadow$`, `shadow$$` and the sibling and parent queries exist only on an element */ type ElementScopeSingleElementCommandNames = SingleElementCommandNames | 'shadow$' | 'nextElement' | 'previousElement' | 'parentElement'; type ElementScopeMultiElementCommandNames = MultiElementCommandNames | 'shadow$$'; type MultiRemoteBrowserQueries = { [K in keyof Pick<BrowserCommandsType, SingleElementCommandNames>]: (...args: Parameters<BrowserCommandsType[K]>) => ThenArg<WebdriverIO.MultiRemoteElement>; } & { [K in keyof Pick<BrowserCommandsType, MultiElementCommandNames>]: (...args: Parameters<BrowserCommandsType[K]>) => ThenArg<WebdriverIO.MultiRemoteElementArray>; }; type MultiRemoteElementQueries = { [K in keyof Pick<ElementCommandsType, ElementScopeSingleElementCommandNames>]: (...args: Parameters<ElementCommandsType[K]>) => ThenArg<WebdriverIO.MultiRemoteElement>; } & { [K in keyof Pick<ElementCommandsType, ElementScopeMultiElementCommandNames>]: (...args: Parameters<ElementCommandsType[K]>) => ThenArg<WebdriverIO.MultiRemoteElementArray>; }; export type MultiRemoteBrowserCommandsType = { [K in keyof Omit<BrowserCommandsType, MultiRemoteArrayCommandNames>]: (...args: Parameters<BrowserCommandsType[K]>) => Promise<ThenArg<ReturnType<BrowserCommandsType[K]>>[]>; } & MultiRemoteBrowserQueries & { mock(...args: Parameters<BrowserCommandsType['mock']>): Promise<WebdriverIO.MultiRemoteMock>; }; export type MultiRemoteElementCommandsType = { [K in keyof Omit<ElementCommandsType, ElementScopeSingleElementCommandNames | ElementScopeMultiElementCommandNames>]: (...args: Parameters<ElementCommandsType[K]>) => Promise<ThenArg<ReturnType<ElementCommandsType[K]>>[]>; } & MultiRemoteElementQueries; export type MultiRemoteProtocolCommandsType = { [K in keyof ProtocolCommands]: (...args: Parameters<ProtocolCommands[K]>) => Promise<ThenArg<ReturnType<ProtocolCommands[K]>>[]>; }; interface ElementArrayExport extends Omit<Array<WebdriverIO.Element>, keyof AsyncIterators<WebdriverIO.Element>>, AsyncIterators<WebdriverIO.Element> { /** * selector used to fetch this list, can be * - undefined if the list was created via `$$([])`, raw element references, or elements that do not share one selector * - a string if `findElements` was used and a reference was found * - or a function if the elements were found via e.g. `$$(() => document.body)` */ selector: Selector | undefined; /** * parent of the element if fetched via `$(parent).$(child)` */ parent: WebdriverIO.Element | WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser | WebdriverIO.BrowsingContext; /** * command name with which this element was found, e.g. `$$`, `react$$`, `custom$$`, `shadow$$` */ foundWith: string; /** * properties of the fetched elements */ props: any[]; /** * Amount of element fetched. */ length: number; /** * get the `WebdriverIO.Element[]` list */ getElements(): Promise<WebdriverIO.ElementArray>; /** * Async iterator so `for await (const el of $$('...'))` yields each element * whether or not the list has been awaited yet. */ [Symbol.asyncIterator](): AsyncIterableIterator<WebdriverIO.Element>; } export type ElementArray = ElementArrayExport; /** * The array `$$` returns on a multi-remote browser. It carries the same * information as `ElementArray` — every entry is a `MultiRemoteElement` rather * than an `Element`, and `isMultiRemote` tells the two apart at runtime. */ interface MultiRemoteElementArrayExport extends Omit<Array<WebdriverIO.MultiRemoteElement>, keyof AsyncIterators<WebdriverIO.MultiRemoteElement>>, AsyncIterators<WebdriverIO.MultiRemoteElement> { /** * selector used to fetch this element array. Undefined when the entries do not share one selector. */ selector: Selector | undefined; /** * parent of the element array, i.e. the multi-remote browser or element it was fetched from */ parent: WebdriverIO.MultiRemoteBrowser | WebdriverIO.MultiRemoteElement; /** * command name with which these elements were found, e.g. `$$`, `react$$`, `custom$$` */ foundWith: string; /** * properties of the fetched elements */ props: any[]; /** * Amount of elements fetched. */ length: number; /** * always `true`, so a multi-remote element array can be told apart from a plain one */ isMultiRemote: true; /** * get the `WebdriverIO.MultiRemoteElement[]` list */ getElements(): Promise<WebdriverIO.MultiRemoteElementArray>; /** * Async iterator over the multi-remote elements in this list. */ [Symbol.asyncIterator](): AsyncIterableIterator<WebdriverIO.MultiRemoteElement>; } export type MultiRemoteElementArray = MultiRemoteElementArrayExport; /** * What `browser.mock()` returns on a multi-remote browser. Methods such as * `respond` and `restore` run on every instance. Captured requests stay on * the mock for one browser: `mock.getInstance(name).calls`. Request ids are * not shared across sessions, so `getBinaryResponse` stays on that mock too. */ interface MultiRemoteMockBase { /** * Instance names, in the order the mocks were created. A `select()` that * reorders browsers is reflected here, so this can differ from * `browser.instances`. */ instances: string[]; /** * Always `true`, so a multi-remote mock can be told apart from a single `Mock`. */ isMultiRemote: true; /** * The mock registered on one instance. * Throws `Multi-remote object has no instance named "<name>"` when `name` is not one of `instances`. */ getInstance(name: string): WebdriverIO.Mock; abort(...args: Parameters<WebdriverIO.Mock['abort']>): this; abortOnce(...args: Parameters<WebdriverIO.Mock['abortOnce']>): this; clear(...args: Parameters<WebdriverIO.Mock['clear']>): this; reset(...args: Parameters<WebdriverIO.Mock['reset']>): this; redirect(...args: Parameters<WebdriverIO.Mock['redirect']>): this; redirectOnce(...args: Parameters<WebdriverIO.Mock['redirectOnce']>): this; request(...args: Parameters<WebdriverIO.Mock['request']>): this; requestOnce(...args: Parameters<WebdriverIO.Mock['requestOnce']>): this; respond(...args: Parameters<WebdriverIO.Mock['respond']>): this; respondOnce(...args: Parameters<WebdriverIO.Mock['respondOnce']>): this; /** * Register the same listener on every instance's mock. */ on(event: 'request', callback: (request: local.NetworkBeforeRequestSentParameters) => void): this; on(event: 'match', callback: (match: local.NetworkBeforeRequestSentParameters) => void): this; on(event: 'continue', callback: (requestId: string) => void): this; on(event: 'fail', callback: (requestId: string) => void): this; on(event: 'overwrite', callback: (response: MockResponse) => void): this; on(event: string, callback: (...args: any[]) => void): this; /** * Restore every instance's mock. */ restore(...args: Parameters<WebdriverIO.Mock['restore']>): Promise<this>; /** * Wait until every instance has received a matching response. */ waitForResponse(...args: Parameters<WebdriverIO.Mock['waitForResponse']>): Promise<Awaited<ReturnType<WebdriverIO.Mock['waitForResponse']>>[]>; } type AddCommandFnScoped<InstanceType = WebdriverIO.Browser, IsElement extends boolean = false> = (this: IsElement extends true ? WebdriverIO.Element : InstanceType, ...args: any[]) => any; export type AddCommandFn = (...args: any[]) => any; type OverwriteCommandFnScoped<ElementKey extends keyof $ElementCommands, BrowserKey extends keyof $BrowserCommands, IsElement extends boolean = false> = (this: IsElement extends true ? WebdriverIO.Element : WebdriverIO.Browser, originalCommand: IsElement extends true ? OmitThisParameter<$ElementCommands[ElementKey]> : OmitThisParameter<$BrowserCommands[BrowserKey]>, ...args: any[]) => Promise<any>; type OverwriteCommandFn<ElementKey extends keyof $ElementCommands, BrowserKey extends keyof $BrowserCommands, IsElement extends boolean = false> = (this: IsElement extends true ? WebdriverIO.Element : WebdriverIO.Browser, originalCommand: IsElement extends true ? OmitThisParameter<$ElementCommands[ElementKey]> : OmitThisParameter<$BrowserCommands[BrowserKey]>, ...args: any[]) => Promise<any>; export type CustomLocatorReturnValue = HTMLElement | HTMLElement[] | NodeListOf<HTMLElement>; export type Instances = CustomCommands.Instances; export type CustomCommandOptions<IsElement extends boolean> = CustomCommands.CustomCommandOptions<IsElement>; export type AddCommandFunction<IsElement extends boolean, T = any, Instance = WebdriverIO.Browser> = IsElement extends true ? AddCommandFnScoped<T | Instance, IsElement> : AddCommandFn; type BrowsingContextCommandOptions = Omit<CustomCommands.CustomCommandOptions<false>, 'attachToElement' | 'attachToBrowsingContext'> & { attachToElement?: false; attachToBrowsingContext: true; }; type BrowsingContextCommand<Key extends keyof WebdriverIO.BrowsingContext> = WebdriverIO.BrowsingContext[Key] extends (...args: any[]) => any ? OmitThisParameter<WebdriverIO.BrowsingContext[Key]> : never; export interface CustomInstanceCommands<T> { /** * add command to every browsing context (tab, window, frame) */ addCommand(name: string, func: (this: WebdriverIO.BrowsingContext, ...args: any[]) => any, options: BrowsingContextCommandOptions): void; /** * add command to `browser`, or to an element when `options.attachToElement` is true */ addCommand<IsElement extends boolean = false, Instance extends Instances = WebdriverIO.Browser>(name: string, func: IsElement extends true ? AddCommandFnScoped<T | Instance, IsElement> : AddCommandFn, options?: CustomCommands.CustomCommandOptions<IsElement>): void; /** * overwrite a command of every browsing context (tab, window, frame) */ overwriteCommand<Key extends keyof WebdriverIO.BrowsingContext>(name: Key, func: (this: WebdriverIO.BrowsingContext, originalCommand: BrowsingContextCommand<Key>, ...args: any[]) => Promise<any>, options: BrowsingContextCommandOptions): void; /** * overwrite a `browser` command, or an element command when `options.attachToElement` is true */ overwriteCommand<ElementKey extends keyof $ElementCommands, BrowserKey extends keyof $BrowserCommands, IsElement extends boolean = false>(name: IsElement extends true ? ElementKey : BrowserKey, func: IsElement extends true ? OverwriteCommandFnScoped<ElementKey, BrowserKey, IsElement> : OverwriteCommandFn<ElementKey, BrowserKey, IsElement>, options?: CustomCommands.CustomCommandOptions<IsElement>): void; /** * create custom selector */ addLocatorStrategy(name: string, func: ((selector: string, root: HTMLElement) => CustomLocatorReturnValue) | ((selector: string) => CustomLocatorReturnValue)): void; } interface InstanceBase extends EventEmitter, SessionFlags { /** * Session id for the current running session */ sessionId: string; /** * Applied WebdriverIO options (options that aren't officially part of WebdriverIO are stripped * out of this object). */ options: Options.WebdriverIO | Options.Testrunner; /** * Puppeteer instance */ puppeteer?: PuppeteerBrowser; strategies: Map<any, any>; commandList: string[]; /** * @private */ __propertiesObject__: Record<string, PropertyDescriptor>; /** * @private */ wdioRetries?: number; } /** * a browser base that has everything besides commands which are defined for sync and async separately */ export interface BrowserBase extends InstanceBase, CustomInstanceCommands<WebdriverIO.Browser> { isMultiRemote: false; /** * capabilities of the browser instance */ capabilities: WebdriverIO.Capabilities; } export type WebdriverIOEventMap = EventMap & { 'dialog': WebdriverIO.Dialog; }; interface BidiEventHandler { on<K extends keyof WebdriverIOEventMap>(event: K, listener: (this: WebdriverIO.Browser, param: WebdriverIOEventMap[K]) => unknown): this; once<K extends keyof WebdriverIOEventMap>(event: K, listener: (this: WebdriverIO.Browser, param: WebdriverIOEventMap[K]) => unknown): this; } /** * @private */ export interface Browser extends Omit<BrowserBase, 'on' | 'once'>, BidiEventHandler, BidiHandler, ProtocolCommands, BrowserCommandsType { } /** * export a browser interface that can be used for typing plugins */ export interface ElementBase extends InstanceBase, ElementReference, CustomInstanceCommands<WebdriverIO.Element> { /** * capabilities of the browser instance */ capabilities: WebdriverIO.Capabilities; /** * WebDriver element reference */ elementId: string; /** * selector used to fetch this element, can be * - undefined if element was created via `$({ 'element-6066-11e4-a52e-4f735466cecf': 'ELEMENT-1' })` * - a string if `findElement` was used and a reference was found * - or a functin if element was found via e.g. `$(() => document.body)` */ selector: Selector; /** * index of the element if fetched with `$$` */ index?: number; /** * parent of the element if fetched via `$(parent).$(child)` */ parent: WebdriverIO.Element | WebdriverIO.Browser | WebdriverIO.BrowsingContext; /** * true if element is a React component */ isReactElement?: boolean; /** * true if element was queried from a shadow root */ isShadowElement?: boolean; /** * whether the element was queried with strict selector semantics, used to * keep the same behavior when the element is re-fetched */ strict?: boolean; /** * error response if element was not found */ error?: Error; /** * locator of the element * @requires WebDriver Bidi */ locator?: remote.BrowsingContextLocator; } interface MultiRemoteBase extends Omit<InstanceBase, 'sessionId'>, CustomInstanceCommands<WebdriverIO.MultiRemoteBrowser> { /** * capabilities of the browser instance */ capabilities: Capabilities.RequestedMultiRemoteCapabilities; /** * Multi-remote browser instance names */ instances: string[]; /** * flag to indicate multi-remote browser session */ isMultiRemote: true; /** * get a specific instance to run commands on it */ getInstance: (browserName: string) => WebdriverIO.Browser; /** * select one or multiple browsers always wrapped into a multi-remote to run commands on them. * Even if only one instance is selected, it will still return a multi-remote browser. * Use getInstance to have exclusive access to a single instance. */ select: (...browserNames: string[]) => WebdriverIO.MultiRemoteBrowser; } interface MultiRemoteElementBase { selector: Selector; /** * Multi-remote browser instance names */ instances: string[]; commandList: string[]; addCommand: Function; overwriteCommand: Function; /** * flag to indicate multi-remote browser session */ isMultiRemote: true; /** * get a specific instance to run commands on it */ getInstance: (browserName: string) => WebdriverIO.Element; /** * select one or multiple browsers always wrapped into a multi-remote to run commands on them. * Even if only one instance is selected, it will still return a multi-remote element. * Use getInstance to have exclusive access to a single element. */ select: (...browserNames: string[]) => WebdriverIO.MultiRemoteElement; /** * @private */ __propertiesObject__: never; } interface MultiRemoteBrowserType extends MultiRemoteBase, MultiRemoteBrowserCommandsType, MultiRemoteProtocolCommandsType { } interface MultiRemoteElementType extends MultiRemoteElementBase, MultiRemoteProtocolCommandsType, Omit<MultiRemoteBrowserCommandsType, keyof MultiRemoteElementCommandsType>, MultiRemoteElementCommandsType { } export type ElementFunction = ((elem: HTMLElement) => HTMLElement | undefined) | ((elem: HTMLElement) => (HTMLElement | undefined)[]); export type CustomStrategyFunction = (...args: any) => ElementReference | ElementReference[]; export type CustomStrategyReference = { strategy: CustomStrategyFunction; strategyName: string; strategyArguments: any[]; }; export type Selector = string | ElementReference | ElementFunction | CustomStrategyReference | HTMLElement; /** * options to modify how a single element is queried via `$` */ export interface ElementQueryOptions { /** * If `true` the query throws a `StrictSelectorError` when the selector resolves * to more than one element. Defaults to the `strictSelectors` config option * which itself defaults to `true`. */ strict?: boolean; } interface CSSValue { type: string; string: string; unit: string; value: any; } interface ParsedColor extends Partial<CSSValue> { rgb?: string; rgba?: string; hex?: string; } export interface ParsedCSSValue { property?: string; value?: string; parsed: ParsedColor; } interface NoneActionEntity { type: 'pause'; duration: number; } interface PointerActionEntity { type: 'pointerMove' | 'pointerDown' | 'pointerUp' | 'pointerCancel' | 'pause'; duration?: number; x?: number; y?: number; button?: number; } interface KeyActionEntity { type: 'keyUp' | 'keyDown'; duration?: number; value?: string; } export interface Action { id: string; actions: (NoneActionEntity | PointerActionEntity | KeyActionEntity)[]; type?: 'pointer' | 'key'; parameters?: { pointerType: 'mouse' | 'pen' | 'touch'; }; } export interface ActionParameter { actions: Action[]; } export type Matcher = { name: string; args: Array<string | object>; class?: string; }; export type ReactSelectorOptions = { props?: Record<string, unknown>; state?: Record<string, unknown>; }; export type MoveToOptions = { xOffset?: number; yOffset?: number; }; export type DragAndDropOptions = { duration?: number; }; export type NewWindowOptions = { type?: 'tab' | 'window'; /** * Top-level browsing context the new tab or window is opened from. * A frame is rejected. BiDi only. */ referenceContext?: string | WebdriverIO.BrowsingContext; }; export type TapOptions = MobileScrollIntoViewOptions & { x?: number; y?: number; }; export type LongPressOptions = { x: number; y: number; duration: number; }; export type ClickOptions = LongPressOptions & { button: Button | ButtonNames; skipRelease: boolean; }; export type PinchAndZoomOptions = { duration: number; scale: number; }; export type WaitForOptions = { timeout?: number; interval?: number; timeoutMsg?: string; reverse?: boolean; withinViewport?: boolean; }; export declare enum MobileScrollDirection { Down = "down", Up = "up", Left = "left", Right = "right" } export type XY = { x: number; y: number; }; export type SwipeOptions = { direction?: `${MobileScrollDirection}`; duration?: number; from?: XY; percent?: number; scrollableElement?: WebdriverIO.Element | ChainablePromiseElement; to?: XY; }; export type MobileScrollIntoViewOptions = SwipeOptions & { maxScrolls?: number; }; export interface CustomScrollIntoViewOptions extends ScrollIntoViewOptions, MobileScrollIntoViewOptions { } export type SwitchContextOptions = { appIdentifier?: string; title?: string | RegExp; url?: string | RegExp; androidWebviewConnectionRetryTime?: number; androidWebviewConnectTimeout?: number; }; type AppiumDetailedContextInterface = { id: string; title?: string; url?: string; }; type IosContextBundleId = { bundleId?: string; }; export type IosDetailedContext = AppiumDetailedContextInterface & IosContextBundleId; export type AndroidDetailedContext = AppiumDetailedContextInterface & { androidWebviewData?: { attached: boolean; empty: boolean; height: number; neverAttached: boolean; screenX: number; screenY: number; visible: boolean; width: number; }; packageName?: string; webviewPageId?: string; }; export type AppiumDetailedCrossPlatformContexts = (IosDetailedContext | AndroidDetailedContext)[]; export type GetContextsOptions = { androidWebviewConnectionRetryTime?: number; androidWebviewConnectTimeout?: number; filterByCurrentAndroidApp?: boolean; isAndroidWebviewVisible?: boolean; returnAndroidDescriptionData?: boolean; returnDetailedContexts?: boolean; waitForWebviewMs?: number; }; export type ActiveAppInfo = { pid: number; bundleId: string; name: string; processArguments: { args: string[]; env: Record<string, string>; }; }; export type WaitUntilOptions = { timeout?: number; timeoutMsg?: string | (() => string); interval?: number; }; export type DragAndDropCoordinate = { x: number; y: number; }; export interface AttachOptions extends Omit<WebDriverAttachOptions, 'capabilities'> { options?: Options.WebdriverIO; capabilities?: WebDriverAttachOptions['capabilities']; requestedCapabilities?: WebDriverAttachOptions['capabilities']; } export type ThrottlePreset = 'offline' | 'GPRS' | 'Regular2G' | 'Good2G' | 'Regular3G' | 'Good3G' | 'Regular4G' | 'DSL' | 'WiFi' | 'online'; export interface CustomThrottle { offline: boolean; downloadThroughput: number; uploadThroughput: number; latency: number; } export type ThrottleOptions = ThrottlePreset | CustomThrottle; export interface ExtendedElementReference { 'element-6066-11e4-a52e-4f735466cecf': string; locator: remote.BrowsingContextLocator; } export type SupportedScopes = 'geolocation' | 'userAgent' | 'colorScheme' | 'media' | 'onLine' | 'locale' | 'timezone' | 'touch' | 'orientation' | 'screen' | 'viewportMeta' | 'textLayout' | 'scripting' | 'scrollbar' | 'forcedColors' | 'clock' | 'device'; export type RestoreMap = Map<SupportedScopes, (() => Promise<any>)[]>; /** * Options for `browser.savePDF`. Lengths are centimeters. * * Defaults match WebDriver Classic `printPage` and WebDriver BiDi * `browsingContext.print`: portrait, scale `1`, background `false`, * shrink-to-fit `true`, page `21.59` × `27.94` cm, margins `1` cm. * Omitted fields are left to the browser. */ export interface PDFPrintOptions { /** * Page orientation. Accepted values are `portrait` and `landscape`. * The property stays a `string` so an existing variable of that type can * still be passed. Any other value is rejected when `savePDF` runs. * @default 'portrait' */ orientation?: string; /** * Page scale. The print protocols accept `0.1`–`2`. * @default 1 */ scale?: number; /** * Print the page background. * @default false */ background?: boolean; /** * Page width in centimeters. * @default 21.59 */ width?: number; /** * Page height in centimeters. * @default 27.94 */ height?: number; /** * Top margin in centimeters. * @default 1 */ top?: number; /** * Bottom margin in centimeters. * @default 1 */ bottom?: number; /** * Left margin in centimeters. * @default 1 */ left?: number; /** * Right margin in centimeters. * @default 1 */ right?: number; /** * Shrink the content to fit the page. * @default true */ shrinkToFit?: boolean; /** * Pages to include. Each entry is a page number or a range such as `'1-3'`. * @default [] */ pageRanges?: Array<string | number>; } /** * How `context.frame()` finds a frame: by the selector of its frame element * on the page, by its url (exact string or RegExp), or by its browsing * context id. */ export type FrameQuery = { selector: string; url?: never; id?: never; } | { url: string | RegExp; selector?: never; id?: never; } | { id: string; selector?: never; url?: never; }; export interface SaveScreenshotOptions { /** * Whether to take a screenshot of the full page or just the current viewport. * @default false */ fullPage?: boolean; /** * The format of the screenshot. * @default 'png' */ format?: 'png' | 'jpeg' | 'jpg'; /** * The quality of the screenshot in case of JPEG format in range 0-100 percent. * @default 100 */ quality?: number; /** * Clipping a rectangle of the screenshot. */ clip?: { x: number; y: number; width: number; height: number; }; } export type TransformElement<T> = T extends WebdriverIO.Element ? HTMLElement : T extends ChainablePromiseElement ? HTMLElement : T extends WebdriverIO.Element[] ? HTMLElement[] : T extends ChainablePromiseArray ? HTMLElement[] : T extends [infer First, ...infer Rest] ? [TransformElement<First>, ...TransformElement<Rest>] : T extends Array<infer U> ? Array<TransformElement<U>> : T; export type TransformReturn<T> = T extends HTMLElement ? WebdriverIO.Element : T extends HTMLElement[] ? WebdriverIO.Element[] : T extends [infer First, ...infer Rest] ? [TransformReturn<First>, ...TransformReturn<Rest>] : T extends Array<infer U> ? Array<TransformReturn<U>> : T; /** * Additional options outside of the WebDriver spec, exclusively for WebdriverIO, only for runtime, and not sent to Appium */ export interface InputOptions { mask?: boolean; } declare global { namespace WebdriverIO { /** * WebdriverIO browser object * @see https://webdriver.io/docs/api/browser */ interface Browser extends Omit<BrowserBase, 'on' | 'once'>, BidiEventHandler, BidiHandler, ProtocolCommands, BrowserCommandsType { } /** * WebdriverIO element object * @see https://webdriver.io/docs/api/element */ interface Element extends ElementBase, ProtocolCommands, ElementCommandsType { } /** * WebdriverIO element array * When fetching elements via `$$`, `custom$$` or `shadow$$` commands an array of elements * is returns. This array has extended prototype properties to provide information about * the parent element, selector and properties of the fetched elements. This is useful to * e.g. re-fetch the set in case no elements got returned. */ interface ElementArray extends ElementArrayExport { } /** * WebdriverIO multi-remote browser object * A multi-remote browser instance is a property on the global WebdriverIO browser object that * allows to control multiple browser instances at once. It can be represented as `Record<string, WebdriverIO.Browser>` * where `string` is the capability name defined in the WebdriverIO options. * * @see https://webdriver.io/docs/multiremote/ */ interface MultiRemoteBrowser extends MultiRemoteBrowserType { } /** * WebdriverIO multi-remote browser object * A multi-remote browser instance is a property on the global WebdriverIO browser object that * allows to control multiple browser instances at once. It can be represented as `Record<string, WebdriverIO.Element>` * where `string` is the capability name defined in the WebdriverIO options. * * @see https://webdriver.io/docs/multiremote/ */ interface MultiRemoteElement extends MultiRemoteElementType { } /** * WebdriverIO multi-remote element array * What `$$`, `custom$$`, `react$$` and `shadow$$` return on a multi-remote * browser or element. Like `ElementArray` * it carries the selector, parent and properties of the fetched set, and * `isMultiRemote` marks it as the multi-remote variant. * * @see https://webdriver.io/docs/multiremote/ */ interface MultiRemoteElementArray extends MultiRemoteElementArrayExport { } /** * WebdriverIO multi-remote mock * What `browser.mock()` returns on a multi-remote browser. `instances` names * each mock, `getInstance(name)` returns that browser's mock, and mock * methods such as `respond` and `restore` run on every instance. * * @see https://webdriver.io/docs/multiremote/ */ interface MultiRemoteMock extends MultiRemoteMockBase { } /** * WebdriverIO Mock object * The mock object is an object that represents a network mock and contains information about * requests that were matching given url and filterOptions. It can be received using the mock command. * * @see https://webdriver.io/docs/api/mock */ interface Mock extends WebDriverInterception { } /** * WebdriverIO Dialog object * The dialog object represents a user prompt that was triggered by the browser. It contains * information about the message, type and default value of the prompt. * It can be received using the `on('dialog')` event. * * @see https://webdriver.io/docs/api/dialog */ interface Dialog extends DialogImport { } /** * A tab, a window, or a frame. Commands on this object send the BiDi * method with `contextId` and do not move the session's current context. * `parent` is absent on a top-level context. `url` is the document URL. * Navigate a held context with `navigate()`. `browser.url()` navigates * the session's initial top-level context and returns it. */ /** * Commands typed with `this: WebdriverIO.Browser` drop that `this` * here (`OmitThisParameter`), so they can be called on a context. */ interface BrowsingContext { isBidi: boolean; isMobile: boolean; capabilities: WebdriverIO.Capabilities; sessionId: string; options: Browser['options']; strategies: Map<string, unknown>; $(selector: Selector, options?: ElementQueryOptions): ChainablePromiseElement; $$(selector: Selector): ChainablePromiseArray; custom$: Browser['custom$']; custom$$: Browser['custom$$']; react$: Browser['react$']; react$$: Browser['react$$']; execute: Browser['execute']; action: Browser['action']; actions: Browser['actions']; keys: OmitThisParameter<Browser['keys']>; scroll: OmitThisParameter<Browser['scroll']>; saveScreenshot: OmitThisParameter<Browser['saveScreenshot']>; savePDF: OmitThisParameter<Browser['savePDF']>; getCookies: Browser['getCookies']; setCookies: Browser['setCookies']; deleteCookies: Browser['deleteCookies']; setViewport: Browser['setViewport']; addInitScript: Browser['addInitScript']; mock: Browser['mock']; mockClearAll: Browser['mockClearAll']; mockRestoreAll: Browser['mockRestoreAll']; emulate: Browser['emulate']; restore: OmitThisParameter<Browser['restore']>; waitUntil: Browser['waitUntil']; pause: OmitThisParameter<Browser['pause']>; frame(target: FrameQuery | string | Element | ChainablePromiseElement | ((context: { context: string; url: string; }) => boolean | Promise<boolean>)): Promise<BrowsingContext>; navigate(url: string, options?: { wait?: 'none' | 'interactive' | 'networkIdle' | 'complete'; headers?: Record<string, string>; auth?: { user: string; pass: string; }; timeout?: number; onBeforeLoad?: Function; }): Promise<BrowsingContext>; refresh(): Promise<void>; closeWindow(): Promise<void>; activate(): Promise<void>; getTitle(): Promise<string>; getUrl(): Promise<string>; back(): Promise<void>; forward(): Promise<void>; acceptAlert(text?: string): Promise<void>; dismissAlert(): Promise<void>; getAlertText(): Promise<string>; on: Browser['on']; off: Browser['off']; once: Browser['once']; emit: Browser['emit']; removeListener: Browser['removeListener']; removeAllListeners: Browser['removeAllListeners']; addCommand(...args: unknown[]): Promise<never>; overwriteCommand(...args: unknown[]): Promise<never>; } } } //# sourceMappingURL=types.d.ts.map