# WebdriverIO > WebdriverIO is an open source, openly governed test automation framework for web browsers, native and hybrid mobile apps, desktop apps and VS Code extensions. ## community ### donate If your company uses WebdriverIO and benefits from it, please ask your manager or your marketing team to support the project by donating to the collective. Support will allow the maintainers to dedicate more time for maintenance and new features for everyone. - [Donate](/community/donate.md): If your company uses WebdriverIO and benefits from it, please ask your manager or your marketing team to support the project by donating to the collective. Support will allow the maintainers to dedicate more time for maintenance and new features for everyone. ### events The WebdriverIO community organizes events around the world. The project is completely community driven and we encourage and support everyone who likes to host and run WebdriverIO meetups and events. - [WebdriverIO Events](/community/events.md): The WebdriverIO community organizes events around the world. The project is completely community driven and we encourage and support everyone who likes to host and run WebdriverIO meetups and events. ### materials If you want to use WebdriverIO materials for your own workshops or events feel free to grab them directly from here. - [Materials](/community/materials.md): If you want to use WebdriverIO materials for your own workshops or events feel free to grab them directly from here. ### openofficehours Contributing to a big Open Source project can be hard. Especially if the codebase is large and requires a lot of context to understand what certain changes do. Then there is the possibility that tools or infrastructure is being used that are unknown. Nevertheless the project depends on your contributions and help to identify bugs and fix them. How can we overcome this hurdle? - [Office Hours](/community/openofficehours.md): Contributing to a big Open Source project can be hard. Especially if the codebase is large and requires a lot of context to understand what certain changes do. Then there is the possibility that tools or infrastructure is being used that are unknown. Nevertheless the project depends on your contributions and help to identify bugs and fix them. How can we overcome this hurdle? ### resources There are many wonderful curated resources the WebdriverIO community has put together. - [Resources](/community/resources.md): There are many wonderful curated resources the WebdriverIO community has put together. ### support This project is maintained by a dedicated group of people. - [Need Help?](/community/support.md): This project is maintained by a dedicated group of people. ### team The WebdriverIO development is led by a dedicated team of developers and SDETs from various companies as well contributions from people around the world. - [Team](/community/team.md): The WebdriverIO development is led by a dedicated team of developers and SDETs from various companies as well contributions from people around the world. ## docs ### accessibility-testing - [Axe Core](/docs/accessibility-testing/axe-core.md): Run automated accessibility checks in your tests with the open-source Axe adapter from Deque, in standalone or testrunner mode. - [BrowserStack Accessibility Testing](/docs/accessibility-testing/browserstack.md): Add automated accessibility scans to WebdriverIO tests running on BrowserStack Automate and review the issues found in BrowserStack reports. - [TestMu AI Accessibility Testing](/docs/accessibility-testing/testmuai.md): Enable TestMu AI (formerly LambdaTest) accessibility testing in your WebdriverIO suite, configure scan options and view the accessibility reports. ### ai-agents Set up Cursor, Claude Code, Copilot or any other coding agent to write, run and debug WebdriverIO tests using the machine-readable docs, the WebdriverIO MCP server and DevTools traces. - [WebdriverIO for Coding Agents](/docs/ai-agents.md): Set up Cursor, Claude Code, Copilot or any other coding agent to write, run and debug WebdriverIO tests using the machine-readable docs, the WebdriverIO MCP server and DevTools traces. ### ai-service A WebdriverIO service that adds browser.act() and browser.extract(): steps written as intent, recorded as WebdriverIO commands and healed when the page changes - [AI Service](/docs/ai-service.md): A WebdriverIO service that adds browser.act() and browser.extract(): steps written as intent, recorded as WebdriverIO commands and healed when the page changes ### ai-steps Write test steps as intent with browser.act() and read typed data with browser.extract() using @wdio/ai-service, then replay them from a committed cache without a model and review every heal. - [AI Steps in Tests](/docs/ai-steps.md): Write test steps as intent with browser.act() and read typed data with browser.extract() using @wdio/ai-service, then replay them from a committed cache without a model and review every heal. ### allure-reporter A WebdriverIO reporter plugin to create Allure Test Reports - [Allure Reporter](/docs/allure-reporter.md): A WebdriverIO reporter plugin to create Allure Test Reports ### api Find reference docs for WebdriverIO protocol bindings and convenience commands, including WebDriver, WebDriver Bidi and Appium commands. - [Introduction](/docs/api.md): Find reference docs for WebdriverIO protocol bindings and convenience commands, including WebDriver, WebDriver Bidi and Appium commands. - [Appium](/docs/api/appium.md): getLogTypes - [The Browser Object](/docs/api/browser.md): Extends: EventEmitter - [$](/docs/api/browser/$.md): The $ command is a short and handy way in order to fetch a single element on the page. - [$$](/docs/api/browser/$$.md): $$ fetches every element that matches a selector. It returns a WebdriverIO.ElementArray - [action](/docs/api/browser/action.md): The action command is a low-level interface for providing virtualized device input actions to the web browser. - [actions](/docs/api/browser/actions.md): Allows to run multiple action interactions at once, e.g. to simulate a pinch zoom or hold a modifier key while - [addCommand](/docs/api/browser/addCommand.md): The browser method addCommand helps you to write your own set of commands. - [addInitScript](/docs/api/browser/addInitScript.md): Adds a script which would be evaluated in one of the following scenarios: - [back](/docs/api/browser/back.md): Go one step back in the joint session history of the current top-level - [browsingContexts](/docs/api/browser/browsingContexts.md): Get every open tab and window of the session as a browsing context, - [call](/docs/api/browser/call.md): You can use call to execute any async action within your test spec. - [custom$](/docs/api/browser/custom$.md): The custom$ allows you to use a custom strategy declared by using browser.addLocatorStrategy. - [custom$$](/docs/api/browser/custom$$.md): The customs$$ allows you to use a custom strategy declared by using browser.addLocatorStrategy. - [debug](/docs/api/browser/debug.md): This command helps you to debug your integration tests. It stops the running browser and gives - [deleteCookies](/docs/api/browser/deleteCookies.md): Delete cookies visible to the current page. By providing a cookie name it - [downloadFile](/docs/api/browser/downloadFile.md): Download a file from the remote computer running Selenium node to local file system - [emulate](/docs/api/browser/emulate.md): Emulation commands that take contexts require a top-level traversable. - [execute](/docs/api/browser/execute.md): Inject a snippet of JavaScript into the page for execution in the context of the currently selected frame. - [forward](/docs/api/browser/forward.md): Go one step forward in the joint session history of the current top-level - [getCookies](/docs/api/browser/getCookies.md): Retrieve a cookie - [getPuppeteer](/docs/api/browser/getPuppeteer.md): Get the Puppeteer Browser instance - [getWindowSize](/docs/api/browser/getWindowSize.md): Returns browser window size. - [installExtension](/docs/api/browser/installExtension.md): Same hosts wdio session treats as a local browser in - [keys](/docs/api/browser/keys.md): Send a sequence of key strokes to the "active" element. You can make an input element active by just clicking - [mock](/docs/api/browser/mock.md): Mock the response of a request. You can define a mock based on a matching - [mockClearAll](/docs/api/browser/mockClearAll.md): Resets all information stored in all registered mocks of the session. - [mockRestoreAll](/docs/api/browser/mockRestoreAll.md): Restores all mock information and behavior stored in all registered - [navigateInContext](/docs/api/browser/navigateInContext.md): The desired state the requested resource should be in before finishing the command. - [newWindow](/docs/api/browser/newWindow.md): Open a new window or tab and wait until its page has loaded, the equivalent of window.open(). - [overwriteCommand](/docs/api/browser/overwriteCommand.md): The browser method overwriteCommand helps you to overwrite the browser's and element's native commands like pause and click. - [pause](/docs/api/browser/pause.md): Pauses execution for a specific amount of time. It is recommended to not use this command to wait for an - [react$](/docs/api/browser/react$.md): The react$ command is a useful command to query React Components by their - [react$$](/docs/api/browser/react$$.md): The react$$ command is a useful command to query multiple React Components - [reloadSession](/docs/api/browser/reloadSession.md): Creates a new Selenium session with your current capabilities. This is useful if you - [restore](/docs/api/browser/restore.md): This command restores specific or all emulated behaviors that were set using the emulate command. - [savePDF](/docs/api/browser/savePDF.md): Prints the page of the current browsing context to a PDF file on your OS. - [saveRecordingScreen](/docs/api/browser/saveRecordingScreen.md): Save a video started by startRecordingScreen command to file. - [saveScreenshot](/docs/api/browser/saveScreenshot.md): Save a screenshot of the current browsing context to a PNG file on your OS. Be aware that - [scroll](/docs/api/browser/scroll.md): Scroll within the browser viewport. Note that x and y coordinates are relative to the current - [setCookies](/docs/api/browser/setCookies.md): Sets one or more cookies for the current page. Make sure you are - [setTimeout](/docs/api/browser/setTimeout.md): Sets the timeouts associated with the current session, timeout durations control such - [setViewport](/docs/api/browser/setViewport.md): Resizes the browser viewport within the browser. As oppose to setWindowSize, - [setWindowSize](/docs/api/browser/setWindowSize.md): Resizes browser window outer size according to provided width and height. Based on your operating - [switchFrame](/docs/api/browser/switchFrame.md): Switch the Classic session into a frame. - [switchWindow](/docs/api/browser/switchWindow.md): Switch focus to a particular tab / window (Classic sessions). - [throttleCPU](/docs/api/browser/throttleCPU.md): Throttles the CPU to emulate a slower processor. - [throttleNetwork](/docs/api/browser/throttleNetwork.md): Throttle the network capabilities of the browser. This can help to - [uninstallExtension](/docs/api/browser/uninstallExtension.md): Uninstall a web extension that was installed with installExtension. - [url](/docs/api/browser/url.md): The url command loads an URL in the browser. If a baseUrl is specified in the config, - [waitUntil](/docs/api/browser/waitUntil.md): This wait command is your universal weapon if you want to wait on something. It expects a condition - [The BrowsingContext Object](/docs/api/browsingContext.md): Hold a tab, a window or a frame as an object and run commands in it directly, without switching the session to it. - [acceptAlert](/docs/api/browsingContext/acceptAlert.md): Accept the user prompt (alert, confirm or prompt) that is open in this - [activate](/docs/api/browsingContext/activate.md): Bring the tab or window of this browsing context to the front and focus it. - [back](/docs/api/browsingContext/back.md): Go back one entry in the history of this tab or window, like the browser's back - [closeWindow](/docs/api/browsingContext/closeWindow.md): Close the tab or window of this browsing context. Other tabs and windows stay - [dismissAlert](/docs/api/browsingContext/dismissAlert.md): Dismiss the user prompt (alert, confirm or prompt) that is open in this - [forward](/docs/api/browsingContext/forward.md): Go forward one entry in the history of this tab or window, like the browser's - [frame](/docs/api/browsingContext/frame.md): Get a frame (` or `) of this browsing context as a browsing - [getAlertText](/docs/api/browsingContext/getAlertText.md): Get the message of the user prompt (alert, confirm or prompt) that is - [getTitle](/docs/api/browsingContext/getTitle.md): Get the title of the document shown in this browsing context. For a frame - [getUrl](/docs/api/browsingContext/getUrl.md): Get the URL of the document shown in this browsing context, read from the - [navigate](/docs/api/browsingContext/navigate.md): Navigate this browsing context to a URL and wait until the page has loaded. - [refresh](/docs/api/browsingContext/refresh.md): Reload the document of this browsing context and wait until the new document - [Chromium](/docs/api/chromium.md): isAlertOpen - [The Clock Object](/docs/api/clock.md): You can modify the browser system clock using the emulate command. It overrides native global functions related to time allowing them to be controlled synchronously via clock.tick() or the yielded clock object. This includes controlling: - [restore](/docs/api/clock/restore.md): Restore all overridden native functions. This is automatically called between tests, so should not - [setSystemTime](/docs/api/clock/setSystemTime.md): Change the system time to the new now. Now can be a timestamp, date object, or not passed in which defaults - [tick](/docs/api/clock/tick.md): Move the clock the specified number of milliseconds. Any timers within the affected range of time will be called. - [The Dialog Object](/docs/api/dialog.md): Dialog objects are dispatched by browser via the browser.on('dialog') event. - [accept](/docs/api/dialog/accept.md): Accepts the dialog and returns when the dialog has been handled. - [defaultValue](/docs/api/dialog/defaultValue.md): If dialog is prompt, returns default prompt value. Otherwise, returns empty string. - [dismiss](/docs/api/dialog/dismiss.md): Dismisses the dialog and returns when the dialog has been handled. - [message](/docs/api/dialog/message.md): A message displayed in the dialog. - [type](/docs/api/dialog/type.md): Returns dialog's type, can be one of alert, beforeunload, confirm or prompt. - [The Element Object](/docs/api/element.md): An Element Object is an object representing an element on the remote user agent, e.g. a DOM Node when running a session within a browser or a mobile element for mobile. It can be received using one of the many element query commands, e.g. $, custom$, react$ or shadow$. - [$](/docs/api/element/$.md): The $ command is a short and handy way in order to fetch a single element on the page. - [$$](/docs/api/element/$$.md): The $$ command fetches every element that matches a selector, starting from this element. - [addValue](/docs/api/element/addValue.md): Add a value to an input or textarea element found by given selector. - [clearValue](/docs/api/element/clearValue.md): Clear the value of an input or textarea element. Make sure you can interact with the - [click](/docs/api/element/click.md): Click on an element. - [custom$](/docs/api/element/custom$.md): The custom$ allows you to use a custom strategy declared by using browser.addLocatorStrategy. - [custom$$](/docs/api/element/custom$$.md): The customs$$ allows you to use a custom strategy declared by using browser.addLocatorStrategy. - [doubleClick](/docs/api/element/doubleClick.md): Double-click on an element. - [dragAndDrop](/docs/api/element/dragAndDrop.md): Drag an item to a destination element or position. - [execute](/docs/api/element/execute.md): Inject a snippet of JavaScript into the page for execution in the context of the currently selected - [getAttribute](/docs/api/element/getAttribute.md): Get an attribute from a DOM-element based on the attribute name. - [getComputedLabel](/docs/api/element/getComputedLabel.md): Get the computed WAI-ARIA label of an element. - [getComputedRole](/docs/api/element/getComputedRole.md): Get the computed WAI-ARIA label of an element. - [getCSSProperty](/docs/api/element/getCSSProperty.md): Get a css property from a DOM-element selected by given selector. The return value - [getElement](/docs/api/element/getElement.md): Access WebdriverIO.Element properties like selector or elementId from the element reference. - [getElements](/docs/api/element/getElements.md): Access WebdriverIO.ElementArray properties like length or selector from the elements reference. - [getHTML](/docs/api/element/getHTML.md): Get source code of specified DOM element by selector. By default, it automatically - [getLocation](/docs/api/element/getLocation.md): Determine an element’s location on the page. The point (0, 0) refers to - [getProperty](/docs/api/element/getProperty.md): The Get Element Property command will return the result of getting a property of an - [getSize](/docs/api/element/getSize.md): Get the width and height for an DOM-element. - [getTagName](/docs/api/element/getTagName.md): Get tag name of a DOM-element. - [getText](/docs/api/element/getText.md): Get the text content from a DOM-element. Make sure the element - [getValue](/docs/api/element/getValue.md): Get the value of a `, or text ` found by given selector. - [isClickable](/docs/api/element/isClickable.md): An element is considered to be clickable when the following conditions are met: - [isDisplayed](/docs/api/element/isDisplayed.md): Return true if the selected DOM-element is displayed (even when the element is outside the viewport). It is using - [isEnabled](/docs/api/element/isEnabled.md): Return true or false if the selected DOM-element is enabled. - [isEqual](/docs/api/element/isEqual.md): Return true if the selected element matches with the provided one. - [isExisting](/docs/api/element/isExisting.md): Returns true if element exists in the DOM. - [isFocused](/docs/api/element/isFocused.md): Return true or false if the selected DOM-element currently has focus. If the selector matches - [isSelected](/docs/api/element/isSelected.md): Will return true or false whether or not an ` or ` element of type - [isStable](/docs/api/element/isStable.md): Will return true when the element is stable (not animating) or false when unstable (currently animating). - [moveTo](/docs/api/element/moveTo.md): Move the mouse by an offset of the specified element. If no element is specified, - [nextElement](/docs/api/element/nextElement.md): Returns the next sibling element of the selected DOM-element. - [parentElement](/docs/api/element/parentElement.md): Returns the parent element of the selected DOM-element. - [previousElement](/docs/api/element/previousElement.md): Returns the previous sibling element of the selected DOM-element. - [react$](/docs/api/element/react$.md): The react$ command is a useful command to query React Components by their - [react$$](/docs/api/element/react$$.md): The react$$ command is a useful command to query multiple React Components - [saveScreenshot](/docs/api/element/saveScreenshot.md): Save a screenshot of an element to a PNG file on your OS. - [scrollIntoView](/docs/api/element/scrollIntoView.md): Scroll element into viewport for Desktop/Mobile Web AND Mobile Native Apps. - [selectByAttribute](/docs/api/element/selectByAttribute.md): Select option with a specific value. - [selectByIndex](/docs/api/element/selectByIndex.md): Select option with a specific index. - [selectByVisibleText](/docs/api/element/selectByVisibleText.md): Select option with displayed text matching the argument. - [setFiles](/docs/api/element/setFiles.md): Set the files of an `` with the WebDriver BiDi - [setValue](/docs/api/element/setValue.md): Input types whose value can't be typed: a range input ignores key strokes, - [shadow$](/docs/api/element/shadow$.md): Access an element inside a given element's shadowRoot. If you are working - [shadow$$](/docs/api/element/shadow$$.md): Access elements inside a given element's shadowRoot. The result is a - [waitForClickable](/docs/api/element/waitForClickable.md): Wait for an element for the provided amount of milliseconds to be clickable or not clickable. - [waitForDisplayed](/docs/api/element/waitForDisplayed.md): true to check if the element is within the viewport. false by default. - [waitForEnabled](/docs/api/element/waitForEnabled.md): Wait for an element (selected by css selector) for the provided amount of - [waitForExist](/docs/api/element/waitForExist.md): Wait for an element for the provided amount of - [waitForStable](/docs/api/element/waitForStable.md): Wait for an element for the provided amount of - [waitUntil](/docs/api/element/waitUntil.md): This wait command is your universal weapon if you want to wait on something. It expects a condition - [Environment Variables](/docs/api/environment.md): WebdriverIO sets the following environment variables within every worker: - [Expect](/docs/api/expect-webdriverio.md): When you're writing tests, you often need to check that values meet certain conditions. expect gives you access to a number of "matchers" that let you validate different things on the browser, an element or mock object. - [Firefox](/docs/api/gecko.md): fullPageScreenshot - [Globals](/docs/api/globals.md): In your test files, WebdriverIO puts each of these methods and objects into the global environment. You don't have to import anything to use them. However, if you prefer explicit imports, you can do import { browser, $, $$, expect } from '@wdio/globals' and set injectGlobals: false in your WDIO configuration. - [Introduction to custom and enhanced Mobile Commands in WebdriverIO](/docs/api/mobile.md): Testing mobile apps and mobile web applications comes with its own challenges, especially when dealing with platform-specific differences between Android and iOS. While Appium provides the flexibility to handle these differences, it often requires you to dive deep into complex, platform-dependent docs (Android, iOS) and commands. This can make writing test scripts more time-consuming, error-prone, and difficult to maintain. - [acceptDialog](/docs/api/mobile/acceptDialog.md): Accept a native mobile alert or permission dialog. - [background](/docs/api/mobile/background.md): Send the currently running app for this session to the background. - [closeApp](/docs/api/mobile/closeApp.md): Close a specific app or the currently active app on the device. - [deepLink](/docs/api/mobile/deepLink.md): Open a deep link URL in the mobile app based on the url and the app's package name (Android) or bundle ID (iOS). - [dismissDialog](/docs/api/mobile/dismissDialog.md): Dismiss a native mobile alert or permission dialog. - [dragAndDrop](/docs/api/mobile/dragAndDrop.md): Drag an item to a destination element or position. - [fingerPrint](/docs/api/mobile/fingerPrint.md): Authenticate users by using their fingerprint scan on supported Android emulators. The - [getClipboard](/docs/api/mobile/getClipboard.md): Get the content of the system clipboard as a base64-encoded string. - [getContext](/docs/api/mobile/getContext.md): Retrieve the context of the current session. - [getContexts](/docs/api/mobile/getContexts.md): The WebdriverIO getContexts method is an improved version of the default Appium contexts - [getCurrentActivity](/docs/api/mobile/getCurrentActivity.md): Get the name of the current Android activity. - [getCurrentPackage](/docs/api/mobile/getCurrentPackage.md): Get the name of the current Android package. - [getDisplayDensity](/docs/api/mobile/getDisplayDensity.md): Get the display density from the device. - [getPerformanceData](/docs/api/mobile/getPerformanceData.md): Get performance data for a specific application. Returns system state information like cpu, - [getPerformanceDataTypes](/docs/api/mobile/getPerformanceDataTypes.md): Returns the information types of the system state which is supported to read - [getStrings](/docs/api/mobile/getStrings.md): Get app strings for a specific language. Returns a key-value object of all string resources - [getSystemBars](/docs/api/mobile/getSystemBars.md): Retrieve visibility and bounds information of the status and navigation bars. - [gsmCall](/docs/api/mobile/gsmCall.md): Make a GSM call on the Android emulator. Valid actions: 'call', 'accept', 'cancel', 'hold'. - [gsmSignal](/docs/api/mobile/gsmSignal.md): Set the GSM signal strength on the Android emulator. - [gsmVoice](/docs/api/mobile/gsmVoice.md): Set the GSM voice state on the Android emulator. Valid values: 'unregistered', 'home', - [isLocked](/docs/api/mobile/isLocked.md): Check whether the device screen is locked. - [launchApp](/docs/api/mobile/launchApp.md): Launch or activate an app on the device. If no bundleId (iOS) or appId (Android) is provided, - [lock](/docs/api/mobile/lock.md): Lock the device screen. - [longPress](/docs/api/mobile/longPress.md): Performs a long press gesture on the given element on the screen. - [longPressKeyCode](/docs/api/mobile/longPressKeyCode.md): Press and hold a particular key code on the device. - [openNotifications](/docs/api/mobile/openNotifications.md): Open Android notifications. - [pinch](/docs/api/mobile/pinch.md): Performs a pinch gesture on the given element on the screen. - [powerAC](/docs/api/mobile/powerAC.md): Set the state of the battery charger on the Android emulator. Valid values: 'on', 'off'. - [powerCapacity](/docs/api/mobile/powerCapacity.md): Set the battery percentage on the Android emulator. Value must be in the range [0, 100]. - [pressKeyCode](/docs/api/mobile/pressKeyCode.md): Press a particular key on the device. The keycode values correspond to Android KeyEvent constants. - [relaunchActiveApp](/docs/api/mobile/relaunchActiveApp.md): Performs a restart of the active native app by: - [scrollIntoView](/docs/api/mobile/scrollIntoView.md): Scroll element into viewport for Desktop/Mobile Web AND Mobile Native Apps. - [sendKeyEvent](/docs/api/mobile/sendKeyEvent.md): Send a key event to the Android device. - [sendSms](/docs/api/mobile/sendSms.md): Simulate an SMS message being received on the Android emulator. - [setClipboard](/docs/api/mobile/setClipboard.md): Set the content of the system clipboard. - [shake](/docs/api/mobile/shake.md): Perform a shake action on the device. Supports iOS Simulator and real devices. - [startActivity](/docs/api/mobile/startActivity.md): The package name of the app to start. - [swipe](/docs/api/mobile/swipe.md): Swipe in a specific direction within viewport or element for Desktop/Mobile Web AND Mobile Native Apps. - [switchContext](/docs/api/mobile/switchContext.md): Switch to a specific context using a given Webview name, title, or url. - [tap](/docs/api/mobile/tap.md): Performs a tap gesture on: - [toggleAirplaneMode](/docs/api/mobile/toggleAirplaneMode.md): Set the airplane mode state on the device. - [toggleData](/docs/api/mobile/toggleData.md): Set the mobile data state on the device. - [toggleEnrollTouchId](/docs/api/mobile/toggleEnrollTouchId.md): Toggle Touch ID enrollment on iOS Simulator. - [toggleLocationServices](/docs/api/mobile/toggleLocationServices.md): Toggle the state of the location service. - [toggleNetworkSpeed](/docs/api/mobile/toggleNetworkSpeed.md): Set the network speed for the Android emulator. Valid values: 'full', 'gsm', 'edge', 'hscsd', - [toggleWiFi](/docs/api/mobile/toggleWiFi.md): Set the WiFi state on the device. - [touchId](/docs/api/mobile/touchId.md): Simulate a Touch ID or Face ID biometric match event on iOS Simulator. - [unlock](/docs/api/mobile/unlock.md): Unlock the device screen. - [zoom](/docs/api/mobile/zoom.md): Performs a zoom gesture on the given element on the screen. - [The Mock Object](/docs/api/mock.md): 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. - [abort](/docs/api/mock/abort.md): Abort the request with one of the following error codes: - [abortOnce](/docs/api/mock/abortOnce.md): Abort the request once with one of the following error codes: - [clear](/docs/api/mock/clear.md): Resets all information stored in the mock.calls array. - [redirect](/docs/api/mock/redirect.md): Sets up a redirect for a given mock. This allows you to redirect a request to another URL. - [request](/docs/api/mock/request.md): Allows you do modify requests the browser makes during the session. This can be useful for the following use cases: - [requestOnce](/docs/api/mock/requestOnce.md): Only change request parameter once with given overwrite for the next request. You can call requestOnce multiple - [respond](/docs/api/mock/respond.md): Always respond with same overwrite. - [respondOnce](/docs/api/mock/respondOnce.md): Only respond once with given overwrite. You can call respondOnce multiple - [restore](/docs/api/mock/restore.md): Does everything that mock.clear() does, and also removes any mocked return values or implementations. - [waitForResponse](/docs/api/mock/waitForResponse.md): Wait until at least one matching request has received a response. - [Modules](/docs/api/modules.md): WebdriverIO publishes various modules to NPM and other registries that you can use to build your own automation framework. See more documentation on WebdriverIO setup types here. - [Protocol Commands](/docs/api/protocols.md): WebdriverIO is an automation framework that relies on various automation protocols to control a remote agent, e.g. for a browser, mobile device or television. Based on the remote device different protocols come into play. These commands are assigned to the Browser or Element Object depending on the session information by the remote server (e.g. browser driver). - [Sauce Labs](/docs/api/saucelabs.md): All commands are only supported on Chrome using Sauce Labs - [Selenium Standalone](/docs/api/selenium.md): file - [WebDriver Protocol](/docs/api/webdriver.md): newSession - [WebDriver Bidi Protocol](/docs/api/webdriverBidi.md): These protocol commands are generated based on the current living ### appium Set up Appium and its drivers with the appium-installer toolkit to test native mobile, hybrid and desktop apps with WebdriverIO. - [Appium Setup](/docs/appium.md): Set up Appium and its drivers with the appium-installer toolkit to test native mobile, hybrid and desktop apps with WebdriverIO. ### appium-service A WebdriverIO service to start & stop Appium Server - [Appium Service](/docs/appium-service.md): A WebdriverIO service to start & stop Appium Server ### arm64-chromedriver How WebdriverIO sets up Chromedriver on ARM64 macOS, Windows and Linux, and what to do when no matching Linux ARM64 driver exists. - [Chromedriver on ARM64](/docs/arm64-chromedriver.md): How WebdriverIO sets up Chromedriver on ARM64 macOS, Windows and Linux, and what to do when no matching Linux ARM64 driver exists. ### assertion Write assertions on browser and element state with the built-in expect-webdriverio library, use soft assertions and migrate from Chai. - [Assertion](/docs/assertion.md): Write assertions on browser and element state with the built-in expect-webdriverio library, use soft assertions and migrate from Chai. ### async-migration Migrate WebdriverIO tests from synchronous to asynchronous command execution step by step, including forEach loops, assertions and sync page objects. - [From Sync to Async](/docs/async-migration.md): Migrate WebdriverIO tests from synchronous to asynchronous command execution step by step, including forEach loops, assertions and sync page objects. ### autocompletion Get autocompletion and inline API documentation for WebdriverIO commands in IntelliJ, WebStorm and Visual Studio Code. - [Autocompletion](/docs/autocompletion.md): Get autocompletion and inline API documentation for WebdriverIO commands in IntelliJ, WebStorm and Visual Studio Code. ### automationProtocols Understand the WebDriver Bidi and WebDriver automation protocols and choose which one WebdriverIO uses to automate browsers and devices. - [Automation Protocols](/docs/automationProtocols.md): Understand the WebDriver Bidi and WebDriver automation protocols and choose which one WebdriverIO uses to automate browsers and devices. ### autowait Understand how WebdriverIO automatically waits for elements to become interactable, when to wait manually, and why implicit timeouts are discouraged. - [Auto-waiting](/docs/autowait.md): Understand how WebdriverIO automatically waits for elements to become interactable, when to wait manually, and why implicit timeouts are discouraged. ### badisi-wdio-harness @badisi/wdio-harness is a 3rd party package, for more information please see GitHub | npm - [Support for Angular component test harnesses Service](/docs/badisi-wdio-harness.md): @badisi/wdio-harness is a 3rd party package, for more information please see GitHub | npm ### bamboo Run WebdriverIO tests in Atlassian Bamboo and publish JUnit results so you can track passing, failing and fixed tests per build. - [Bamboo](/docs/bamboo.md): Run WebdriverIO tests in Atlassian Bamboo and publish JUnit results so you can track passing, failing and fixed tests per build. ### best-practices - [Browser Logs](/docs/best-practices/browser-logs.md): Capture browser console logs during a test with WebDriver Bidi log events and assert against the collected messages. - [File Download](/docs/best-practices/file-download.md): Configure download directories for Chrome, Firefox and Edge, wait for downloads to finish and verify downloaded files across browsers. ### bestpractices Write fast, resilient tests with WebdriverIO by using stable selectors, fewer element queries, built-in assertions and no manual pauses. - [Best Practices](/docs/bestpractices.md): Write fast, resilient tests with WebdriverIO by using stable selectors, fewer element queries, built-in assertions and no manual pauses. ### boilerplates Browse community boilerplate projects for WebdriverIO with Mocha, Jasmine, Cucumber, Electron and mobile setups to bootstrap your own test suite. - [v9 Boilerplate Projects](/docs/boilerplates.md): Browse community boilerplate projects for WebdriverIO with Mocha, Jasmine, Cucumber, Electron and mobile setups to bootstrap your own test suite. ### capabilities Define capabilities to choose the browser or mobile environment your tests run in, including custom vendor capabilities and special use cases. - [Capabilities](/docs/capabilities.md): Define capabilities to choose the browser or mobile environment your tests run in, including custom vendor capabilities and special use cases. ### cloudservices Run WebdriverIO tests on Sauce Labs, BrowserStack, TestingBot, TestMu AI (formerly LambdaTest), Perfecto and other cloud providers. - [Using Cloud Services](/docs/cloudservices.md): Run WebdriverIO tests on Sauce Labs, BrowserStack, TestingBot, TestMu AI (formerly LambdaTest), Perfecto and other cloud providers. ### component-testing Run unit and component tests in real browsers with the WebdriverIO browser runner, powered by Vite, including setup, test harness and debugging. - [Component Testing](/docs/component-testing.md): Run unit and component tests in real browsers with the WebdriverIO browser runner, powered by Vite, including setup, test harness and debugging. - [Coverage](/docs/component-testing/coverage.md): Collect code coverage for component tests with the browser runner, which instruments your code with istanbul through Vite. - [Lit](/docs/component-testing/lit.md): Set up the WebdriverIO browser runner for Lit web components and write tests that query elements inside nested shadow roots. - [Mocking](/docs/component-testing/mocking.md): Mock functions, modules and network requests in browser runner component tests with fn, spyOn and mock from @wdio/browser-runner. - [Preact](/docs/component-testing/preact.md): Set up the WebdriverIO browser runner for a Preact project with the preact preset and write component tests with Testing Library. - [React](/docs/component-testing/react.md): Set up the WebdriverIO browser runner for a React project with the react preset and write component tests with Testing Library. - [SolidJS](/docs/component-testing/solid.md): Set up the WebdriverIO browser runner for a SolidJS project with the solid preset and write component tests that render into the page. - [Stencil](/docs/component-testing/stencil.md): Set up the WebdriverIO browser runner for Stencil components, render them with the render helper and wait for element updates. - [Svelte](/docs/component-testing/svelte.md): Set up the WebdriverIO browser runner for a Svelte project with the svelte preset and write component tests with Testing Library. - [Vue.js](/docs/component-testing/vue.md): Set up the WebdriverIO browser runner for Vue.js, write component tests with Testing Library and test async components and Nuxt apps. ### concise-reporter A concise reporter for WebdriverIO - [Concise Reporter](/docs/concise-reporter.md): A concise reporter for WebdriverIO ### configuration Look up every configuration option for WebDriver, standalone WebdriverIO and the WDIO testrunner, including all testrunner hooks. - [Configuration](/docs/configuration.md): Look up every configuration option for WebDriver, standalone WebdriverIO and the WDIO testrunner, including all testrunner hooks. ### configurationfile Browse an annotated example wdio.conf.js that lists every supported testrunner option, capability and hook with explanations. - [Configuration File](/docs/configurationfile.md): Browse an annotated example wdio.conf.js that lists every supported testrunner option, capability and hook with explanations. ### contribute You like WebdriverIO and want to help making it better? Awesome! We are working to make this process as easy and transparent as possible. We might be not quite there yet but this guide will help you to ramp you up as a contributor and give you everything you need to make your first contribution. If there is any information missing that prevents you from sending in a pull request, please let us know. We treat these kind of issues like actual bugs. - [Contribute](/docs/contribute.md): You like WebdriverIO and want to help making it better? Awesome! We are working to make this process as easy and transparent as possible. We might be not quite there yet but this guide will help you to ramp you up as a contributor and give you everything you need to make your first contribution. If there is any information missing that prevents you from sending in a pull request, please let us know. We treat these kind of issues like actual bugs. ### cucumberjs-json-reporter A WebdriverIO reporter that creates CucumberJS JSON files - [CucumberJS JSON Reporter](/docs/cucumberjs-json-reporter.md): A WebdriverIO reporter that creates CucumberJS JSON files ### customcommands Add your own browser and element commands with addCommand, overwrite existing commands and extend the TypeScript type definitions. - [Custom Commands](/docs/customcommands.md): Add your own browser and element commands with addCommand, overwrite existing commands and extend the TypeScript type definitions. ### custommatchers Register custom browser and element matchers with expect.extend and add TypeScript types for them. - [Custom Matchers](/docs/custommatchers.md): Register custom browser and element matchers with expect.extend and add TypeScript types for them. ### customreporter Build a custom reporter for the WDIO testrunner on top of @wdio/reporter, handle runner events and publish it on NPM. - [Custom Reporter](/docs/customreporter.md): Build a custom reporter for the WDIO testrunner on top of @wdio/reporter, handle runner events and publish it on NPM. ### customservices Write a custom launcher or worker service for the WDIO testrunner using testrunner hooks, handle service errors and publish it on NPM. - [Custom Services](/docs/customservices.md): Write a custom launcher or worker service for the WDIO testrunner using testrunner hooks, handle service errors and publish it on NPM. ### debugging Debug WebdriverIO tests with browser.debug, VS Code or WebStorm breakpoints, strategies for flaky tests, and CPU and heap profiling. - [Debugging](/docs/debugging.md): Debug WebdriverIO tests with browser.debug, VS Code or WebStorm breakpoints, strategies for flaky tests, and CPU and heap profiling. ### desktop-testing - [Dioxus](/docs/desktop-testing/dioxus.md): Test Dioxus desktop apps on Windows, macOS and Linux with the WebdriverIO Dioxus service, using the setup wizard or a manual configuration. - [API Reference](/docs/desktop-testing/dioxus/api.md): Complete API reference for @wdio/dioxus-service. - [Browser Mode](/docs/desktop-testing/dioxus/browser-mode.md): Browser mode lets you test your Dioxus frontend UI in plain Chrome against a running dev server — no Dioxus binary, no driver. The Dioxus invoke API is intercepted at the JavaScript boundary in the renderer, so you can mock individual commands and assert on call arguments just like in native mode. - [Coexistence](/docs/desktop-testing/dioxus/coexistence.md): This guide explains how to run @wdio/dioxus-service alongside @wdio/tauri-service and @wdio/electron-service in the same monorepo. - [Configuration](/docs/desktop-testing/dioxus/configuration.md): Complete guide to configuring @wdio/dioxus-service in your WebdriverIO setup. - [Deeplink Testing](/docs/desktop-testing/dioxus/deeplink-testing.md): The service provides the ability to test custom protocol handlers and deeplinks in your Dioxus application using the browser.dioxus.triggerDeeplink() method. - [Edge WebDriver on Windows](/docs/desktop-testing/dioxus/edge-webdriver-windows.md): Overview - [Log Forwarding](/docs/desktop-testing/dioxus/log-forwarding.md): Capture and forward logs from your Dioxus application to WebdriverIO's logger system. - [Platform Support](/docs/desktop-testing/dioxus/platform-support.md): Complete guide to platform-specific requirements, limitations, and driver setup for Dioxus testing. - [Bridge Setup](/docs/desktop-testing/dioxus/plugin-setup.md): Overview - [Quick Start](/docs/desktop-testing/dioxus/quick-start.md): Get up and running with WebdriverIO and Dioxus E2E testing in minutes. - [Troubleshooting](/docs/desktop-testing/dioxus/troubleshooting.md): Solutions for common issues when testing Dioxus applications with WebdriverIO. - [Usage Examples](/docs/desktop-testing/dioxus/usage-examples.md): Practical examples for testing Dioxus applications with WebdriverIO. - [Electron](/docs/desktop-testing/electron.md): Test Electron apps with the WebdriverIO Electron service, which sets up Chromedriver, detects your app binary and lets you mock Electron APIs. - [Accessing Electron APIs](/docs/desktop-testing/electron/api.md): This guide covers how to work with Electron APIs in your tests, including accessing APIs from the main process and mocking them for testing. - [API Reference](/docs/desktop-testing/electron/api-reference.md): This document provides a complete reference for all browser.electron.* methods and exported utility functions provided by the service. - [Common Issues](/docs/desktop-testing/electron/common-issues.md): These are some common issues which others have encountered whilst using the service. For debugging tools and features, see the Debugging guide. - [Configuration](/docs/desktop-testing/electron/configuration.md): This document covers all configuration options for the WDIO Electron Service, including service options and Chromedriver configuration. - [Debugging](/docs/desktop-testing/electron/debugging.md): This guide covers the debugging tools and features available in the Electron service to help you gain visibility into your application's behavior during tests. - [Deeplink Testing](/docs/desktop-testing/electron/deeplink-testing.md): The service provides the ability to test custom protocol handlers and deeplinks in your Electron application using the browser.electron.triggerDeeplink() method. This feature automatically handles platform-specific differences, particularly on Windows where deeplinks would normally launch a new instance instead of reaching the test instance. - [Standalone Mode](/docs/desktop-testing/electron/standalone.md): You can also use the service without the WDIO testrunner, e.g. in a normal Node.js script. - [Window Management](/docs/desktop-testing/electron/window-management.md): The service automatically tracks the active Electron BrowserWindow and ensures WebdriverIO commands target it. You can write tests against your app without manually shuffling window handles when the renderer changes (for example, splash screen → main window). - [MacOS](/docs/desktop-testing/macos.md): Automate native macOS applications with WebdriverIO using Appium and the Mac2 driver, starting from the project setup wizard. - [Tauri](/docs/desktop-testing/tauri.md): Test Tauri desktop apps on Windows, macOS and Linux with the WebdriverIO Tauri service, using the setup wizard or a manual configuration. - [API Reference](/docs/desktop-testing/tauri/api.md): Complete API reference for @wdio/tauri-service. - [Configuration](/docs/desktop-testing/tauri/configuration.md): Complete guide to configuring @wdio/tauri-service in your WebdriverIO setup. - [CrabNebula Setup](/docs/desktop-testing/tauri/crabnebula-setup.md): This guide walks you through setting up CrabNebula's tauri-driver for cross-platform Tauri testing. - [Deeplink Testing](/docs/desktop-testing/tauri/deeplink-testing.md): The service provides the ability to test custom protocol handlers and deeplinks in your Tauri application using the browser.tauri.triggerDeeplink() method. - [Edge WebDriver on Windows](/docs/desktop-testing/tauri/edge-webdriver-windows.md): Overview - [Log Forwarding](/docs/desktop-testing/tauri/log-forwarding.md): Capture and forward logs from your Tauri application to WebDriverIO's logger system. - [Platform Support](/docs/desktop-testing/tauri/platform-support.md): Complete guide to platform-specific requirements, limitations, and WebDriver setup for Tauri testing. - [Plugin Setup](/docs/desktop-testing/tauri/plugin-setup.md): Overview - [Quick Start](/docs/desktop-testing/tauri/quick-start.md): Get up and running with WebdriverIO and Tauri E2E testing in minutes. - [Troubleshooting](/docs/desktop-testing/tauri/troubleshooting.md): Solutions for common issues when testing Tauri applications with WebdriverIO. - [Usage Examples](/docs/desktop-testing/tauri/usage-examples.md): Practical examples for testing Tauri applications with WebdriverIO. - [Windows](/docs/desktop-testing/windows.md): Check the current state of automating native Windows applications with WebdriverIO and why no stable driver is available yet. ### devtools Visualize, control and inspect test runs in a browser-based debugging UI that works with WebdriverIO, Nightwatch.js and Selenium WebDriver. - [DevTools](/docs/devtools.md): Visualize, control and inspect test runs in a browser-based debugging UI that works with WebdriverIO, Nightwatch.js and Selenium WebDriver. - [Allure Integration](/docs/devtools/allure.md): Attach DevTools trace-mode artifacts such as trace zips, screenshots and videos to your Allure report automatically. - [Cross-Framework Support](/docs/devtools/cross-framework.md): Compare how completely DevTools trace mode captures WebdriverIO, Selenium and Nightwatch runs, and which gaps each adapter has. - [The Dashboard](/docs/devtools/dashboard.md): Watch test runs live in the DevTools dashboard, rerun single tests or suites, and configure the dashboard window and backend. - [Getting Started](/docs/devtools/getting-started.md): Install WebdriverIO DevTools and run your first test in live mode or trace mode to replay the DOM, screenshots, network and console output. - [Trace Mode Limitations](/docs/devtools/limitations.md): Review what DevTools trace mode deliberately does not capture and the known limitations across the WebdriverIO, Selenium and Nightwatch adapters. - [Mobile Testing](/docs/devtools/mobile.md): Capture Appium sessions (mobile browser, native and hybrid apps) in DevTools live and trace mode, and run the per-adapter mobile examples. - [Nightwatch DevTools](/docs/devtools/nightwatch.md): Add the DevTools debugging UI to a Nightwatch test suite without changing tests, and configure screencasts, BiDi capture and trace mode. - [Configuration Reference](/docs/devtools/reference.md): Look up every DevTools option for live mode and trace mode across the WebdriverIO, Selenium and Nightwatch adapters, with defaults. - [Selenium DevTools](/docs/devtools/selenium.md): Add the DevTools debugging UI to Selenium WebDriver tests in Node.js or Python with any test runner, and enable trace mode. - [Trace Player](/docs/devtools/trace-player.md): Open trace-mode artifacts in the show-trace player for offline replay and review, or load them into other trace viewers. - [WebDriverIO DevTools](/docs/devtools/wdio.md): Install and configure the WebdriverIO DevTools service to debug tests with DOM replay, screenshots, network and console capture and screencasts. - [Console Logs](/docs/devtools/wdio/console-logs.md): Capture and inspect browser console messages and WebdriverIO framework logs recorded by DevTools during test execution. - [Interactive Test Rerunning & Visualization](/docs/devtools/wdio/interactive-test-rerunning.md): Watch tests run with live browser previews and per-command screenshots, then rerun single tests or suites from the DevTools UI. - [Metadata](/docs/devtools/wdio/metadata.md): Inspect the capabilities, environment and timing of each browser session in the DevTools Metadata tab to diagnose environment-specific failures. - [Multi-Framework Support](/docs/devtools/wdio/multi-framework-support.md): Use the DevTools service with Mocha, Jasmine or Cucumber without framework-specific configuration. - [Network Logs](/docs/devtools/wdio/network-logs.md): Inspect every HTTP request and response captured by DevTools during a test to debug API calls, payloads and slow requests. - [Preserve & Rerun (Compare)](/docs/devtools/wdio/preserve-and-rerun.md): Snapshot a failing run and rerun the test in one click with Preserve & Rerun, then compare both runs to find what changed. - [Session Screencast](/docs/devtools/wdio/screencast.md): Record browser sessions as .webm videos with DevTools screencast, configure capture options and find the output files. - [TestLens](/docs/devtools/wdio/testlens.md): Jump from a test or command in the DevTools UI straight to its source line, in the Source tab or in VS Code, with TestLens. - [Trace Mode](/docs/devtools/wdio/trace-mode.md): Capture headless trace artifacts with DevTools trace mode and configure format, granularity, retention, screenshots, video and assertions. ### docker Run your WebdriverIO test suite inside a Docker container with a preinstalled browser for consistent results across machines. - [Docker](/docs/docker.md): Run your WebdriverIO test suite inside a Docker container with a preinstalled browser for consistent results across machines. ### dot-reporter A WebdriverIO plugin to report in dot style - [Dot Reporter](/docs/dot-reporter.md): A WebdriverIO plugin to report in dot style ### driverbinaries Let WebdriverIO download and manage browser drivers automatically, or set up Chromedriver, Geckodriver, Edgedriver and Safaridriver manually. - [Driver Binaries](/docs/driverbinaries.md): Let WebdriverIO download and manage browser drivers automatically, or set up Chromedriver, Geckodriver, Edgedriver and Safaridriver manually. ### ecosystem Directory of all official and community WebdriverIO services, reporters and tools, with the package to install for each. - [Ecosystem](/docs/ecosystem.md): Directory of all official and community WebdriverIO services, reporters and tools, with the package to install for each. ### emulation Emulate geolocation, media features, user agent, network, locale, timezone, screen and devices with the emulate command. - [Emulation](/docs/emulation.md): Emulate geolocation, media features, user agent, network, locale, timezone, screen and devices with the emulate command. ### enterprise Get commercial support and maintenance for WebdriverIO and other open source dependencies through the Tidelift Subscription. - [WebdriverIO for Enterprise](/docs/enterprise.md): Get commercial support and maintenance for WebdriverIO and other open source dependencies through the Tidelift Subscription. ### extension-testing - [VS Code Extension Testing](/docs/extension-testing/vscode-extensions.md): Test VS Code extensions end to end in the desktop IDE or as web extensions with WebdriverIO and the VS Code service. - [Web Extension Testing](/docs/extension-testing/web-extensions.md): Load a web extension into Chrome or Firefox for a WebdriverIO session, including a mid-session BiDi install and uninstall. ### firefox-profile-service WebdriverIO service that lets you define your Firefox profile in your wdio.conf.js - [Firefox Profile Service](/docs/firefox-profile-service.md): WebdriverIO service that lets you define your Firefox profile in your wdio.conf.js ### flowcharts - [Create worker process](/docs/flowcharts/createlocalworkerprocess.md): Follow a flowchart of how the WebdriverIO local runner creates a worker process to run a spec file. - [High level overview](/docs/flowcharts/highleveloverview.md): See a flowchart of how the WebdriverIO ecosystem and its core packages interact during a test run. - [Test Execution](/docs/flowcharts/testexecution.md): Follow a flowchart of the test execution process and how @wdio/runner interacts with the other WebdriverIO packages. - [Type generation](/docs/flowcharts/typegeneration.md): See how protocol specs are turned into TypeScript types, typings tests and API docs, and which source files to edit before regenerating. - [WDIO Commands](/docs/flowcharts/wdiocommands.md): Follow flowcharts of how the @wdio/cli run, repl, install and config commands parse arguments and execute. ### flutter-testing - [Base Appium Configuration](/docs/flutter-testing/base-appium-configuration.md): Install the Appium service and Flutter finder package and configure the base Appium setup for testing Flutter apps with WebdriverIO. - [Introduction](/docs/flutter-testing/introduction.md): Get an overview of end-to-end testing of Flutter apps on Android and iOS with WebdriverIO, Appium and the Appium Flutter Driver. - [Preparing the Flutter App](/docs/flutter-testing/preparing-flutter-application.md): Enable the flutter_driver extension in a Flutter app and produce a test build so WebdriverIO and Appium can interact with its widgets. - [Setting up WebdriverIO in your environment](/docs/flutter-testing/setting-up-webdriverio.md): Configure wdio.conf.ts and Appium capabilities to start a Flutter app with the Appium Flutter Driver on Android and iOS. - [Writing Tests](/docs/flutter-testing/writing-tests.md): Write WebdriverIO tests for Flutter apps by switching to the Flutter context and interacting with widgets through the flutter_driver extension. ### frameworks Configure Mocha, Jasmine, Cucumber.js or Vitest as the test framework for the WDIO testrunner, or integrate third-party frameworks like Serenity/JS. - [Frameworks](/docs/frameworks.md): Configure Mocha, Jasmine, Cucumber.js or Vitest as the test framework for the WDIO testrunner, or integrate third-party frameworks like Serenity/JS. ### gettingstarted Create a WebdriverIO project with npm init wdio@latest, run your first test and find the next guide for your platform. - [Getting Started](/docs/gettingstarted.md): Create a WebdriverIO project with npm init wdio@latest, run your first test and find the next guide for your platform. ### githubactions Run your WebdriverIO tests on GitHub Actions by adding a workflow file to your repository. - [Github Actions](/docs/githubactions.md): Run your WebdriverIO tests on GitHub Actions by adding a workflow file to your repository. ### gmangiapelo-wdio-azure-devops-service @gmangiapelo/wdio-azure-devops-service is a 3rd party package, for more information please see GitHub | npm - [Azure DevOps Test Plans Service](/docs/gmangiapelo-wdio-azure-devops-service.md): @gmangiapelo/wdio-azure-devops-service is a 3rd party package, for more information please see GitHub | npm ### headless-and-display-servers Run headed browsers and desktop apps on Linux CI and in containers with the Weston or Xvfb virtual display that the testrunner starts, including its options, CI recipes and troubleshooting. - [Headless & Display Servers](/docs/headless-and-display-servers.md): Run headed browsers and desktop apps on Linux CI and in containers with the Weston or Xvfb virtual display that the testrunner starts, including its options, CI recipes and troubleshooting. ### html-reporter A WebdriverIO reporter that creates an HTML report - [HTML Reporter](/docs/html-reporter.md): A WebdriverIO reporter that creates an HTML report ### jenkins Run WebdriverIO tests in Jenkins and publish JUnit reporter results to debug failures and track test history. - [Jenkins](/docs/jenkins.md): Run WebdriverIO tests in Jenkins and publish JUnit reporter results to debug failures and track test history. ### json-reporter A WebdriverIO plugin to report results in json format. - [JSON Reporter](/docs/json-reporter.md): A WebdriverIO plugin to report results in json format. ### junit-reporter A WebdriverIO reporter that creates Jenkins compatible XML based JUnit reports - [Junit Reporter](/docs/junit-reporter.md): A WebdriverIO reporter that creates Jenkins compatible XML based JUnit reports ### lighthouse-service A WebdriverIO service that allows you to run Chrome DevTools commands in your tests - [Lighthouse Service](/docs/lighthouse-service.md): A WebdriverIO service that allows you to run Chrome DevTools commands in your tests ### mcp Let AI assistants automate browsers and mobile apps through the WebdriverIO MCP server, including installation, usage with Claude and available tools. - [MCP (Model Context Protocol)](/docs/mcp.md): Let AI assistants automate browsers and mobile apps through the WebdriverIO MCP server, including installation, usage with Claude and available tools. - [Cloud Providers](/docs/mcp/cloud-providers.md): Run WebdriverIO MCP browser and mobile sessions on cloud device farms, including credentials, app uploads, tunnels and reporting. - [Configuration](/docs/mcp/configuration.md): Configure the WebdriverIO MCP server, including session, browser, mobile, cloud provider, element detection and Appium options. - [FAQ](/docs/mcp/faq.md): Find answers to common questions about installing, using and troubleshooting the WebdriverIO MCP server for browser and mobile automation. - [Resources](/docs/mcp/resources.md): Read live session state, session history and cloud provider setup details through the read-only wdio:// resources of the WebdriverIO MCP server. - [Selectors](/docs/mcp/selectors.md): Choose selectors to locate elements on web pages and mobile apps when automating with the WebdriverIO MCP server. - [Tools](/docs/mcp/tools.md): Look up the tools exposed by the WebdriverIO MCP server for sessions, navigation, element interaction, screenshots, gestures and app lifecycle. - [Transport](/docs/mcp/transport.md): Run the WebdriverIO MCP server over the default stdio transport or over Streamable HTTP, and pick the right mode for your client. ### mocksandspies Mock network requests and responses in your tests with browser.mock, abort requests and inspect calls with spies. - [Request Mocks and Spies](/docs/mocksandspies.md): Mock network requests and responses in your tests with browser.mock, abort requests and inspect calls with spies. ### multiremote Control multiple browser or device sessions from a single test with multi-remote, in standalone mode or with the WDIO testrunner. - [Multi-remote](/docs/multiremote.md): Control multiple browser or device sessions from a single test with multi-remote, in standalone mode or with the WDIO testrunner. ### ocr-testing - [CLI Wizard](/docs/ocr-testing/cli-wizard.md): Check which text the OCR service can find in an image without running a test by using the OCR CLI wizard. - [Getting Started](/docs/ocr-testing/getting-started.md): Install and configure @wdio/ocr-service, set up TypeScript support and tune contrast, image folder and language options. - [Test execution time](/docs/ocr-testing/more-test-optimization.md): Speed up OCR-based tests by cropping the search area of the screen and using a local Tesseract installation. - [ocrClickOnText](/docs/ocr-testing/ocr-click-on-text.md): Click on an element by its visible text with ocrClickOnText, which finds the text on screen with OCR and fuzzy matching. - [Frequently Asked Questions](/docs/ocr-testing/ocr-faq.md): Find answers to common questions about slow OCR tests, text that is not found and combining OCR commands with regular selectors. - [ocrGetElementPositionByText](/docs/ocr-testing/ocr-get-element-position-by-text.md): Get the on-screen position of a text with ocrGetElementPositionByText, using OCR and fuzzy matching to find it. - [ocrGetText](/docs/ocr-testing/ocr-get-text.md): Read the text shown on the screen or in a specific area with ocrGetText from the OCR service. - [ocrSetValue](/docs/ocr-testing/ocr-set-value.md): Type into an input field located by its visible text with ocrSetValue, which finds the field with OCR and fuzzy matching. - [OCR Testing](/docs/ocr-testing/ocr-testing.md): Locate and interact with elements by their visible text on web and mobile apps with the OCR service when regular selectors fall short. - [ocrWaitForTextDisplayed](/docs/ocr-testing/ocr-wait-for-text-displayed.md): Wait until a specific text is displayed on the screen with ocrWaitForTextDisplayed from the OCR service. ### organizingsuites Organize a growing test suite by sharing config files, grouping specs into suites, running specs sequentially and including or excluding tests. - [Organizing Test Suite](/docs/organizingsuites.md): Organize a growing test suite by sharing config files, grouping specs into suites, running specs sequentially and including or excluding tests. ### pageobjects Structure your tests with the page object pattern by moving selectors and page-specific actions into reusable page classes, and pass them to Vitest tests as fixtures. - [Page Object Pattern](/docs/pageobjects.md): Structure your tests with the page object pattern by moving selectors and page-specific actions into reusable page classes, and pass them to Vitest tests as fixtures. ### parallel-tests Run the Mocha tests or Cucumber scenarios of one spec file at the same time, each in its own WebDriver BiDi browsing context, with mochaOpts.parallelMode or cucumberOpts.parallelMode, a form of browser pooling similar to Playwright's fullyParallel. - [Parallel Tests in a Spec File](/docs/parallel-tests.md): Run the Mocha tests or Cucumber scenarios of one spec file at the same time, each in its own WebDriver BiDi browsing context, with mochaOpts.parallelMode or cucumberOpts.parallelMode, a form of browser pooling similar to Playwright's fullyParallel. ### parameterize-tests Parameterize tests with loops and dynamic functions, environment variables, .env files or data from a CSV file. - [Parameterize Tests](/docs/parameterize-tests.md): Parameterize tests with loops and dynamic functions, environment variables, .env files or data from a CSV file. ### percy-overview Get an overview of visual testing for websites and native mobile apps with Percy and App Percy, and how Percy compares snapshots. - [Unlocking Percy - An Overview](/docs/percy-overview.md): Get an overview of visual testing for websites and native mobile apps with Percy and App Percy, and how Percy compares snapshots. ### platforms - [Extensions & Editors](/docs/platforms/apps-and-extensions.md): Load a browser extension or a VS Code extension into a WebdriverIO session and test it end to end. - [Desktop Apps](/docs/platforms/desktop.md): Pick the right WebdriverIO setup for native macOS apps and for Electron, Tauri and Dioxus apps on macOS, Windows and Linux, and run a first test. - [Mobile Apps](/docs/platforms/mobile.md): Set up and run WebdriverIO tests for native, hybrid and mobile web apps on Android and iOS emulators, simulators, real devices and device clouds. - [Web Browsers](/docs/platforms/web.md): Set up and run WebdriverIO end-to-end, component, visual and accessibility tests in Chrome, Firefox, Microsoft Edge and Safari. ### protractor-migration Migrate a Protractor test suite to WebdriverIO step by step, including dependencies, configuration file and test files, with the help of a codemod. - [From Protractor](/docs/protractor-migration.md): Migrate a Protractor test suite to WebdriverIO step by step, including dependencies, configuration file and test files, with the help of a codemod. ### proxy Route requests through a proxy, either between your tests and the driver or between the browser and the internet. - [Proxy Setup](/docs/proxy.md): Route requests through a proxy, either between your tests and the driver or between the browser and the internet. ### qajonatasmartins-wdio-google-chat-service @qajonatasmartins/wdio-google-chat-service is a 3rd party package, for more information please see GitHub | npm - [Google Chat Service](/docs/qajonatasmartins-wdio-google-chat-service.md): @qajonatasmartins/wdio-google-chat-service is a 3rd party package, for more information please see GitHub | npm ### record Record user flows with the Chrome DevTools Recorder and export them as WebdriverIO tests. - [Record Tests](/docs/record.md): Record user flows with the Chrome DevTools Recorder and export them as WebdriverIO tests. ### repl Use the WebdriverIO REPL to try out commands and debug tests interactively from the command line or from within a running test. - [REPL interface](/docs/repl.md): Use the WebdriverIO REPL to try out commands and debug tests interactively from the command line or from within a running test. ### retry Retry flaky tests in Mocha, Jasmine or Cucumber, rerun whole spec files and run a specific test multiple times to detect flakiness. - [Retry Flaky Tests](/docs/retry.md): Retry flaky tests in Mocha, Jasmine or Cucumber, rerun whole spec files and run a specific test multiple times to detect flakiness. ### runner Choose between the local runner and the browser runner, and configure browser runner options such as presets, Vite config and coverage. - [Runner](/docs/runner.md): Choose between the local runner and the browser runner, and configure browser runner options such as presets, Vite config and coverage. ### sap_oss-wdio-qmate-service @saposs/wdio-qmate-service is a 3rd party package, for more information please see GitHub | npm - [Qmate Service](/docs/sap_oss-wdio-qmate-service.md): @saposs/wdio-qmate-service is a 3rd party package, for more information please see GitHub | npm ### sauce-service WebdriverIO service that provides a better integration into Sauce Labs - [Sauce Service](/docs/sauce-service.md): WebdriverIO service that provides a better integration into Sauce Labs ### security Protect sensitive test data by following security best practices and masking passwords and keys in logs and reports. - [Security](/docs/security.md): Protect sensitive test data by following security best practices and masking passwords and keys in logs and reports. ### selectors Find elements with CSS, text, XPath, accessibility name, ARIA role and other selector strategies, and learn which ones are most resilient. - [Selectors](/docs/selectors.md): Find elements with CSS, text, XPath, accessibility name, ARIA role and other selector strategies, and learn which ones are most resilient. ### seleniumgrid Connect WebdriverIO tests to an existing Selenium Grid by setting the protocol, hostname, port and path in your configuration. - [Selenium Grid](/docs/seleniumgrid.md): Connect WebdriverIO tests to an existing Selenium Grid by setting the protocol, hostname, port and path in your configuration. ### serenity-js-html-reporter @serenity-js/html-reporter is a 3rd party package, for more information please see GitHub | npm - [Serenity/JS HTML Reporter](/docs/serenity-js-html-reporter.md): @serenity-js/html-reporter is a 3rd party package, for more information please see GitHub | npm ### session Drive a browser, mobile app or desktop app from the shell with short wdio session commands, then export the steps as a test. - [wdio session](/docs/session.md): Drive a browser, mobile app or desktop app from the shell with short wdio session commands, then export the steps as a test. - [Debug a test with a session](/docs/session/debug.md): Pause a failing WebdriverIO run and inspect it with wdio session, then resume or close it. - [Run code in a session](/docs/session/exec.md): Run WebdriverIO code and assertions in a live wdio session with exec. - [Export a session as a test](/docs/session/export.md): Turn the steps you ran in wdio session into a spec, page objects and custom commands. - [Snapshots and refs](/docs/session/snapshots.md): Read the page with wdio session snapshot, then act on the refs it prints. - [Session targets](/docs/session/targets.md): Open a browser, mobile app, desktop app, Electron app or a cloud device with wdio session. ### session-commands Every wdio session action and flag, from open through doctor and skill. - [wdio session commands](/docs/session-commands.md): Every wdio session action and flag, from open through doctor and skill. ### setuptypes Compare the ways to use WebdriverIO, from raw protocol bindings to standalone mode and the WDIO testrunner, and pick the right one. - [Setup Types](/docs/setuptypes.md): Compare the ways to use WebdriverIO, from raw protocol bindings to standalone mode and the WDIO testrunner, and pick the right one. ### sharding Split your test suite across multiple machines with the --shard option to run tests faster, for example on GitHub Actions. - [Sharding](/docs/sharding.md): Split your test suite across multiple machines with the --shard option to run tests faster, for example on GitHub Actions. ### shared-store-service A WebdriverIO service to exchange data across processes - [Shared Store Service](/docs/shared-store-service.md): A WebdriverIO service to exchange data across processes ### snapshot Assert objects, DOM structures and command results with snapshot and inline snapshot tests, and compare visual snapshots. - [Snapshot](/docs/snapshot.md): Assert objects, DOM structures and command results with snapshot and inline snapshot tests, and compare visual snapshots. ### spec-reporter A WebdriverIO plugin to report in spec style - [Spec Reporter](/docs/spec-reporter.md): A WebdriverIO plugin to report in spec style ### sponsor Support WebdriverIO financially as a business or individual through GitHub Sponsors, Tidelift or OpenCollective, and see the tier benefits. - [Become a WebdriverIO Sponsor](/docs/sponsor.md): Support WebdriverIO financially as a business or individual through GitHub Sponsors, Tidelift or OpenCollective, and see the tier benefits. ### static-server-service A WebdriverIO service that can serve your static websites - [Static Server Service](/docs/static-server-service.md): A WebdriverIO service that can serve your static websites ### sumologic-reporter A WebdriverIO reporter that sends test results to Sumologic for data analyses - [Sumologic Reporter](/docs/sumologic-reporter.md): A WebdriverIO reporter that sends test results to Sumologic for data analyses ### testingbot-service A WebdriverIO service that provides a better integration into TestingBot - [Testingbot Service](/docs/testingbot-service.md): A WebdriverIO service that provides a better integration into TestingBot ### testplanit-wdio-reporter @testplanit/wdio-reporter is a 3rd party package, for more information please see GitHub | npm - [TestPlanIt Reporter Reporter](/docs/testplanit-wdio-reporter.md): @testplanit/wdio-reporter is a 3rd party package, for more information please see GitHub | npm ### testrunner Install the WDIO testrunner from @wdio/cli and use its config, run, install, repl and session commands to set up and run test suites. - [Testrunner](/docs/testrunner.md): Install the WDIO testrunner from @wdio/cli and use its config, run, install, repl and session commands to set up and run test suites. ### timeouts Configure WebDriver session timeouts, WebdriverIO waitfor timeouts and test framework timeouts to keep tests reliable. - [Timeouts](/docs/timeouts.md): Configure WebDriver session timeouts, WebdriverIO waitfor timeouts and test framework timeouts to keep tests reliable. ### tvlabs-wdio-service @tvlabs/wdio-service is a 3rd party package, for more information please see GitHub | npm - [TV Labs Service](/docs/tvlabs-wdio-service.md): @tvlabs/wdio-service is a 3rd party package, for more information please see GitHub | npm ### typescript Write WebdriverIO tests in TypeScript with tsx, set up tsconfig.json and add type definitions for frameworks, services and custom commands. - [TypeScript Setup](/docs/typescript.md): Write WebdriverIO tests in TypeScript with tsx, set up tsconfig.json and add type definitions for frameworks, services and custom commands. ### v10-migration Update a WebdriverIO v9 project to v10, including every breaking change and a coding-agent skill that applies this guide. - [From v9 to v10](/docs/v10-migration.md): Update a WebdriverIO v9 project to v10, including every breaking change and a coding-agent skill that applies this guide. ### v6-migration Upgrade a WebdriverIO project from v5 to v6 by updating dependencies, transforming the config file and updating specs and page objects. - [From v5 to v6](/docs/v6-migration.md): Upgrade a WebdriverIO project from v5 to v6 by updating dependencies, transforming the config file and updating specs and page objects. ### v7-migration Upgrade a WebdriverIO project from v6 to v7 by updating dependencies, transforming the config file and updating Cucumber step definitions. - [From v6 to v7](/docs/v7-migration.md): Upgrade a WebdriverIO project from v6 to v7 by updating dependencies, transforming the config file and updating Cucumber step definitions. ### video-reporter A WebdriverIO reporter that makes videos of failed tests and has optional Allure integration - [Video Reporter](/docs/video-reporter.md): A WebdriverIO reporter that makes videos of failed tests and has optional Allure integration ### visual-testing Compare screenshots of screens, elements or full pages against baselines with the @wdio/visual-service, including installation and usage. - [Visual Testing](/docs/visual-testing.md): Compare screenshots of screens, elements or full pages against baselines with the @wdio/visual-service, including installation and usage. - [Elevate Your Visual Testing with Argos](/docs/visual-testing/argos.md): Send WebdriverIO screenshots to Argos to review grouped visual changes from pull requests, approve intended ones and catch regressions. - [Compare Options](/docs/visual-testing/compare-options.md): Tune how screenshots are compared with visual sensitivity, pixelmatch, mobile block-out and reporting options for the visual service. - [Key Considerations for Optimal Use](/docs/visual-testing/considerations.md): Understand the limits of image comparison, platform consistency, mismatch percentages and headless browsers before relying on visual tests. - [FAQ](/docs/visual-testing/faq.md): Find answers to common visual testing questions, such as updating baselines, fixing canvas installation errors and upgrading to v10. - [For Mobile Application](/docs/visual-testing/integrate-with-app-percy.md): Integrate WebdriverIO mobile app tests with BrowserStack App Percy for visual testing, starting with setting your PERCY_TOKEN. - [For Web Application](/docs/visual-testing/integrate-with-percy.md): Integrate WebdriverIO tests for web applications with BrowserStack Percy for visual testing, from creating a project to running builds. - [SmartUI](/docs/visual-testing/integrate-with-smartui.md): Add AI-powered visual regression testing to WebdriverIO tests with TestMu AI (formerly LambdaTest) SmartUI, including setup and options. - [Save Options](/docs/visual-testing/method-options.md): Set per-method save, compare and folder options for visual testing methods that override the service-level options. - [Methods](/docs/visual-testing/methods.md): Use the save and check methods of the visual service to capture screenshots and compare screens, elements and full pages against baselines. - [Default Options](/docs/visual-testing/service-options.md): Configure default options for the visual service, including screenshot capture, full-page screenshots, baselines, folders and reporting. - [Test Output](/docs/visual-testing/test-output.md): Understand the output and images produced by the save and check methods of the visual service, including layout testing and block-outs. - [Prerequisites](/docs/visual-testing/visual-reporter.md): Generate and browse the Visual Reporter to review visual test diffs from the JSON output of @wdio/visual-service, locally or in CI. - [Writing Tests](/docs/visual-testing/writing-tests.md): Write visual tests with Mocha, Jasmine or Cucumber that save screenshots or match them against baselines with custom matchers and check methods. ### watcher Rerun tests automatically when spec or application files change by running the WDIO testrunner with the --watch flag and filesToWatch. - [Watch Test Files](/docs/watcher.md): Rerun tests automatically when spec or application files change by running the WDIO testrunner with the --watch flag and filesToWatch. ### wdio-aws-device-farm-service wdio-aws-device-farm-service is a 3rd party package, for more information please see GitHub | npm - [AWS Device Farm Service](/docs/wdio-aws-device-farm-service.md): wdio-aws-device-farm-service is a 3rd party package, for more information please see GitHub | npm ### wdio-camera-service wdio-camera-service is a 3rd party package, for more information please see GitHub | npm - [Camera Service Service](/docs/wdio-camera-service.md): wdio-camera-service is a 3rd party package, for more information please see GitHub | npm ### wdio-cleanuptotal-service wdio-cleanuptotal-service is a 3rd party package, for more information please see GitHub | npm - [CleanupTotal Service](/docs/wdio-cleanuptotal-service.md): wdio-cleanuptotal-service is a 3rd party package, for more information please see GitHub | npm ### wdio-cucumber-viewport-logger-service wdio-cucumber-viewport-logger-service is a 3rd party package, for more information please see GitHub | npm - [Cucumber Viewport Logger Service](/docs/wdio-cucumber-viewport-logger-service.md): wdio-cucumber-viewport-logger-service is a 3rd party package, for more information please see GitHub | npm ### wdio-delta-reporter-service wdio-delta-reporter-service is a 3rd party package, for more information please see GitHub | npm - [Delta Reporter Reporter](/docs/wdio-delta-reporter-service.md): wdio-delta-reporter-service is a 3rd party package, for more information please see GitHub | npm ### wdio-devtools-service @wdio/devtools-service is a 3rd party package, for more information please see GitHub | npm - [DevTools (Test Debugging & Visualization) Service](/docs/wdio-devtools-service.md): @wdio/devtools-service is a 3rd party package, for more information please see GitHub | npm ### wdio-dioxus-service @wdio/dioxus-service is a 3rd party package, for more information please see GitHub | npm - [Dioxus Service](/docs/wdio-dioxus-service.md): @wdio/dioxus-service is a 3rd party package, for more information please see GitHub | npm ### wdio-docker-service wdio-docker-service is a 3rd party package, for more information please see GitHub | npm - [Docker Service](/docs/wdio-docker-service.md): wdio-docker-service is a 3rd party package, for more information please see GitHub | npm ### wdio-electron-service @wdio/electron-service is a 3rd party package, for more information please see GitHub | npm - [Electron Service](/docs/wdio-electron-service.md): @wdio/electron-service is a 3rd party package, for more information please see GitHub | npm ### wdio-eslinter-service wdio-eslinter-service is a 3rd party package, for more information please see GitHub | npm - [Auto-detect missing imports w/eslint Service](/docs/wdio-eslinter-service.md): wdio-eslinter-service is a 3rd party package, for more information please see GitHub | npm ### wdio-gmail-service wdio-gmail-service is a 3rd party package, for more information please see GitHub | npm - [Gmail Service](/docs/wdio-gmail-service.md): wdio-gmail-service is a 3rd party package, for more information please see GitHub | npm ### wdio-intercept-service wdio-intercept-service is a 3rd party package, for more information please see GitHub | npm - [Intercept Service](/docs/wdio-intercept-service.md): wdio-intercept-service is a 3rd party package, for more information please see GitHub | npm ### wdio-json-html-reporter wdio-json-html-reporter is a 3rd party package, for more information please see GitHub | npm - [JSON HTML Reporter Reporter](/docs/wdio-json-html-reporter.md): wdio-json-html-reporter is a 3rd party package, for more information please see GitHub | npm ### wdio-lambdatest-service wdio-lambdatest-service is a 3rd party package, for more information please see GitHub | npm - [TestMu AI (Formerly LambdaTest) Service](/docs/wdio-lambdatest-service.md): wdio-lambdatest-service is a 3rd party package, for more information please see GitHub | npm ### wdio-light-reporter wdio-light-reporter is a 3rd party package, for more information please see GitHub | npm - [Light Reporter Reporter](/docs/wdio-light-reporter.md): wdio-light-reporter is a 3rd party package, for more information please see GitHub | npm ### wdio-ng-apimock-service wdio-ng-apimock-service is a 3rd party package, for more information please see GitHub | npm - [Ng-apimock Service](/docs/wdio-ng-apimock-service.md): wdio-ng-apimock-service is a 3rd party package, for more information please see GitHub | npm ### wdio-novus-visual-regression-service wdio-novus-visual-regression-service is a 3rd party package, for more information please see GitHub | npm - [Novus Visual Regression Service](/docs/wdio-novus-visual-regression-service.md): wdio-novus-visual-regression-service is a 3rd party package, for more information please see GitHub | npm ### wdio-null-driver-service wdio-null-driver-service is a 3rd party package, for more information please see GitHub | npm - [Null Driver Service](/docs/wdio-null-driver-service.md): wdio-null-driver-service is a 3rd party package, for more information please see GitHub | npm ### wdio-nuxt-service wdio-nuxt-service is a 3rd party package, for more information please see GitHub | npm - [Nuxt Service Service](/docs/wdio-nuxt-service.md): wdio-nuxt-service is a 3rd party package, for more information please see GitHub | npm ### wdio-obsidian-service wdio-obsidian-service is a 3rd party package, for more information please see GitHub | npm - [Obsidian Plugin Testing Service](/docs/wdio-obsidian-service.md): wdio-obsidian-service is a 3rd party package, for more information please see GitHub | npm ### wdio-ocr-service @wdio/ocr-service is a 3rd party package, for more information please see GitHub | npm - [OCR Testing Service](/docs/wdio-ocr-service.md): @wdio/ocr-service is a 3rd party package, for more information please see GitHub | npm ### wdio-performancetotal-service wdio-performancetotal-service is a 3rd party package, for more information please see GitHub | npm - [PerformanceTotal Service](/docs/wdio-performancetotal-service.md): wdio-performancetotal-service is a 3rd party package, for more information please see GitHub | npm ### wdio-qunit-service wdio-qunit-service is a 3rd party package, for more information please see GitHub | npm - [QUnit Service](/docs/wdio-qunit-service.md): wdio-qunit-service is a 3rd party package, for more information please see GitHub | npm ### wdio-reportportal-reporter wdio-reportportal-reporter is a 3rd party package, for more information please see GitHub | npm - [Report Portal Reporter](/docs/wdio-reportportal-reporter.md): wdio-reportportal-reporter is a 3rd party package, for more information please see GitHub | npm ### wdio-reportportal-service wdio-reportportal-service is a 3rd party package, for more information please see GitHub | npm - [Report Portal Service](/docs/wdio-reportportal-service.md): wdio-reportportal-service is a 3rd party package, for more information please see GitHub | npm ### wdio-rerun-service wdio-rerun-service is a 3rd party package, for more information please see GitHub | npm - [Re-run Service](/docs/wdio-rerun-service.md): wdio-rerun-service is a 3rd party package, for more information please see GitHub | npm ### wdio-robonut-service wdio-robonut-service is a 3rd party package, for more information please see GitHub | npm - [Robonut Service](/docs/wdio-robonut-service.md): wdio-robonut-service is a 3rd party package, for more information please see GitHub | npm ### wdio-roku-service wdio-roku-service is a 3rd party package, for more information please see GitHub | npm - [Roku Service](/docs/wdio-roku-service.md): wdio-roku-service is a 3rd party package, for more information please see GitHub | npm ### wdio-slack-reporter wdio-slack-reporter is a 3rd party package, for more information please see GitHub | npm - [Slack Reporter Reporter](/docs/wdio-slack-reporter.md): wdio-slack-reporter is a 3rd party package, for more information please see GitHub | npm ### wdio-slack-service wdio-slack-service is a 3rd party package, for more information please see GitHub | npm - [Slack Service](/docs/wdio-slack-service.md): wdio-slack-service is a 3rd party package, for more information please see GitHub | npm ### wdio-tauri-service @wdio/tauri-service is a 3rd party package, for more information please see GitHub | npm - [Tauri Service](/docs/wdio-tauri-service.md): @wdio/tauri-service is a 3rd party package, for more information please see GitHub | npm ### wdio-teamcity-reporter wdio-teamcity-reporter is a 3rd party package, for more information please see GitHub | npm - [Teamcity Reporter Reporter](/docs/wdio-teamcity-reporter.md): wdio-teamcity-reporter is a 3rd party package, for more information please see GitHub | npm ### wdio-testrail-reporter @wdio/testrail-reporter is a 3rd party package, for more information please see GitHub | npm - [Testrail Reporter Reporter](/docs/wdio-testrail-reporter.md): @wdio/testrail-reporter is a 3rd party package, for more information please see GitHub | npm ### wdio-tesults-service wdio-tesults-service is a 3rd party package, for more information please see GitHub | npm - [Tesults Service](/docs/wdio-tesults-service.md): wdio-tesults-service is a 3rd party package, for more information please see GitHub | npm ### wdio-timeline-reporter wdio-timeline-reporter is a 3rd party package, for more information please see GitHub | npm - [Timeline Reporter](/docs/wdio-timeline-reporter.md): wdio-timeline-reporter is a 3rd party package, for more information please see GitHub | npm ### wdio-ui5-service wdio-ui5-service is a 3rd party package, for more information please see GitHub | npm - [UI5 Service](/docs/wdio-ui5-service.md): wdio-ui5-service is a 3rd party package, for more information please see GitHub | npm ### wdio-visual-service @wdio/visual-service is a 3rd party package, for more information please see GitHub | npm - [Image Comparison (Visual Regression Testing) Service](/docs/wdio-visual-service.md): @wdio/visual-service is a 3rd party package, for more information please see GitHub | npm ### wdio-vscode-service wdio-vscode-service is a 3rd party package, for more information please see GitHub | npm - [VSCode Extension Testing Service](/docs/wdio-vscode-service.md): wdio-vscode-service is a 3rd party package, for more information please see GitHub | npm ### wdio-wait-for wdio-wait-for is a 3rd party package, for more information please see GitHub | npm - [Library of useful expected conditions Service](/docs/wdio-wait-for.md): wdio-wait-for is a 3rd party package, for more information please see GitHub | npm ### wdio-winappdriver-service wdio-winappdriver-service is a 3rd party package, for more information please see GitHub | npm - [winappdriver Service](/docs/wdio-winappdriver-service.md): wdio-winappdriver-service is a 3rd party package, for more information please see GitHub | npm ### wdio-wiremock-service wdio-wiremock-service is a 3rd party package, for more information please see GitHub | npm - [WireMock Service](/docs/wdio-wiremock-service.md): wdio-wiremock-service is a 3rd party package, for more information please see GitHub | npm ### wdio-ywinappdriver-service wdio-ywinappdriver-service is a 3rd party package, for more information please see GitHub | npm - [ywinappdriver Service](/docs/wdio-ywinappdriver-service.md): wdio-ywinappdriver-service is a 3rd party package, for more information please see GitHub | npm ### wdio-zafira-listener-service wdio-zafira-listener-service is a 3rd party package, for more information please see GitHub | npm - [Zafira Listener Service](/docs/wdio-zafira-listener-service.md): wdio-zafira-listener-service is a 3rd party package, for more information please see GitHub | npm ### webdriver-mock-service A WebdriverIO service to stub all endpoints for internal testing purposes. - [Webdriver Mock Service](/docs/webdriver-mock-service.md): A WebdriverIO service to stub all endpoints for internal testing purposes. ### why-webdriverio What sets WebdriverIO apart from other test automation tools - one API for every platform, web standards, open governance and first-class support for coding agents. - [Why WebdriverIO?](/docs/why-webdriverio.md): What sets WebdriverIO apart from other test automation tools - one API for every platform, web standards, open governance and first-class support for coding agents. --- # Full Documentation Content # Donate If your company uses WebdriverIO and benefits from it, please ask your manager or your marketing team to support the project by donating to the collective. Support will allow the maintainers to dedicate more time for maintenance and new features for everyone. Please checkout our [OpenCollective page](https://opencollective.com/webdriverio) for further information on how to donate to the project. Thank you to everyone who will or has donated money to the collective and therefore has supported the project and everyone who contributed to it. It really means a lot ❤️ ## Expense Policies[​](#expense-policies "Direct link to Expense Policies") We want to be transparent in the way we accept expenses to the collective. Everyone should be eligible to participate and send in expenses for development on certain features. We also want to give back to the community by allowing us to expense event expenses. The following expense types may be eligible to be reimbursed from the collective: ### Event Expenses[​](#event-expenses "Direct link to Event Expenses") If you host an event that has a speaker talking about using WebdriverIO and it's features you can expense up to **$100**. Reimbursement requirements for event expenses include: * You or the event account must share the project on social media (𝕏, Facebook or LinkedIn) at least 3x * The event page must have the WebdriverIO logo and a link to the project page in your meetup description * You must use the funds for qualified event expenses such as food, beverage, room or equipment rental. * You must submit receipts with your reimbursement request. ### Development Expenses[​](#development-expenses "Direct link to Development Expenses") If you have done development work on any of the repositories within the GitHub WebdriverIO organisation you may reimburse up to **$1000** if the following requirements are met: * You must have submitted qualifying pull requests that have closed at least 10 issues that were labeled with [`Expensable 💸`](https://github.com/webdriverio/webdriverio/labels/Expensable%20%F0%9F%92%B8) * Every additional issue closed with that label can be expensed with $100 * You must submit links to all issues you’ve closed due to your pull requests * In order to close the ticket automatically, you must have one commit message with the Fix keyword. For example, Fix #1234 to close ticket #1234. * Pull Requests must be merged by someone from the [core team](https://github.com/webdriverio/webdriverio/blob/main/AUTHORS.md#tsc-technical-steering-committee). If there are several Pull Requests, the core team member either selects the most recent one or the best one - that’s up to them to decide what is best for the project. * You must claim an [`Expensable 💸`](https://github.com/webdriverio/webdriverio/labels/Expensable%20%F0%9F%92%B8) issue by commenting to the issue thread to ensure that no one else is working on the same issue. * Anyone contributing to WebdriverIO is eligible to expense their work if the implemented features or bug fixes are not objectives of a commercial job. ### Travel Expenses[​](#travel-expenses "Direct link to Travel Expenses") If you are a member of the [Technical Steering Committee team](https://github.com/webdriverio/webdriverio/blob/main/AUTHORS.md#tsc-technical-steering-committee) you are eligible to expense flights and hotel accommodations for travel to conferences or meetups as part of a speaking engagement on WebdriverIO, not paid by the event itself or a company. You may expense up to $500. Reimbursement requirements for travel expenses include: * You must send out a post from your main social media account (e.g. 𝕏, LinkedIn or personal blog) thanking all contributors of the collective after the event took place. * You must use the funds for qualified travel expenses such as ground or air transportation to the event and hotel accomodations. * You must submit receipts with your reimbursement request. --- # WebdriverIO Events The WebdriverIO community organizes events around the world. The project is completely community driven and we encourage and support everyone who likes to host and run WebdriverIO meetups and events. Loading... # Host your own WebdriverIO Event? You would like to host a WebdriverIO meetup? Awesome ❤️! We would love to support you and provide Pizza and drinks. Let's get in touch: please [raise an issue](https://github.com/webdriverio/webdriverio/issues/new?assignees=\&labels=Event+%F0%9F%93%85%2CNeeds+Triaging+%E2%8F%B3\&projects=\&template=event-proposal.yml\&title=%5B%F0%9F%93%85+Event+Suggestion%5D%3A+%3Ctitle%3E) in the WebdriverIO repository and we will take it from there. --- # Materials If you want to use WebdriverIO materials for your own workshops or events feel free to grab them directly from here. ## Workshops[​](#workshops "Direct link to Workshops") The WebdriverIO community gives workshops around the world. Feel free to use these materials to host your own. * [webdriverio/workshop](https://github.com/webdriverio/workshop) ## Assets[​](#assets "Direct link to Assets") If you create your own WebdriverIO content for education purposes, feel free to grab these assets to include in your materials. ### Roboter Logo[​](#roboter-logo "Direct link to Roboter Logo") ![Roboter Logo](/assets/images/robot-3677788dd63849c56aa5cb3f332b12d5.svg "Roboter Logo") ![Roboter Logo White](/assets/images/robot-white-efa2a168533bfa9b626ddaad0581bf43.svg "Roboter Logo White") ### Project Logo[​](#project-logo "Direct link to Project Logo") ![Roboter Logo](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNjRweCIgaGVpZ2h0PSI2NHB4IiB2aWV3Qm94PSIwIDAgNjQgNjQiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8dGl0bGU+TG9nbyBSZWd1bGFyPC90aXRsZT4KICAgIDxnIGlkPSJMb2dvLVJlZ3VsYXIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxyZWN0IGlkPSJSZWN0YW5nbGUiIGZpbGw9IiNFQTU5MDYiIHg9IjAiIHk9IjAiIHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgcng9IjUiPjwvcmVjdD4KICAgICAgICA8cGF0aCBkPSJNOCwxNiBMOCw0OCBMNiw0OCBMNiwxNiBMOCwxNiBaIE00MywxNiBDNTEuODM2NTU2LDE2IDU5LDIzLjE2MzQ0NCA1OSwzMiBDNTksNDAuODM2NTU2IDUxLjgzNjU1Niw0OCA0Myw0OCBDMzQuMTYzNDQ0LDQ4IDI3LDQwLjgzNjU1NiAyNywzMiBDMjcsMjMuMTYzNDQ0IDM0LjE2MzQ0NCwxNiA0MywxNiBaIE0yNywxNiBMMTQuMTA2LDQ3Ljk5OTIwNzggTDExLjk5OSw0Ny45OTkyMDc4IEwyNC44OTQsMTYgTDI3LDE2IFogTTQzLDE4IEMzNS4yNjgwMTM1LDE4IDI5LDI0LjI2ODAxMzUgMjksMzIgQzI5LDM5LjczMTk4NjUgMzUuMjY4MDEzNSw0NiA0Myw0NiBDNTAuNzMxOTg2NSw0NiA1NywzOS43MzE5ODY1IDU3LDMyIEM1NywyNC4yNjgwMTM1IDUwLjczMTk4NjUsMTggNDMsMTggWiIgaWQ9IkNvbWJpbmVkLVNoYXBlIiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+CiAgICA8L2c+Cjwvc3ZnPg== "Project Logo") --- # Office Hours Contributing to a big Open Source project can be hard. Especially if the codebase is large and requires a lot of context to understand what certain changes do. Then there is the possibility that tools or infrastructure is being used that are unknown. Nevertheless the project depends on your contributions and help to identify bugs and fix them. How can we overcome this hurdle? The WebdriverIO projects has introduced Open Office Hours that allow everyone to schedule individual 1:1 pairing sessions with the WebdriverIO contributors. This allows you to get started contributing to WebdriverIO easily with the help of people that know the code base well. We only ask you to pick [a task](https://github.com/webdriverio/webdriverio/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Afirst-timers-only) you would like to work on up-front so that the pairing partner can be prepared for the session to provide better guidance. This is a free opportunity for you to not only give back to the WebdriverIO community but also get to know the team behind the project. Currently we offer 4 slots a week from: every Wednesday 10am - 12am (CEST / GMT+2) for our European friends as well as: 11am - 13am (PDT / GMT -7) for people living on the west side of this hemisphere. Before you book an appointment, make sure you can meet the following basic requirements needed to contribute to WebdriverIO: * you've found an issue you like to contribute to in the [issue tracker](https://github.com/webdriverio/webdriverio/issues) (without an issue, your appointment will be cancelled immediatelly) * you have been working on a Node.js project before (these sessions can't be used to learn Node.js fundamentals) * you've read the [Contribution Guidelines](https://github.com/webdriverio/webdriverio/blob/main/CONTRIBUTING.md#set-up-project) and have the project set-up locally or in an ephemeral workspace * you can run the projects unit tests, and they are passing After that, you can book an appointment at any time on: [calendly.com/webdriverio/open-office-hours](https://calendly.com/webdriverio/open-office-hours) All sessions will be held over [Zoom](https://zoom.us/) or [Google Hangouts](https://hangouts.google.com/) but alternative platforms are possible, please let us know in the comment section. Also please note that this is not a way to get individual consulting for your own projects. The time is to be used to work on WebdriverIO related bugs or features. For support questions we still ask you to use our [Discord Support Server](https://discord.webdriver.io). We are looking forward to meet you all online and hope to find more collaborators helping us to push the project forward! --- # Resources There are many wonderful curated resources the WebdriverIO community has put together. Make sure to contribute yours at [`awesome-webdriverio`](https://github.com/webdriverio-community/awesome-webdriverio)! * [WebdriverIO Ecosystem](#webdriverio-ecosystem) * [Support WebdriverIO](#support-webdriverio) * [Documentation](#documentation) * [Community](#community) * [Twitter](#twitter) * [Plugins](#plugins) * [Services](#services) * [Reporters](#reporters) * [Miscellaneous](#miscellaneous) * [Research & Training](#research--training) * [Articles](#articles) * [Videos](#videos) * [Conference/Meetup Talks/Webinars](#conferencemeetup-talkswebinars) * [Courses](#courses) * [Books](#books) * [WebdriverIO Examples](#webdriverio-examples) ## WebdriverIO Ecosystem[​](#webdriverio-ecosystem "Direct link to WebdriverIO Ecosystem") ### Support WebdriverIO[​](#support-webdriverio "Direct link to Support WebdriverIO") *The following references give you more information on how to financially support the project.* * [WebdriverIO Open Collective](https://opencollective.com/webdriverio) - Help support the teams ongoing development efforts. * [Sponsor Documentation](https://webdriver.io/docs/sponsor) * [GitHub Sponsor Page](https://github.com/sponsors/webdriverio) * [Tidelift Sponsor Page](https://tidelift.com/subscription/pkg/npm-webdriverio?utm_source=npm-webdriverio\&utm_medium=github_sponsor_button) ### Documentation[​](#documentation "Direct link to Documentation") * [WebdriverIO 4.x](http://v4.webdriver.io) - WebdriverIO 4.x Documentation. * [WebdriverIO 5.x](http://v5.webdriver.io) - WebdriverIO 5.x Documentation. * [WebdriverIO 6.x](http://v6.webdriver.io) - WebdriverIO 6.x Documentation. * [WebdriverIO 7.x](http://v7.webdriver.io) - WebdriverIO 7.x Documentation. * [WebdriverIO 8.x](http://v8.webdriver.io) - WebdriverIO 8.x Documentation. ### Community[​](#community "Direct link to Community") * [Discord Server](https://discord.webdriver.io) * [#webdriverio in Selenium Slack](https://seleniumhq.slack.com/join/shared_invite/zt-f7jwg1n7-RVw4v4sMA7Zjufira_~EVw) * [Stack Overflow](http://stackoverflow.com/tags/webdriver-io) ### Twitter[​](#twitter "Direct link to Twitter") *People passionate about WebdriverIO (In no particular order)* * [Christian Bromann](https://twitter.com/bromann) - Staff Software Engineer at the Open Source Program Office at Sauce Labs. * [Kevin Lamping](https://twitter.com/klamping) - Senior Front End Engineer. * [Wim Selles](https://twitter.com/wswebcreation) - Senior Solutions Architect at Sauce Labs. ## Plugins[​](#plugins "Direct link to Plugins") ### Services[​](#services "Direct link to Services") * [WebdriverIO Community Services](https://github.com/webdriverio-community?q=service) - A set of community maintained services. * [Wdi5](https://github.com/js-soft/wdi5) - Cross-platform test framework for hybrid UI5 apps. wdi5 = Webdriver.IO + UI5 Test API + appium. * [ChromeDriver](https://github.com/webdriverio-community/wdio-chromedriver-service) - Run Chrome browser seamlessly when running tests. * [SafariDriver](https://github.com/webdriverio-community/wdio-safaridriver-service) - Run Safari browser seamlessly when running tests. * [GeckoDriver](https://github.com/webdriverio-community/wdio-geckodriver-service) - Run Gecko browser seamlessly when running tests. * [EdgeDriver](https://github.com/webdriverio-community/wdio-edgedriver-service) - Run Microsoft Edge browser seamlessly when running tests. * [Gmail](https://github.com/webdriverio-community/wdio-gmail-service) - Fetch e-mails from Google Mail. * [Intercept](https://github.com/webdriverio-community/wdio-intercept-service) - Capture and assert HTTP ajax calls. * [Zafira Listener](https://github.com/shashidharus/wdio-zafira-listener-service) - Report tests to Zafira Dashboard. * [Report Portal](https://github.com/borisosipov/wdio-reportportal-service) - Service used by Report Portal Reporter. * [Docker](https://github.com/stsvilik/wdio-docker-service) - Helps run functional/integration tests against/using containerized applications. * [WireMock](https://github.com/erwinheitzman/wdio-wiremock-service) - Run WireMock seamlessly when running tests. * [Slack](https://github.com/carmenmitru/wdio-slack-service) - Send test results as a slack notification/message to channels. * [LambdaTest](https://github.com/LambdaTest/wdio-lambdatest-service) - Manage tunnel and job metadata for LambdaTest users. * [Image Comparison (Visual Regression Testing)](https://github.com/wswebcreation/wdio-image-comparison-service) - Image comparison and visual regression testing. * [Ng-apimock](https://github.com/ng-apimock/webdriverio-plugin) - Service used by @ng-apimock/core. * [Novus Visual Regression](https://github.com/Jnegrier/wdio-novus-visual-regression-service) - Visual regression testing. * [Re-run](https://github.com/jwplayer/wdio-rerun-service) - Tracks failing tests and scenarios, allowing failing or unstable tests or scenarios to be re-run. * [winappdriver](https://github.com/licanhua/wdio-winappdriver-service) - Run WinAppDriver server seamlessly when running tests. * [ywinappdriver](https://github.com/licanhua/wdio-ywinappdriver-service) - Run ywinappdriver server seamlessly when running tests. * [PerformanceTotal](https://github.com/tzurp/performance-total) - Analyze performance of test automated flows. * [CleanupTotal](https://github.com/tzurp/cleanup-total) - Proper cleanup after each test made easy. * [AWS Device Farm](https://github.com/awslabs/wdio-aws-device-farm-service) - AWS Device Farm service. * [OCR service for Appium Native Apps](https://github.com/wswebcreation/wdio-ocr-service) - Run Tesseract OCR for Appium Native App tests. * [Auto-detect missing imports w/eslint](https://github.com/jamesmortensen/wdio-eslinter-service) - Automatically run eslint checks prior to executing tests. * [wopee.wdio](https://github.com/autonomous-testing/wopee.wdio) - Visual regression testing service by Wopee.io with autonomous test maintenance and AI-powered healing. * [tracelane](https://github.com/Cubenest/rrweb-stack) - Records failed end-to-end tests as self-contained, offline-replayable HTML reports with session replay, console and failed-network panels. No backend. ### Reporters[​](#reporters "Direct link to Reporters") * [WebdriverIO Community Reporters](https://github.com/webdriverio-community?q=reporter) - A set of community maintained reporters. * [Report Portal](https://github.com/borisosipov/wdio-reportportal-reporter) - Report results to Report Portal. * [Video](https://github.com/presidenten/wdio-video-reporter) - Makes videos of failed tests and has optional allure integration. * [HTML](https://github.com/rpii/wdio-html-reporter) - Generates a nice HTML report. * [JSON](https://github.com/fijijavis/wdio-json-reporter) - Report results in JSON format. * [Mochawesome](https://github.com/fijijavis/wdio-mochawesome-reporter) - Report results in Mochawesome format. * [Timeline](https://github.com/QualityOps/wdio-timeline-reporter) - Report results in an aggregated visualisation interface. * [CucumberJS](https://github.com/wswebcreation/wdio-cucumberjs-json-reporter) - Report results in CucumberJS JSON format. * [Markdown](https://github.com/carmenmitru/wdio-markdown-reporter) - Report results in Markdown format. * [Delta Reporter](https://github.com/delta-reporter/delta-reporter-wdio) - Report results in Delta Reporter format. * [Teamcity](https://github.com/webdriverio-community/wdio-teamcity-reporter) - Report results to the build results page of Teamcity Portal. ### Miscellaneous[​](#miscellaneous "Direct link to Miscellaneous") * [wdio-wait-for](https://github.com/webdriverio-community/wdio-wait-for) - A lightweight library of useful expected conditions for the WebdriverIO framework. * [@wdio/schematics](https://github.com/webdriverio/webdriverio-schematics) - A schematic to add WebdriverIO to an Angular project. * [@badisi/wdio-harness](https://github.com/Badisi/wdio-harness) - WebdriverIO support for Angular component test harnesses. * [@rbnx/webdriverio](https://github.com/Roozenboom/rbnx/tree/main/packages/webdriverio) - Nx plugin that adds WebdriverIO support to a Nx workspace. * [@rahularanger/WTicks](https://github.com/RahulARanger/WTicks) - A tool for exporting Selenium `.side` files into a WebdriverIO script. ## Research & Training[​](#research--training "Direct link to Research & Training") ### Articles[​](#articles "Direct link to Articles") * Ross Addinall | 20-Apr-21 - [Cypress vs WebDriverIO](https://vitaq.io/2021/04/20/cypress-vs-webdriverio). ### Videos[​](#videos "Direct link to Videos") * [UI Automation with WebdriverIO](https://testautomationu.applitools.com/webdriverio-tutorial) - By Julia Pottinger. * [Automated Software Testing with WebdriverIO](https://www.udemy.com/course/automated-software-testing-with-webdriverio/) - By Kaniel Outis. * [WebdriverIO - Tutorial for beginners](https://www.youtube.com/watch?v=e8goAKb6CC0\&list=PL6AdzyjjD5HBbt9amjf3wIVMaobb28ZYN) - By Automation Bro. * [Learn WebdriverIO Course](https://www.youtube.com/watch?v=I5hRcPH5dx8\&list=PL0y7qCn3hjLY6JvohBcmUHKHf_iOi8WuF\&ab_channel=Front-endTestingwithKevin) - By Kevin Lamping. * [WebDriverIO - JavaScript Tool](https://www.youtube.com/watch?v=7J3FnyEGXd4\&list=PLFGoYjJG_fqqswF8qDdWNG3b-BtZfiqQn\&ab_channel=NaveenAutomationLabs) - By Naveen AutomationLabs. * [WebdriverIO : NETWORK LOGS](https://www.youtube.com/watch?v=Be9IPyxHmLs) - By Seventeenth Sep. * [WebdriverIO with TypeScript and BDD Framework](https://www.youtube.com/watch?v=FnC--5WB8ow\&list=PLGk7ftfMz7jbZcArQU894rAfo6B1PbXbG\&ab_channel=TestAutomationHub) - By TestAutomationHub. ### Conference/Meetup Talks/Webinars[​](#conferencemeetup-talkswebinars "Direct link to Conference/Meetup Talks/Webinars") * [Electron Testing with WebdriverIO](https://www.youtube.com/watch?v=mAqxh3L_sP4) - By Christian Bromann. * [My favourite features of WebdriverIO](https://www.youtube.com/watch?v=CHcjEI3YZ7Y) - By Julia Pottinger. * [The Nuts and Bolts of WebdriverIO](https://www.youtube.com/watch?v=jOmvPpzLMf8) - By Christian Bromann. * [Using WebdriverIO with Data Provider](https://www.youtube.com/watch?v=0YQCVJk8K_Q) - By Kumar Vikram. * [Scale Your Automated Testing with BrowserStack and WebdriverIO](https://www.youtube.com/watch?v=bW3SM46xslE) - By Kevin Lamping. * [WebdriverIO - Bootstrap your test suite in mins](https://www.youtube.com/watch?v=a7tdIkTeM0o) - By Shweta Varma. ### Courses[​](#courses "Direct link to Courses") * [Web App Testing with WebdriverIO](https://learn.webdriver.io) - By Kevin Lamping. ### Books[​](#books "Direct link to Books") * [Enhanced Test Automation with WebdriverIO: Unlock the superpowers of hybrid testing frameworks](https://www.amazon.co.uk/dp/1837630186?ref_=cm_sw_r_cp_ud_dp_7PPKW4XNVXHFQ9XA2A0D) - Elevate your testing game to the next level using advanced techniques and proven strategies with this book for WebdriverIO beginners and automation pros alike. * [The Web App Testing Guidebook](https://leanpub.com/webapp-testing-guidebook) - Covers everything you need to know to get off the ground with UI testing. Examples are built using real-world scenarios, showing how you would actually write your tests. It's a step-by-step guide on how to effectively write UI test automation for the real world. * [Practical WebDriverIO](https://www.springer.com/de/book/9781484266601) - Teaches you intermediate and advanced methods for using WebDriverIO APIs. ### WebdriverIO Examples[​](#webdriverio-examples "Direct link to WebdriverIO Examples") * [Boilerplate Projects](https://webdriver.io/docs/boilerplates) - Over time, our community has developed several projects that you can use as inspiration to set up your own test suite. [Back to top](#contents) --- # Need Help? This project is maintained by a dedicated group of people. If you're interested in making a contribution to the WebdriverIO project, check out [the free "Office Hours" program](/blog/2020/07/01/office-hours) to help you with your efforts. If you're seeking immediate help with your own project, reach out to a trusted WebdriverIO expert: * [Kevin Lamping](https://www.codementor.io/@kevinlamping) * [Add your name to this list](https://github.com/webdriverio/webdriverio/edit/master/website/docs/Support.md) ## Stack Overflow[​](#stack-overflow "Direct link to Stack Overflow") Stack Overflow is a popular forum to ask code-level questions or if you’re stuck with a specific error. Read through the [existing questions](https://stackoverflow.com/questions/tagged/webdriver-io) tagged with webdriver-io or [ask your own](https://stackoverflow.com/questions/ask?tags=webdriver-io)! ## Discussion Forums[​](#discussion-forums "Direct link to Discussion Forums") There are many online forums which are a great place for discussion about WebdriverIO features, problems and bugs, e.g.: * [GitHub Discussions](https://github.com/webdriverio/webdriverio/discussions) * [Discord Community Server](https://discord.webdriver.io) * [#webdriverio Channel on SeleniumHQ Slack](https://join.slack.com/t/seleniumhq/shared_invite/zt-vv33sc0w-VKKQop3WDV_lfrLXGGHvDw) ## News[​](#news "Direct link to News") For the latest news about WebdriverIO, [follow @webdriverio on 𝕏](https://x.com/webdriverio) and the official [WebdriverIO blog](/blog) on this website. --- # Team The WebdriverIO development is led by a dedicated team of developers and SDETs from various companies as well contributions from people around the world. ## Technical Steering Committee[​](#technical-steering-committee "Direct link to Technical Steering Committee") ![](https://avatars2.githubusercontent.com/u/4043890?s=460) #### Adam Bjerstedt[](https://github.com/abjerstedt) Senior Software Engineer - Android at [Target](https://www.target.com/). ![](https://avatars2.githubusercontent.com/u/731337?s=460) #### Christian Bromann[](https://github.com/christian-bromann)[](https://x.com/bromann) Staff Software Engineer at the Open Source Program Office [@saucelabs](https://saucelabs.com/). ![](https://avatars.githubusercontent.com/u/15839059?s=460) #### Erwin Heitzman[](https://github.com/erwinheitzman) Senior Test Automation Engineer at [deTesters](https://detesters.nl/). ![](https://avatars0.githubusercontent.com/u/706039?s=460) #### Kevin Lamping[](https://github.com/klamping)[](https://x.com/klamping) Senior Front End Engineer. ![](https://avatars0.githubusercontent.com/u/25589559?s=460) #### Mykola Grybyk[](https://github.com/mgrybyk) Senior Software Development Engineer in Test. ![](https://avatars3.githubusercontent.com/u/1300981?s=460) #### Will Brock[](https://github.com/WillBrock) Automation Engineering Manager at [Focus School Software](https://focusschoolsoftware.com/). ![](https://avatars2.githubusercontent.com/u/11979740?s=460) #### Wim Selles[](https://github.com/wswebcreation)[](https://x.com/wswebcreation) Senior Solutions Architect [@saucelabs](https://saucelabs.com/). ## Project Collaborators[​](#project-collaborators "Direct link to Project Collaborators") ![](https://avatars0.githubusercontent.com/u/14321495?s=460) #### Baruch Velez[](https://github.com/baruchvlz)[](https://x.com/baruchvelez) ![](https://avatars.githubusercontent.com/u/6514276?v=4) #### Boris Osipov[](https://github.com/BorisOsipov)[](https://x.com/bo_osipov) and [many many more](https://github.com/orgs/webdriverio/people). --- # Axe Core You can include accessibility tests within your WebdriverIO test suite using the open-source accessibility tools [from Deque called Axe](https://www.deque.com/axe/). The setup is very easy, all you need to do is to install the WebdriverIO Axe adapter via: * npm * Yarn * pnpm * Bun ``` npm install -g @axe-core/webdriverio ``` ``` yarn global add @axe-core/webdriverio ``` ``` pnpm add -g @axe-core/webdriverio ``` ``` bun add --global @axe-core/webdriverio ``` The Axe adapter can be used either in [standalone or testrunner](/docs/setuptypes.md) mode by simply importing and initializing it with the [browser object](/docs/api/browser.md), e.g.: ``` import { browser } from '@wdio/globals' import AxeBuilder from '@axe-core/webdriverio' describe('Accessibility Test', () => { it('should get the accessibility results from a page', async () => { const builder = new AxeBuilder({ client: browser }) await browser.url('https://testingbot.com') const result = await builder.analyze() console.log('Acessibility Results:', result) }) }) ``` You can find more documentation on the Axe WebdriverIO adapter [on GitHub](https://github.com/dequelabs/axe-core-npm/tree/develop/packages/webdriverio#usage). --- # BrowserStack Accessibility Testing You can easily integrate accessibility tests in your WebdriverIO test suites using the [Automated tests feature of BrowserStack Accessibility Testing](https://www.browserstack.com/docs/accessibility/automated-tests?utm_source=webdriverio\&utm_medium=partnered\&utm_campaign=documentation). ## Advantages of Automated Tests in BrowserStack Accessibility Testing[​](#advantages-of-automated-tests-in-browserstack-accessibility-testing "Direct link to Advantages of Automated Tests in BrowserStack Accessibility Testing") To use Automated tests in BrowserStack Accessibility Testing, your tests should be running on BrowserStack Automate. The following are the advantages of Automated tests: * Seamlessly integrates into your pre-existing automation test suite. * No code changes are required in test cases. * Requires zero additional maintenance for accessibility testing. * Understand historical trends and gain test-case insights. ## Get Started with BrowserStack Accessibility Testing[​](#get-started-with-browserstack-accessibility-testing "Direct link to Get Started with BrowserStack Accessibility Testing") Follow these steps to integrate your WebdriverIO test suites with BrowserStack's Accessibility Testing: 1. Install `@wdio/browserstack-service` npm package. * npm * Yarn * pnpm * Bun ``` npm install --save-dev @wdio/browserstack-service ``` ``` yarn add --dev @wdio/browserstack-service ``` ``` pnpm add --save-dev @wdio/browserstack-service ``` ``` bun add --dev @wdio/browserstack-service ``` 2. Update `wdio.conf.js` config file. ``` exports.config = { //... user: '' || process.env.BROWSERSTACK_USERNAME, key: '' || process.env.BROWSERSTACK_ACCESS_KEY, commonCapabilities: { 'bstack:options': { projectName: "Your static project name goes here", buildName: "Your static build/job name goes here" } }, services: [ ['browserstack', { accessibility: true, // Optional configuration options accessibilityOptions: { 'wcagVersion': 'wcag21a', 'includeIssueType': { 'bestPractice': false, 'needsReview': true }, 'includeTagsInTestingScope': ['Specify tags of test cases to be included'], 'excludeTagsInTestingScope': ['Specify tags of test cases to be excluded'] }, }] ], //... }; ``` You can view detailed instructions [here](https://www.browserstack.com/docs/accessibility/automated-tests/get-started/webdriverio?utm_source=webdriverio\&utm_medium=partnered\&utm_campaign=documentation). --- # TestMu AI Accessibility Testing You can easily integrate accessibility tests in your WebdriverIO test suites using [TestMu AI Accessibility Testing](https://www.testmuai.com/support/docs/accessibility-automation-settings/). ## Advantages of TestMu AI Accessibility Testing[​](#advantages-of-testmu-ai-accessibility-testing "Direct link to Advantages of TestMu AI Accessibility Testing") TestMu AI Accessibility Testing helps you identify and fix accessibility issues in your web applications. The following are the key advantages: * Seamlessly integrates with your existing WebdriverIO test automation. * Automated accessibility scanning during test execution. * Comprehensive WCAG compliance reporting. * Detailed issue tracking with remediation guidance. * Support for multiple WCAG standards (WCAG 2.0, WCAG 2.1, WCAG 2.2). * Real-time accessibility insights in the TestMu AI dashboard. ## Get Started with TestMu AI Accessibility Testing[​](#get-started-with-testmu-ai-accessibility-testing "Direct link to Get Started with TestMu AI Accessibility Testing") Follow these steps to integrate your WebdriverIO test suites with TestMu AI's Accessibility Testing: 1. Install the TestMu AI WebdriverIO service package. * npm * Yarn * pnpm * Bun ``` npm install --save-dev @lambdatest/wdio-lambdatest-service ``` ``` yarn add --dev @lambdatest/wdio-lambdatest-service ``` ``` pnpm add --save-dev @lambdatest/wdio-lambdatest-service ``` ``` bun add --dev @lambdatest/wdio-lambdatest-service ``` 2. Update your `wdio.conf.js` configuration file. ``` exports.config = { //... user: process.env.LT_USERNAME || '', key: process.env.LT_ACCESS_KEY || '', capabilities: [{ browserName: 'chrome', 'LT:Options': { platform: 'Windows 10', version: 'latest', accessibility: true, // Enable accessibility testing accessibilityOptions: { wcagVersion: 'wcag21a', // WCAG version (wcag20, wcag21a, wcag21aa, wcag22aa) bestPractice: false, needsReview: true } } }], services: [ ['lambdatest', { tunnel: false }] ], //... }; ``` 3. Run your tests as usual. TestMu AI will automatically scan for accessibility issues during test execution. ``` npx wdio run wdio.conf.js ``` ## Configuration Options[​](#configuration-options "Direct link to Configuration Options") The `accessibilityOptions` object supports the following parameters: * **wcagVersion**: Specify the WCAG standard version to test against * `wcag20` - WCAG 2.0 Level A * `wcag21a` - WCAG 2.1 Level A * `wcag21aa` - WCAG 2.1 Level AA (default) * `wcag22aa` - WCAG 2.2 Level AA * **bestPractice**: Include best practice recommendations (default: `false`) * **needsReview**: Include issues that need manual review (default: `true`) ## Viewing Accessibility Reports[​](#viewing-accessibility-reports "Direct link to Viewing Accessibility Reports") After your tests complete, you can view detailed accessibility reports in the [TestMu AI Dashboard](https://automation.lambdatest.com/): 1. Navigate to your test execution 2. Click on the "Accessibility" tab 3. Review identified issues with severity levels 4. Get remediation guidance for each issue For more detailed information, visit the [TestMu AI Accessibility Automation documentation](https://www.testmuai.com/support/docs/accessibility-automation-settings/). --- # WebdriverIO for Coding Agents Most WebdriverIO tests today are written together with a coding agent. This page shows how to give an agent the three things it needs to do that well: **current documentation** (so it writes v10 code instead of guessing), **a way to drive the app under test** (so it can explore the UI and verify selectors), and **debuggable test runs** (so it can fix failing tests on its own). ## 1. Give your agent the documentation[​](#1-give-your-agent-the-documentation "Direct link to 1. Give your agent the documentation") Every page on this site is available as clean Markdown, without navigation, scripts or styling: | Resource | URL | Use it for | | ------------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | | Documentation index | [`https://webdriver.io/llms.txt`](https://webdriver.io/llms.txt) | A curated map of all pages with one-line summaries. Start here. | | Full documentation | [`https://webdriver.io/llms-full.txt`](https://webdriver.io/llms-full.txt) | The complete docs in a single file, for agents with large context windows. | | Any single page | Append `.md` to the URL, e.g. [`/docs/api/browser/url.md`](https://webdriver.io/docs/api/browser/url.md) | Loading exactly the page the agent needs. | | Content negotiation | Request any `/docs/*` URL with `Accept: text/markdown` | Agents and tools that fetch URLs as-is. | Each doc page also has a **Copy page** menu with options to copy the page as Markdown or open it directly in ChatGPT, Claude or Cursor. ### Docs MCP server[​](#docs-mcp-server "Direct link to Docs MCP server") The documentation is also available as a remote MCP server at `https://webdriver.io/mcp`. It gives an agent three tools: `search_docs` to find the right page, `get_page` to read it as Markdown, and `list_sections` to load a whole section at once. Add it next to the WebdriverIO MCP server described below: .mcp.json ``` { "mcpServers": { "webdriverio-docs": { "url": "https://webdriver.io/mcp" } } } ``` For Claude Code, run `claude mcp add --transport http webdriverio-docs https://webdriver.io/mcp`. ## Let your agent use `wdio session`[​](#let-your-agent-use-wdio-session "Direct link to let-your-agent-use-wdio-session") [`wdio session`](/docs/session.md) keeps a WebdriverIO session alive between shell commands. An agent can open a browser, phone or desktop app, snapshot what is on screen, act on refs, and export the steps that worked as a test. That is the default way to drive an app from a coding agent. The [MCP server](/docs/mcp.md) in the next section is the alternative when the agent should call tools instead of the shell. Install the skill into the project: ``` npx wdio session skill --install . ``` That writes `.agents/skills/wdio-session/SKILL.md`. `npm init wdio` writes the same file when you accept coding agent support, and adds the project rules below. An agent can create the project itself. The wizard takes a flag for every question, and `--yes` fills in the defaults for the rest, so it never waits for input: ``` npm init wdio@latest . -- --yes --typescript --framework mocha --browsers chrome --reporters spec ``` `npm init wdio@latest -- --help` lists every flag and its values. See [Answer the wizard with flags](/docs/gettingstarted.md#answer-the-wizard-with-flags). The [WebdriverIO Session](/docs/session.md) section covers targets, snapshots, `exec`, export and debugging. Command reference: [wdio session commands](/docs/session-commands.md). ### Add the docs to your agent[​](#add-the-docs-to-your-agent "Direct link to Add the docs to your agent") To make the docs available in every chat, add the index to your agent: * **Cursor**: add `https://webdriver.io/llms.txt` as a custom doc in the Cursor settings (*Indexing & Docs*), then reference it in chat with `@` and the name you gave it. * **Claude Code / Codex / other CLI agents**: add the link to your project's `AGENTS.md` or `CLAUDE.md` (see [project rules](#3-add-project-rules) below). The agents fetch the pages they need on demand. ## 2. Let your agent drive the browser or app[​](#2-let-your-agent-drive-the-browser-or-app "Direct link to 2. Let your agent drive the browser or app") The [WebdriverIO MCP server](/docs/mcp.md) (`@wdio/mcp`) lets an agent open browsers (Chrome, Firefox, Edge, Safari), native and hybrid mobile apps (via Appium) and cloud devices, inspect the accessibility tree, click, type and take screenshots. Agents use it to explore a page before writing a test, to find robust selectors, and to reproduce a failure step by step. Add it to your MCP client configuration (for example `.mcp.json` or `.cursor/mcp.json` in your project): .mcp.json ``` { "mcpServers": { "wdio-mcp": { "command": "npx", "args": ["-y", "@wdio/mcp"] } } } ``` For Claude Code, register it from the command line: ``` claude mcp add --transport stdio wdio-mcp -- npx -y @wdio/mcp ``` See the [MCP configuration](/docs/mcp/configuration.md) for session options, and [Cloud Providers](/docs/mcp/cloud-providers.md) to run on BrowserStack, Sauce Labs, TestMu AI or TestingBot. ## 3. Add project rules[​](#3-add-project-rules "Direct link to 3. Add project rules") Agents follow the conventions of a project much more reliably when they are written down. Add a section like the following to the `AGENTS.md` (or `CLAUDE.md`, `.cursor/rules`) of your test project and adjust the paths and commands: AGENTS.md ``` ## End-to-end tests (WebdriverIO v10) - Docs: https://webdriver.io/llms.txt - fetch the relevant page as Markdown (append `.md`) before using an API you are not sure about. Do not use APIs from WebdriverIO v8 or older. - Config: `wdio.conf.ts`. Specs: `test/specs/**/*.e2e.ts`. Page objects: `test/pageobjects/`. - Run all tests: `npx wdio run wdio.conf.ts` - Run a single spec: `npx wdio run wdio.conf.ts --spec test/specs/login.e2e.ts` - Tests are async: always `await` commands, e.g. `await $('button').click()`. Never use the removed sync mode. - Prefer user-facing selectors: accessibility name or text (`$('aria/Submit')`, `$('button=Submit')`), then `data-testid`. Avoid XPath and generated CSS classes. - Rely on auto-waiting and `expect-webdriverio` matchers (`await expect($('h1')).toHaveText('Welcome')`) instead of `browser.pause()`. - To explore the app or verify a selector, use the `wdio-mcp` MCP server. - To drive the app from the shell, follow `.agents/skills/wdio-session/SKILL.md` (`npx wdio session`). - When a test fails, read the DevTools trace in `test-results/` (see `transcript.md`) before changing code. ``` The rules above reflect the recommendations in [Best Practices](/docs/bestpractices.md), [Selectors](/docs/selectors.md) and [Auto-waiting](/docs/autowait.md). ## 4. Let the agent debug failing tests[​](#4-let-the-agent-debug-failing-tests "Direct link to 4. Let the agent debug failing tests") The [WebdriverIO DevTools](/docs/devtools.md) service can record a **trace** of every run: a portable artifact with a step-by-step Markdown transcript, screenshots, accessibility-tree snapshots and network logs for each action. This gives an agent the same information a human gets from watching the test, without needing a browser window. Install the service and enable trace mode: ``` npm install @wdio/devtools-service --save-dev ``` wdio.conf.ts ``` export const config: WebdriverIO.Config = { // ... services: [ ['devtools', { mode: 'trace', // one trace per test makes it easy to hand a single failure to an agent traceGranularity: 'test', // plain files instead of a zip, so agents can read them directly traceFormat: 'ndjson-directory' }] ] } ``` After a run, traces are written to `test-results/`. Point your agent at the folder of the failing test and ask it to read `transcript.md` first. See [Trace Mode](/docs/devtools/wdio/trace-mode.md) for all options, including granularity and retention. ## Recommended workflow[​](#recommended-workflow "Direct link to Recommended workflow") 1. Ask the agent to explore the feature under test with the MCP server and propose selectors. 2. Let it write the spec and page object following your project rules, fetching WebdriverIO docs pages as needed. 3. Have it run the single spec with `--spec` and iterate until it passes. 4. If a test fails in CI, give the agent the trace of that test and let it fix the test or report the bug. ## Next steps[​](#next-steps "Direct link to Next steps") * [Getting Started](/docs/gettingstarted.md) - create a project with `npm init wdio@latest` * [WebdriverIO MCP](/docs/mcp.md) - all tools the MCP server provides * [DevTools](/docs/devtools.md) - live mode and trace mode * [Best Practices](/docs/bestpractices.md) - what good WebdriverIO tests look like * [From v9 to v10](/docs/v10-migration.md#migrate-with-a-coding-agent) - the migration skill for an existing suite --- # AI Service > Steps written as intent: `browser.act()` performs a user action described in natural language, `browser.extract()` reads typed data, with your own model. ``` import { z } from 'zod' await browser.url('/shop') await browser.act('Add a blue shirt in size M to the shopping cart') const cart = await browser.extract( 'the line items in the cart', z.array(z.object({ name: z.string(), size: z.string(), qty: z.number() })) ) expect(cart).toContainEqual({ name: 'Blue Shirt', size: 'M', qty: 1 }) ``` `act` hands the instruction to a model together with the `wdio session` actions (snapshot, click, fill, press, …). The model works through the page with refs from accessibility snapshots, and every step it takes runs as a regular WebdriverIO command with a stable selector. `act` does not assert, the test checks the outcome. ## Installation[​](#installation "Direct link to Installation") ``` npm install @wdio/ai-service --save-dev ``` Install the LangChain package of the provider you use. Models are created with LangChain's [`initChatModel`](https://docs.langchain.com/oss/javascript/langchain/models#initialize-a-model), so every provider it supports works, e.g. `google`, `mistralai`, `groq` or `bedrock`: | Provider | Package | API key | | ------------------------ | ---------------------- | ------------------------------------------------------- | | `anthropic` | `@langchain/anthropic` | `ANTHROPIC_API_KEY` | | `openai` | `@langchain/openai` | `OPENAI_API_KEY` | | `openrouter` | `@langchain/openai` | `OPENROUTER_API_KEY` | | `ollama` | `@langchain/ollama` | none, runs locally (`OLLAMA_BASE_URL` for another host) | | `llama-cpp`, `lm-studio` | `@langchain/openai` | none, set `baseURL` | ## Configuration[​](#configuration "Direct link to Configuration") ``` // wdio.conf.ts export const config: WebdriverIO.Config = { // ... services: [['ai', { model: 'anthropic:claude-sonnet-5-5' }]] } ``` | Option | Type | Default | Description | | ---------------- | -------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `model` | `string \| ModelConfig \| BaseChatModel` | `process.env.WDIO_AI_MODEL` | `'provider:model'`, a config object (`provider`, `model`, `baseURL`, `apiKey`, `temperature`, `maxTokens`) or any LangChain chat model. | | `cache` | `'auto' \| 'write' \| 'heal' \| 'locked' \| 'off'` | `'auto'` | See [Cache](#cache). | | `cacheDir` | `string \| (specPath) => string` | `/__act__/` | Where cache files live. | | `instructions` | `string` | | Markdown file with project conventions, appended to the system prompt. | | `maxSteps` | `number` | `15` | Tool calls one `act` may make. | | `maxModelCalls` | `number` | | Model calls per worker. | | `actions` | `string[]` | page actions of `wdio session` | Actions the model may use. Code execution, cookies, storage, mocks and emulation are never offered. | | `effects` | `'strict' \| 'loose' \| 'off' \| { mode, ignore }` | `'strict'` | How replayed and healed steps are checked against what they did when recorded, see [Step effects](#step-effects). `ignore` adds URL patterns to the analytics hosts that never count. | | `responseBodies` | `boolean` | `true` | Collect fetch and XHR response bodies over WebDriver BiDi so `extract` can read them, see [Extract](#extract). | | `healEvidence` | `boolean` | `true` | Save screenshots of every heal and failed replay, plus a video where the browser records one, see [Heal evidence](#heal-evidence). | | `workspace.dir` | `string` | `/ai` or `.wdio/ai` | Root of the evidence folders, see [Workspace](#workspace). | | `workspace.keep` | `'on-failure' \| 'always' \| 'never'` | `'on-failure'` | Keep a test's folder when an `act` call failed or healed, or the test failed. | Your model key never leaves your machine except to the model endpoint you configure. ## Usage[​](#usage "Direct link to Usage") ``` // placeholders: values are substituted after the model call and never sent to the model await browser.act('Log in as {{email}} with password {{password}}', { values: { email: process.env.SHOP_USER!, password: process.env.SHOP_PASS! } }) ``` `act` resolves to `{ source, steps, summary }`. `steps` lists the WebdriverIO code that ran. When the model reports that the instruction cannot be completed, or the step limit or timeout (`timeout`, default 60s) is reached, `act` throws an `ActError` with the reason. At the timeout, or when the test ends, a step whose action already runs finishes first: `act` never returns while one of its steps still uses the browser. A cached step that only waited for its element until then does not run its action, and a `wait` of the model ends by the timeout. ## Scope[​](#scope "Direct link to Scope") `act` and `extract` are available on the browser, on elements and on browsing contexts: ``` // only the billing form: snapshots show nothing else, steps stay inside it await $('form#billing').act('Fill in a valid German address') // a cross-origin payment frame, held from the page const page = await browser.url('https://shop.example/checkout') const payment = await page.frame('https://pay.example/form') await payment.act('Pay with the test card {{card}}', { values: { card: '4242 4242 4242 4242' } }) ``` On a frame or a tab the steps run in that browsing context, and the browser goes back to where it was afterwards. On the browser the model can enter frames, go back to the top document and switch to a window a step opened. These steps are recorded and replayed like any other. ## Extract[​](#extract "Direct link to Extract") `extract(instruction, schema, options?)` reads information from the page and validates it against a [Standard Schema](https://standardschema.dev): zod, valibot, arktype and others. The model can only read the page (`snapshot`, `find`, `get`, `is`, `scroll`, the workspace), never change it. When the schema library can describe itself as JSON Schema (zod 4 can), the model gets that shape. An answer that does not match is rejected and the model answers again once. `extract` results are never cached: a read has to see the current page. Like `act`, it returns after a read step that still runs at its `timeout` or at the end of the test. Keep pass/fail decisions in code: let `extract` find the value, and assert it with `expect`. Pages often show less than they load: a count instead of the items, a rounded price, a truncated name. Over WebDriver BiDi the service collects the bodies of the fetch and XHR responses with a text body that the page receives, using a network data collector (Chrome and Firefox). Before an `extract` call it writes the latest 50 to `/responses` in the workspace, with an index of method, URL and status. The model can read them and names the file as evidence. Analytics hosts and the `effects.ignore` patterns are left out. Set `responseBodies: false` to turn this off. ``` // the page only shows "2 items in your cart" const skus = await browser.extract('the SKUs of the items in the cart', z.array(z.string())) ``` ## Cache[​](#cache "Direct link to Cache") The steps of every `act` call are recorded in `__act__/.json` next to the spec. Commit the file. Later runs replay the steps without calling the model, so a passing run costs no tokens and is as fast as hand-written commands. ``` { "version": 1, "entries": { "cart adds a shirt › #1": { "instruction": "Add a blue shirt in size M to the shopping cart", "platform": "web", "model": "anthropic:claude-sonnet-5-5", "recordedAt": "2026-10-01T12:00:00.000Z", "steps": [ { "action": "click", "args": { "target": "role/link[name=\"Blue Shirt\"]" }, "code": "await $('role/link[name=\"Blue Shirt\"]').click()" }, { "action": "click", "args": { "target": "role/button[name=\"Add to cart\"]" }, "code": "await $('role/button[name=\"Add to cart\"]').click()" } ] } } } ``` An entry is keyed by the full test title and the position of the `act` call in the test (`#1`, `#2`, …), or by the `id` option. When the instruction text changes, the call is recorded again. Placeholders stay placeholders in the file. ## Healing[​](#healing "Direct link to Healing") When a replayed step fails because the page changed, `act` heals it in two levels and reports every heal: | Level | What happens | Model call | Reported as | | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ----------------- | | 1 | Try the other recorded selectors of the element, then its role and accessible name with the [`role/` selector](https://webdriver.io/docs/selectors#role-selector). A selector is only used when it matches exactly one element. | no | `healed: 'cache'` | | 2 | The model gets the steps that already ran and the failing step, and continues from the current page. | yes | `healed: 'model'` | The healed steps replace the entry, except in `locked` mode, which heals at level 1 but writes nothing and fails instead of calling the model. At the end of the run the service prints a summary: ``` @wdio/ai-service: 42 act calls · 39 from cache · 2 healed without the model · 1 healed by the model · 0 recorded by the model · 3.1k tokens Healed: cart.e2e.ts › cart adds a shirt "Add a blue shirt to the cart": step 2 [data-testid="add"] → role/button[name="Add to cart"] (without the model) evidence: ./logs/ai/heals/cart.e2e.ts-cart-adds-a-shirt-1c71c48d checkout.e2e.ts › checkout pays "Pay with the test card": continued by the model evidence: ./logs/ai/heals/checkout.e2e.ts-checkout-pays-24560807 Updated cache entries: ./logs/act-cache ``` Every call also emits an `ai:act` event on `process` with `{ spec, test, instruction, source, healed, healedSteps, artifacts, error, usage, durationMs }`, so reporters can show it. ### Heal evidence[​](#heal-evidence "Direct link to Heal evidence") A heal is a change you should review, so the service shows you what happened. When a cached step fails, it saves: * `failed.png`, the page when the step failed * `step-1.png`, `step-2.png`, …, the page after each step that healed it * a WebM video of the whole heal, in browsers that implement the WebDriver BiDi [`browsingContext.startScreencast`](https://w3c.github.io/webdriver-bidi/#command-browsingContext-startScreencast) command (Firefox today) The files go to `/heals/--/`, and the summary prints the folder. Nothing is captured while cached steps replay fine. Set `healEvidence: false` to turn it off. `workspace.keep: 'never'` also captures no heal evidence, so no screenshots of your app stay on disk. | Mode | Cached | Not cached | Writes | | -------- | ---------------------- | --------------------------- | ------------------------------------------------------------------------------------- | | `write` | replay | record with the model | the cache files | | `heal` | replay | record with the model | `/act-cache/` only, the cache files stay unchanged | | `locked` | replay | fail, never calls the model | nothing | | `off` | always calls the model | | nothing | `auto` is `heal` when `process.env.CI` is set and `write` otherwise. A call's own `cache` option decides where its entry goes. Workers that write the same cache file take turns, so none loses the entries of another. `wdio run -s` (`updateSnapshots: 'all'`) records every `act` call again. ## Step effects[​](#step-effects "Direct link to Step effects") Every recorded step also stores what it did: the fetch and XHR requests it sent (`POST /api/cart → 2xx`, IDs in the path become `:id`), the navigation it caused, a window it opened, the named parts of the page that changed (`status "Cart"`) and a dialog it opened. WebDriver BiDi delivers all of it as events, the page changes come from a `MutationObserver` the service installs as a preload script. ``` "effect": { "requests": ["POST /api/cart → 2xx"], "changed": ["status \"Cart\""] } ``` > **Experimental:** the names in `changed` are experimental. A minor release may name the parts of a page differently, and a cached step whose `changed` names no longer match then has to be recorded again (`wdio run -s`). Requests, navigation, new windows and dialogs are stable. A replayed or healed step is only accepted when it has the same effect: * A healed step that clicks a similar but wrong element, for example a *Add to cart* button that now adds to the wishlist, sends a different request and is rejected. * A step that still finds its element but no longer does anything fails with *"ran, but the step no longer causes POST /api/cart → 2xx. The app may have changed behavior, not just markup."*: a regression, not a markup change. * A step that ran but did something else is never run again, not with another selector and not by the model, because it may already have submitted a form or a payment. `act` fails in every cache mode, and you decide whether the app changed on purpose. * Steps the model takes to continue from a step whose element is gone have to cause the effect of that step. | Mode | Check | | -------- | --------------------------------------------------------------------------------------------------------------------- | | `strict` | every recorded request, the navigation, the new window, every changed region and the dialog. Extra requests are fine. | | `loose` | the navigation and at least one recorded request or changed region | | `off` | only the target | Requests to common analytics and telemetry hosts, websockets, beacons and assets never count. A step is done when its requests finished, no navigation is pending and the page had no changes for 100 ms, so `act` waits for slow requests instead of a fixed time. A replay waits up to 5 seconds, or the `waitforTimeout` of your config when it is longer. A step whose request is still running then fails with *"the step was still running after 8000ms (POST /api/cart), so its effect could not be checked"*, not as a behavior change. A step recorded while a request is still running keeps the parts that finished. WebDriver Classic sessions see navigation and page changes but not requests, new windows or dialogs, so only those parts are checked there, and the summary says so. Native app effects are not checked. ## Workspace[​](#workspace "Direct link to Workspace") When the model works on a test, the service collects what happened in a folder per test, `/ai////`: ``` snapshots/003.txt every snapshot the model took console.ndjson browser console, from the start of the session (BiDi) network.ndjson requests and responses (BiDi) page.html page source, when the model saves it with the `source` tool outputs/ tool results too long for the prompt steps.json the steps that ran ``` The files in `snapshots/` use the [`wdio session` snapshot](https://webdriver.io/docs/session/snapshots) layout, which is experimental: read them, but don't parse them in tooling. The model can read the folder with the read-only file tools of [Deep Agents](https://docs.langchain.com/oss/javascript/deepagents/overview) (`ls`, `read_file`, `glob`, `grep`). It cannot write files or read anything outside the folder. Placeholder values are redacted from every file. A test that replays from the cache creates no folder. A failed `act` error names the folder, so you can look at what the model saw. ## Eject[​](#eject "Direct link to Eject") Turn `act()` calls back into plain WebdriverIO code once they are recorded: ``` npx wdio-ai eject test/specs/cart.e2e.ts ``` ``` // act: Add a blue shirt in size M to the shopping cart await $('role/link[name="Blue Shirt"]').click() await $('role/combobox[name="Size"]').selectByVisibleText('M') await $('role/button[name="Add to cart"]').click() ``` The instruction stays as a comment. Placeholders become references to the `values` of the call. A call gets the steps recorded for exactly that call: the entry of its `id`, or of its test title and its position among the `act` calls of the test, the same key the service records. A call in a branch, a loop or a callback has no fixed position, give it an `id`. Calls without a matching entry, or whose entry was recorded for another instruction, are left alone and reported. Use `--test ` to eject the calls of one test and `--dry-run` to print the result. Without the testrunner: ``` import { remote } from 'webdriverio' import { act } from '@wdio/ai-service' const browser = await remote({ capabilities: { browserName: 'chrome' } }) await browser.url('https://shop.example') await act(browser, 'Add a blue shirt to the shopping cart', { model: 'ollama:qwen3:8b' }) ``` For more information on WebdriverIO see the [homepage](https://webdriver.io). --- # AI Steps in Tests `@wdio/ai-service` lets a test describe a step instead of scripting it: `browser.act('Add a blue shirt to the cart')` asks your model to perform it, records the WebdriverIO commands it ran, and replays them from a cache file on every later run. The model is only called again when the page changed and a recorded step can no longer be repaired without it. Use it for flows whose markup changes often, or to get a test running before you know the selectors. Use plain WebdriverIO commands for everything you already know how to script. ## Set up the service[​](#set-up-the-service "Direct link to Set up the service") Install the service and the LangChain package of your model provider: ``` npm install --save-dev @wdio/ai-service @langchain/anthropic zod ``` Add the service to your config and set the API key of the provider (`ANTHROPIC_API_KEY` here) in the environment: wdio.conf.ts ``` export const config: WebdriverIO.Config = { specs: ['./test/specs/**/*.e2e.ts'], capabilities: [{ browserName: 'chrome', webSocketUrl: true }], framework: 'mocha', services: [['ai', { model: 'anthropic:claude-sonnet-5-5' }]] } ``` `webSocketUrl: true` opens a WebDriver BiDi session. The service works over WebDriver Classic too, but BiDi lets it check what every step did and read the API responses of the page. See the [AI Service](/docs/ai-service.md) page for every option and provider, including local models through Ollama. ## Write a test[​](#write-a-test "Direct link to Write a test") test/specs/cart.e2e.ts ``` import { browser, expect } from '@wdio/globals' import { z } from 'zod' describe('cart', () => { it('adds a shirt', async () => { await browser.url('https://shop.example/') await browser.act('Add a blue shirt in size M to the shopping cart') const cart = await browser.extract( 'the line items in the cart', z.array(z.object({ name: z.string(), size: z.string(), qty: z.number() })) ) expect(cart).toContainEqual({ name: 'Blue Shirt', size: 'M', qty: 1 }) }) }) ``` * `act` performs the step and never asserts. Check the outcome with `expect`. * `extract` only reads the page and validates the answer against the schema. It is never cached. * Secrets go into placeholders. The model sees `{{password}}`, never the value: ``` await browser.act('Log in as {{email}} with password {{password}}', { values: { email: process.env.SHOP_USER!, password: process.env.SHOP_PASS! } }) ``` * Call `act` on an element to keep the model inside it, or on a held frame or tab: ``` await $('form#billing').act('Fill in a valid German address') ``` ## Record once, replay without a model[​](#record-once-replay-without-a-model "Direct link to Record once, replay without a model") The first run records the steps of every `act` call in `__act__/.json` next to the spec: ``` npx wdio run wdio.conf.ts --spec test/specs/cart.e2e.ts ``` Commit the `__act__` directory. Later runs replay the recorded commands, so a passing run makes no model calls and costs no tokens. | `cache` | Use it for | | ---------------- | ---------------------------------------------------------------------------------------------------------------- | | `auto` (default) | `write` locally, `heal` when `process.env.CI` is set | | `write` | recording and updating the cache files | | `heal` | CI: repair failing steps, write the repaired entries to `/act-cache/` and leave the cache files alone | | `locked` | CI runs that must not call a model: replay only, fail when a step cannot be repaired without the model | | `off` | always ask the model | Run `npx wdio run wdio.conf.ts -s` to record every `act` call again. ## Review heals[​](#review-heals "Direct link to Review heals") When a recorded step fails, the service first tries the other selectors it recorded for the element and then its role and accessible name. Only if that fails does the model continue from the failing step. Every replayed or healed step has to do what it did when it was recorded: send the same requests, navigate to the same page and change the same parts of the page. A heal onto a similar but wrong button is rejected. The run ends with a summary: ``` @wdio/ai-service: 42 act calls · 39 from cache · 2 healed without the model · 1 healed by the model · 0 recorded by the model · 3.1k tokens Healed: cart.e2e.ts › cart adds a shirt "Add a blue shirt in size M to the shopping cart": step 2 [data-testid="add"] → role/button[name="Add to cart"] (without the model) evidence: ./logs/ai/heals/cart.e2e.ts-cart-adds-a-shirt-1c71c48d ``` The evidence folder holds a screenshot of the page when the step failed, one after each healing step, and a video of the heal in browsers that record a WebDriver BiDi screencast (Firefox today). Review the heal, then commit the updated cache file. ## Turn steps into plain code[​](#turn-steps-into-plain-code "Direct link to Turn steps into plain code") Once a flow is stable, replace its `act` calls with the recorded commands: ``` npx wdio-ai eject test/specs/cart.e2e.ts ``` ``` // act: Add a blue shirt in size M to the shopping cart await $('role/link[name="Blue Shirt"]').click() await $('role/combobox[name="Size"]').selectByVisibleText('M') await $('role/button[name="Add to cart"]').click() ``` ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") | Error | Fix | | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | `act("…") failed: no model is configured. Set the `model` option of the service or the WDIO_AI_MODEL environment variable.` | Set `model` in the service options or export `WDIO_AI_MODEL=anthropic:claude-sonnet-5-5`. | | `[@wdio/ai-service] The "anthropic" provider needs "@langchain/anthropic". Install it with `npm install --save-dev @langchain/anthropic`.` | Install the provider package. | | `[@wdio/ai-service] No API key for "anthropic". Set ANTHROPIC_API_KEY or pass `apiKey` in the model config.` | Export the key in the shell or CI secret that runs the tests. | | `act("…") failed: no cached steps for "…" and the cache is locked` | Record the call locally with `cache: 'write'` and commit the `__act__` file. | | `act("…") failed: cached step 1 (…) ran, but the step no longer causes POST /api/cart → 2xx. The app may have changed behavior, not just markup.` | The element is still there but does something else: a regression, not a markup change. Check the app. | | `act("…") failed: …` followed by `Evidence: ` | The model could not complete the instruction. The folder has every snapshot it took, the console and network events and the steps that ran. | ## Next steps[​](#next-steps "Direct link to Next steps") * [AI Service](/docs/ai-service.md): every option, the cache format, step effects and the workspace * [Selectors](/docs/selectors.md#role-selector): the `role/` selector recorded steps use * [WebdriverIO for Coding Agents](/docs/ai-agents.md): write tests together with a coding agent --- # Allure Reporter > A WebdriverIO reporter plugin to create [Allure Test Reports](https://allurereport.org/docs/webdriverio/). ![Allure Reporter Example](/assets/images/allure-bb6c9b036b07594235a5aca5aff5ac43.png) ### New Features[​](#new-features "Direct link to New Features") * **Test Plan Support** - Execute only specific tests defined in a test plan file * **Enhanced SDK Integration** - Updated to use `allure-js-commons` v3.3.2 with improved performance * **Better Cucumber Support** - Improved handling of Cucumber scenarios and steps * **Enhanced Error Handling** - More robust error reporting and debugging capabilities ### Test Plan Feature[​](#test-plan-feature "Direct link to Test Plan Feature") The Test Plan feature allows you to execute only specific tests defined in a JSON file. This is particularly useful for: * Running subset of tests in CI/CD pipelines * Parallel test execution * Test prioritization #### Configuration[​](#configuration "Direct link to Configuration") Create a test plan file (`.allure/testplan.json` or `testplan.json`): ``` { "version": "1.0", "tests": [ { "id": "test-001", "selector": "test/index.test.ts#should generate testplan.json" } ] } ``` #### How Selectors Work[​](#how-selectors-work "Direct link to How Selectors Work") Test plan selectors work by matching against the test's `fulltitle`, which includes the file path and test name. The format is: ``` # ``` Examples: * `test/index.test.ts#should generate testplan.json` - matches specific test in specific file * `Login Tests` - matches any test with "Login Tests" in the title * `User Registration` - matches any test with "User Registration" in the title The selector matching is flexible and supports: * **Exact matches** - full test title * **Partial matches** - substring of test title * **File-specific matches** - include file path for precise targeting #### Testplan[​](#testplan "Direct link to Testplan") The test plan support can be enabled by providing ALLURE\_TESTPLAN\_PATH environment variable – the reporter automatically loads the test plan file and run tests which match the selectors. ``` ALLURE_TESTPLAN_PATH=/path/to/your/testplan.json ``` #### Usage Examples[​](#usage-examples "Direct link to Usage Examples") **Example 1: Running specific tests by file and test name** ``` { "version": "1.0", "tests": [ { "id": "login-001", "selector": "tests/auth.test.js#should login with valid credentials" }, { "id": "login-002", "selector": "tests/auth.test.js#should reject invalid credentials" } ] } ``` **Example 2: Running tests by partial title match** ``` { "version": "1.0", "tests": [ { "id": "smoke-001", "selector": "Login Tests" }, { "id": "smoke-002", "selector": "User Registration" } ] } ``` **Example 3: Running all tests in a specific file** ``` { "version": "1.0", "tests": [ { "id": "auth-suite", "selector": "tests/auth.test.js" } ] } ``` ## Installation[​](#installation "Direct link to Installation") The easiest way is to include `@wdio/allure-reporter` as a devDependency in your `package.json`. ``` { "devDependencies": { "@wdio/allure-reporter": "^7.0.0" } } ``` You can simply do it by: ``` npm install @wdio/allure-reporter --save-dev ``` ## Configuration[​](#configuration-1 "Direct link to Configuration") Configure the output directory in your wdio.conf.js file: ``` export const config = { // ... reporters: [['allure', { outputDir: 'allure-results', disableWebdriverStepsReporting: true, disableWebdriverScreenshotsReporting: true, addConsoleLogs: true, // Attach console logs to reports reportedEnvironmentVars: { 'NODE_VERSION': process.version, 'BROWSER': 'chrome' } }]], // ... } ``` ### Configuration Options[​](#configuration-options "Direct link to Configuration Options") * `outputDir` - defaults to `./allure-results`. After a test run is complete, you will find that this directory has been populated with an `.json` file for each spec, plus a number of `.txt` and `.png` files and other attachments. * `disableWebdriverStepsReporting` - optional parameter (`false` by default), in order to log only custom steps to the reporter. * `issueLinkTemplate` - optional parameter, in order to specify the issue link pattern. Reporter will replace `{}` placeholder with value specified in `addIssue(value)` call parameter. The same logic is applied if Cucumber is used and tag `issue` is set at any level, it will be converted to the link in the report. The parameter value example: ``` https://example.org/issue/{} ``` * `tmsLinkTemplate` - optional parameter, in order to specify TMS (Test Management System) link pattern. Reporter will replace `{}` placeholder with value specified in `addTestId(value)` call parameter. The same logic is applied if Cucumber is used and tag `testId` is set at any level, it will be converted to the link in the report. The parameter value example: ``` https://example.org/tms/{} ``` * `disableWebdriverScreenshotsReporting` - optional parameter (`false` by default), in order to not attach screenshots to the reporter. * `useCucumberStepReporter` - optional parameter (`false` by default), set it to true in order to change the report hierarchy when using cucumber. Try it for yourself and see how it looks. * `disableMochaHooks` - optional parameter (`false` by default), set it to true in order to not fetch the `before/after` stacktrace/screenshot/result hooks into the Allure Reporter. * `addConsoleLogs` - optional parameter (`false` by default), set to true in order to attach console logs from step to the reporter. * `reportedEnvironmentVars` (**type:** `Record`) - Set this option to display the environment variables in the report. Note that setting this, does not modify the actual environment variables. * `includeVersionInHistoryId` - optional parameter (`false` by default). Allure `historyId` is derived from the test title plus the browser or device family (`chrome`, `iphone 12`, …), not the worker `cid` and not the browser/OS version. That keeps trends stable when Chrome or a mobile OS updates between runs. Vendor aliases such as `Google Chrome` / `googlechrome` and `msedge` / `Microsoft Edge` are collapsed to the same family. Allure still records the full version on the test as a `browser`/`device` parameter. Set this to `true` only if you run the same test against multiple versions of the same browser or device (for example iOS 14 vs iOS 15 on an iPhone 12) and need separate history trends per version. ## Supported Allure API[​](#supported-allure-api "Direct link to Supported Allure API") ### Core API Functions[​](#core-api-functions "Direct link to Core API Functions") * `addLabel(name, value)` - assign a custom label to test * `addFeature(featureName)` – assign features to test * `addStory(storyName)` – assign user story to test * `addSeverity(value)` – assign severity to test, accepts one of these values: blocker, critical, normal, minor, trivial * `addTag(value)` – assign a tag label to test * `addEpic(value)` – assign an epic label to test * `addOwner(value)` – assign an owner label to test * `addSuite(value)` – assign a suite label to test * `addSubSuite(value)` – assign a sub suite label to test * `addParentSuite(value)` – assign a parent suite label to test * `addIssue(value)` – assign issue id to test * `addAllureId(value)` – assign allure test ops id label to test * `addTestId(value)` – assign TMS test id to test ### Attachments and Content[​](#attachments-and-content "Direct link to Attachments and Content") * `addAttachment(name, content, [type])` – save attachment to test. * `name` (*String*) - attachment name. * `content` – attachment content. * `type` (*String*, optional) – attachment MIME-type, `text/plain` by default * `addArgument(name, value)` - add an additional argument to test * `addDescription(description, [type])` – add description to test. * `description` (*String*) - description of the test. * `type` (*String*, optional) – description type, `text` by default. Values \['text', 'html','markdown'] ### Steps API[​](#steps-api "Direct link to Steps API") * `addStep(title, [{content, name = 'attachment'}], [status])` - add step to test. * `title` (*String*) - name of the step. * `content` (*String*, optional) - step attachment * `name` (*String*, optional) - step attachment name, `attachment` by default. * `status` (*String*, optional) - step status, `passed` by default. Must be "failed", "passed" or "broken" * `startStep(title)` - start with a step * `title` (*String*) - name of the step. * `endStep(status)` - end with a step * `status` (*String*, optional) - step status, `passed` by default. Must be "failed", "passed" or "broken" * `step(name, body)` - starts step with content function inside. Allows to create steps with infinite hierarchy * `body` (*Function*) - the step body async function ### Usage[​](#usage "Direct link to Usage") Allure Api can be accessed using: CJS ``` const allureReporter = require('@wdio/allure-reporter').default ``` ESM ``` import allureReporter from '@wdio/allure-reporter' ``` Mocha example ``` describe('Suite', () => { it('Case', () => { allureReporter.addFeature('Feature') }) }) ``` #### Cucumber[​](#cucumber "Direct link to Cucumber") Basic Cucumber example: ``` Given('I include feature and story name', () => { allureReporter.addFeature('Feature_name'); allureReporter.addStory('Story_name'); }) ``` #### Custom steps[​](#custom-steps "Direct link to Custom steps") `step` method simplifies dealing with steps because each step present as an async function with any content inside. The first argument of the function is the current step, that has most of the allure API methods (such as `label`, `epic`, `attach` etc): ``` allureReporter.step('my step name', async (s1) => { s1.label('foo', 'bar') await s1.step('my child step name', async (s2) => { // you can add any combination of steps in the body function }) }) ``` ##### Cucumber Tags[​](#cucumber-tags "Direct link to Cucumber Tags") Cucumber tags with special names (`issue` and `testId`) are converted to the links (the corresponding link templates must be configured before): ``` @issue=BUG-1 @testId=TST-2 Feature: This is a feature with global tags that will be converted to Allure links @issue=BUG-3 @testId=TST-4 Scenario: This is a scenario with tags that will be converted to Allure links Given I do something ``` Cucumber tags with special names (`feature`) are mapped to Allure labels: ``` Feature: Test user role @feature=login Scenario: Login Given I test login ``` ## Displaying the report[​](#displaying-the-report "Direct link to Displaying the report") The results can be consumed by any of the [reporting tools](https://allurereport.org/) offered by Allure. For example: ### Command-line[​](#command-line "Direct link to Command-line") Install the [Allure command-line tool](https://www.npmjs.com/package/allure-commandline), and process the results directory: ``` allure generate [allure_output_dir] && allure open ``` This will generate a report (by default in `./allure-report`), and open it in your browser. ### Autogenerate Report[​](#autogenerate-report "Direct link to Autogenerate Report") You can also auto-generate the report by using the Allure command line tool programmatically. To do so install the package in your project by: ``` npm i allure-commandline ``` Then add or extend your `onComplete` hook or create a [custom service](/docs/customservices.md) for this: ``` // wdio.conf.js const allure = require('allure-commandline') export const config = { // ... onComplete: function() { const reportError = new Error('Could not generate Allure report') const generation = allure(['generate', 'allure-results', '--clean']) return new Promise((resolve, reject) => { const generationTimeout = setTimeout( () => reject(reportError), 5000) generation.on('exit', function(exitCode) { clearTimeout(generationTimeout) if (exitCode !== 0) { return reject(reportError) } console.log('Allure report successfully generated') resolve() }) }) } // ... } ``` ### Jenkins[​](#jenkins "Direct link to Jenkins") Install and configure the [Allure Jenkins plugin](https://allurereport.org/docs/integrations-jenkins/) ## Add Screenshots[​](#add-screenshots "Direct link to Add Screenshots") Screenshots can be attached to the report by using the `takeScreenshot` function from WebDriverIO in the `afterTest` hook for Mocha and Jasmine or `afterStep` hook for Cucumber. First set `disableWebdriverScreenshotsReporting: false` in reporter options, then add in afterStep hook: ### Mocha / Jasmine[​](#mocha--jasmine "Direct link to Mocha / Jasmine") wdio.conf.js ``` afterTest: async function(test, context, { error, result, duration, passed, retries }) { if (error) { await browser.takeScreenshot(); } } ``` ### Cucumber[​](#cucumber-1 "Direct link to Cucumber") wdio.conf.js ``` afterStep: async function (step, scenario, { error, duration, passed }, context) { if (error) { await browser.takeScreenshot(); } } ``` As shown in the example above, when this function is called, a screenshot image will be attached to the allure report. ### Compatibility[​](#compatibility "Direct link to Compatibility") * **Allure**: Compatible with Allure Framework 3.x * **Parallel mode**: supported with Mocha and Cucumber [`parallelMode`](https://webdriver.io/docs/parallel-tests). With Mocha, `before()` and `after()` fixtures show once per test, as they run once per test. ## Getting Help[​](#getting-help "Direct link to Getting Help") * Check the [Allure documentation](https://allurereport.org/docs/) * Report issues on [Webdriverio](https://github.com/webdriverio/webdriverio/issues) or [Allure3](https://github.com/allure-framework/allure3/) --- # Introduction Welcome to the WebdriverIO API docs. These pages contain reference materials for all implemented protocol bindings and convenience commands. Protocol commands, including [WebDriver](/docs/api/webdriver.md), [WebDriver Bidi](/docs/api/webdriverBidi.md) or mobile commands like [Appium](http://appium.io) are commands that are directly send to the underlying driver backend. Convenience commands provided by the [`browser`](/docs/api/browser.md), [`element`](/docs/api/element.md) or [`mock`](/docs/api/mock.md) object offer higher level interactivity. info These are the docs for WebdriverIO **v10**. Still on v9? Use the [v9 documentation](https://v9.webdriver.io) or follow the [v10 migration guide](/docs/v10-migration.md). ## Contribute[​](#contribute "Direct link to Contribute") If you feel like you have a good example for a command, don't hesitate to open a PR and submit it. Just click on the orange link on the bottom left with the label *“Edit this page”*. Make sure you understand the way we write these docs by checking the [Contributing](https://github.com/webdriverio/webdriverio/blob/main/CONTRIBUTING.md) section. --- # Appium ## getLogTypes[​](#getlogtypes "Direct link to getLogTypes") Get available log types.

Appium command. More details can be found in the [official protocol docs](https://www.selenium.dev/documentation/webdriver/troubleshooting/logging/). ### Usage[​](#usage "Direct link to Usage") ``` await driver.getLogTypes() ``` ### Returns[​](#returns "Direct link to Returns") * **\** **`logTypes`:** The list of available log types, example: browser, driver. *** ## getLogs[​](#getlogs "Direct link to getLogs") Get the log for a given log type. Log buffer is reset after each request.

Appium command. More details can be found in the [official protocol docs](https://www.selenium.dev/documentation/webdriver/troubleshooting/logging/). ### Usage[​](#usage-1 "Direct link to Usage") ``` await driver.getLogs(type) ``` ### Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ------ | -------- | ------------ | | `type` | `string` | the log type | ### Returns[​](#returns-1 "Direct link to Returns") * **\** **`logs`:** The list of log entries. *** ## getSession[​](#getsession "Direct link to getSession") Retrieve the capabilities of the current session.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/jsonwp/#getsession). caution This protocol command is deprecated
Use `getAppiumSessionCapabilities` instead ### Usage[​](#usage-2 "Direct link to Usage") ``` await driver.getSession() ``` ### Returns[​](#returns-2 "Direct link to Returns") * **\** **`capabilities`:** An object describing the session's capabilities. *** ## getAppiumContext[​](#getappiumcontext "Direct link to getAppiumContext") Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/guides/context/). ### Usage[​](#usage-3 "Direct link to Usage") ``` await driver.getAppiumContext() ``` ### Returns[​](#returns-3 "Direct link to Returns") * **\** **`context`:** a string representing the current context or null representing 'no context' *** ## switchAppiumContext[​](#switchappiumcontext "Direct link to switchAppiumContext") Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/guides/context/). ### Usage[​](#usage-4 "Direct link to Usage") ``` await driver.switchAppiumContext(name) ``` ### Parameters[​](#parameters-1 "Direct link to Parameters") | Name | Type | Details | | ------ | -------- | ------------------------------------------ | | `name` | `string` | a string representing an available context | *** ## getAppiumContexts[​](#getappiumcontexts "Direct link to getAppiumContexts") Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/guides/context/). ### Usage[​](#usage-5 "Direct link to Usage") ``` await driver.getAppiumContexts() ``` ### Returns[​](#returns-4 "Direct link to Returns") * **\** **`contexts`:** an array of strings representing available contexts, e.g. 'WEBVIEW', or 'NATIVE' *** ## getAppiumCommands[​](#getappiumcommands "Direct link to getAppiumCommands") Retrieve the endpoints and BiDi commands supported in the current session.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#listcommands). ### Usage[​](#usage-6 "Direct link to Usage") ``` await driver.getAppiumCommands() ``` ### Returns[​](#returns-5 "Direct link to Returns") * **\** **`commands`:** Supported endpoints and BiDi commands, each grouped into common, driver-specific, and plugin-specific endpoints/commands. *** ## getAppiumExtensions[​](#getappiumextensions "Direct link to getAppiumExtensions") Retrieve the extension commands supported in the current session.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#listextensions). ### Usage[​](#usage-7 "Direct link to Usage") ``` await driver.getAppiumExtensions() ``` ### Returns[​](#returns-6 "Direct link to Returns") * **\** **`commands`:** Supported extension commands, grouped into driver-specific and plugin-specific commands. *** ## getAppiumSessionCapabilities[​](#getappiumsessioncapabilities "Direct link to getAppiumSessionCapabilities") Retrieve the capabilities of the current session.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#getappiumsessioncapabilities). ### Usage[​](#usage-8 "Direct link to Usage") ``` await driver.getAppiumSessionCapabilities() ``` ### Returns[​](#returns-7 "Direct link to Returns") * **\** **`capabilities`:** An object describing the session's capabilities. *** ## startRecordingScreen[​](#startrecordingscreen "Direct link to startRecordingScreen") Start recording the screen.

Appium command. More details can be found in the [official protocol docs](https://appium.github.io/appium.io/docs/en/commands/device/recording-screen/start-recording-screen/). ### Usage[​](#usage-9 "Direct link to Usage") ``` await driver.startRecordingScreen(options) ``` ### Parameters[​](#parameters-2 "Direct link to Parameters") | Name | Type | Details | | ------------------------- | -------- | --------------------------------------------------------------- | | `options`
*optional* | `object` | Appium driver-specific recording options (refer to driver docs) | ### Returns[​](#returns-8 "Direct link to Returns") * **\** **`response`:** Empty string, or the base64 encoded string of a previous screen recording, if forceRestart and remotePath are not set ### Support[​](#support "Direct link to Support") ![Support for XCUITest (9.3+)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) ![Support for Windows (10+)](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4OCA4OCI+PHBhdGggZD0ibTAgMTIuNDAyIDM1LjY4Ny00Ljg2MDIuMDE1NiAzNC40MjMtMzUuNjcuMjAzMTN6bTM1LjY3IDMzLjUyOS4wMjc3IDM0LjQ1My0zNS42Ny00LjkwNDEtLjAwMi0yOS43OHptNC4zMjYxLTM5LjAyNSA0Ny4zMTgtNi45MDZ2NDEuNTI3bC00Ny4zMTguMzc1NjV6bTQ3LjMyOSAzOS4zNDktLjAxMTEgNDEuMzQtNDcuMzE4LTYuNjc4NC0uMDY2My0zNC43Mzl6IiBmaWxsPSIjMDBhZGVmIi8+PC9zdmc+) * **iOS:** XCUITest (9.3+) * **Android:** UiAutomator (4.2+) * **Windows:** Windows (10+) *** ## stopRecordingScreen[​](#stoprecordingscreen "Direct link to stopRecordingScreen") Stop recording the screen.

Appium command. More details can be found in the [official protocol docs](https://appium.github.io/appium.io/docs/en/commands/device/recording-screen/stop-recording-screen/). ### Usage[​](#usage-10 "Direct link to Usage") ``` await driver.stopRecordingScreen(options) ``` ### Parameters[​](#parameters-3 "Direct link to Parameters") | Name | Type | Details | | ------------------------- | -------- | --------------------------------------------------------------- | | `options`
*optional* | `object` | Appium driver-specific recording options (refer to driver docs) | ### Returns[​](#returns-9 "Direct link to Returns") * **\** **`response`:** Base64 encoded string of the screen recording, or an empty string if the remotePath option is set ### Support[​](#support-1 "Direct link to Support") ![Support for XCUITest (9.3+)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) ![Support for Windows (10+)](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4OCA4OCI+PHBhdGggZD0ibTAgMTIuNDAyIDM1LjY4Ny00Ljg2MDIuMDE1NiAzNC40MjMtMzUuNjcuMjAzMTN6bTM1LjY3IDMzLjUyOS4wMjc3IDM0LjQ1My0zNS42Ny00LjkwNDEtLjAwMi0yOS43OHptNC4zMjYxLTM5LjAyNSA0Ny4zMTgtNi45MDZ2NDEuNTI3bC00Ny4zMTguMzc1NjV6bTQ3LjMyOSAzOS4zNDktLjAxMTEgNDEuMzQtNDcuMzE4LTYuNjc4NC0uMDY2My0zNC43Mzl6IiBmaWxsPSIjMDBhZGVmIi8+PC9zdmc+) * **iOS:** XCUITest (9.3+) * **Android:** UiAutomator (4.2+) * **Windows:** Windows (10+) *** ## rotateDevice[​](#rotatedevice "Direct link to rotateDevice") Rotate the device in three dimensions.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/mjsonwp/#setrotation). ### Usage[​](#usage-11 "Direct link to Usage") ``` await driver.rotateDevice(x, y, z) ``` ### Parameters[​](#parameters-4 "Direct link to Parameters") | Name | Type | Details | | ---- | -------- | ---------------------------------------------------- | | `x` | `number` | x offset to use for the center of the rotate gesture | | `y` | `number` | y offset to use for the center of the rotate gesture | | `z` | `number` | z offset to use for the center of the rotate gesture | ### Support[​](#support-2 "Direct link to Support") ![Support for UIAutomation (8.0 to 9.3)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) * **iOS:** UIAutomation (8.0 to 9.3) * **Android:** UiAutomator (4.2+) *** ## installApp[​](#installapp "Direct link to installApp") Install the given app onto the device.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#installapp). ### Usage[​](#usage-12 "Direct link to Usage") ``` await driver.installApp(appPath, options) ``` ### Parameters[​](#parameters-5 "Direct link to Parameters") | Name | Type | Details | | ------------------------- | -------- | ------------------------------------ | | `appPath` | `string` | Path to application .apk file | | `options`
*optional* | `object` | Driver-specific installation options | ### Support[​](#support-3 "Direct link to Support") ![Support for XCUITest (9.3+), UIAutomation (8.0 to 9.3)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) * **iOS:** XCUITest (9.3+), UIAutomation (8.0 to 9.3) * **Android:** UiAutomator (4.2+) *** ## activateApp[​](#activateapp "Direct link to activateApp") Activate the given app on the device

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#activateapp). ### Usage[​](#usage-13 "Direct link to Usage") ``` await driver.activateApp(appId, bundleId, options) ``` ### Parameters[​](#parameters-6 "Direct link to Parameters") | Name | Type | Details | | -------------------------- | -------- | ------------------------------------- | | `appId`
*optional* | `string` | App package ID (required for Android) | | `bundleId`
*optional* | `string` | Bundle ID (required for iOS) | | `options`
*optional* | `object` | Driver-specific launch options | ### Support[​](#support-4 "Direct link to Support") ![Support for XCUITest (9.3+)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) * **iOS:** XCUITest (9.3+) * **Android:** UiAutomator (4.2+) *** ## removeApp[​](#removeapp "Direct link to removeApp") Remove an app from the device.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#removeapp). ### Usage[​](#usage-14 "Direct link to Usage") ``` await driver.removeApp(appId, bundleId, options) ``` ### Parameters[​](#parameters-7 "Direct link to Parameters") | Name | Type | Details | | -------------------------- | -------- | ------------------------------------- | | `appId`
*optional* | `string` | App package ID (required for Android) | | `bundleId`
*optional* | `string` | Bundle ID (required for iOS) | | `options`
*optional* | `object` | Driver-specific uninstall options | ### Returns[​](#returns-10 "Direct link to Returns") * **\** **`didRemovalSucceed`:** Return true if uninstall was successful, false if not ### Support[​](#support-5 "Direct link to Support") ![Support for XCUITest (9.3+), UIAutomation (8.0 to 9.3)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) * **iOS:** XCUITest (9.3+), UIAutomation (8.0 to 9.3) * **Android:** UiAutomator (4.2+) *** ## terminateApp[​](#terminateapp "Direct link to terminateApp") Terminate the given app on the device

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#terminateapp). ### Usage[​](#usage-15 "Direct link to Usage") ``` await driver.terminateApp(appId, bundleId, options) ``` ### Parameters[​](#parameters-8 "Direct link to Parameters") | Name | Type | Details | | -------------------------- | -------- | ------------------------------------- | | `appId`
*optional* | `string` | App package ID (required for Android) | | `bundleId`
*optional* | `string` | Bundle ID (required for iOS) | | `options`
*optional* | `object` | Driver-specific termination options | ### Support[​](#support-6 "Direct link to Support") ![Support for XCUITest (9.3+)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) * **iOS:** XCUITest (9.3+) * **Android:** UiAutomator (4.2+) *** ## isAppInstalled[​](#isappinstalled "Direct link to isAppInstalled") Check whether the specified app is installed on the device.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#isappinstalled). ### Usage[​](#usage-16 "Direct link to Usage") ``` await driver.isAppInstalled(appId, bundleId) ``` ### Parameters[​](#parameters-9 "Direct link to Parameters") | Name | Type | Details | | -------------------------- | -------- | ------------------------------------- | | `appId`
*optional* | `string` | App package ID (required for Android) | | `bundleId`
*optional* | `string` | Bundle ID (required for iOS) | ### Returns[​](#returns-11 "Direct link to Returns") * **\** **`isAppInstalled`:** Return true if installed, false if not ### Support[​](#support-7 "Direct link to Support") ![Support for XCUITest (9.3+), UIAutomation (8.0 to 9.3)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) * **iOS:** XCUITest (9.3+), UIAutomation (8.0 to 9.3) * **Android:** UiAutomator (4.2+) *** ## queryAppState[​](#queryappstate "Direct link to queryAppState") Get the given app status on the device

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#queryappstate). ### Usage[​](#usage-17 "Direct link to Usage") ``` await driver.queryAppState(appId, bundleId) ``` ### Parameters[​](#parameters-10 "Direct link to Parameters") | Name | Type | Details | | -------------------------- | -------- | ------------------------------------- | | `appId`
*optional* | `string` | App package ID (required for Android) | | `bundleId`
*optional* | `string` | Bundle ID (required for iOS) | ### Returns[​](#returns-12 "Direct link to Returns") * **\** **`appStatus`:** 0 is not installed. 1 is not running. 2 is running in background suspended. 3 is running in background. 4 is running in foreground ### Support[​](#support-8 "Direct link to Support") ![Support for XCUITest (9.3+)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) * **iOS:** XCUITest (9.3+) * **Android:** UiAutomator (4.2+) *** ## hideKeyboard[​](#hidekeyboard "Direct link to hideKeyboard") Hide soft keyboard.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#hidekeyboard). ### Usage[​](#usage-18 "Direct link to Usage") ``` await driver.hideKeyboard(strategy, key, keyCode, keyName) ``` ### Parameters[​](#parameters-11 "Direct link to Parameters") | Name | Type | Details | | -------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `strategy`
*optional* | `string` | hide keyboard strategy (UIAutomation only), available strategies - 'press', 'pressKey', 'swipeDown', 'tapOut', 'tapOutside', 'default' | | `key`
*optional* | `string` | key value if strategy is 'pressKey' | | `keyCode`
*optional* | `string` | key code if strategy is 'pressKey' | | `keyName`
*optional* | `string` | key name if strategy is 'pressKey' | ### Support[​](#support-9 "Direct link to Support") ![Support for XCUITest (9.3+), UIAutomation (8.0 to 9.3)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) ![Support for Windows (10+)](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4OCA4OCI+PHBhdGggZD0ibTAgMTIuNDAyIDM1LjY4Ny00Ljg2MDIuMDE1NiAzNC40MjMtMzUuNjcuMjAzMTN6bTM1LjY3IDMzLjUyOS4wMjc3IDM0LjQ1My0zNS42Ny00LjkwNDEtLjAwMi0yOS43OHptNC4zMjYxLTM5LjAyNSA0Ny4zMTgtNi45MDZ2NDEuNTI3bC00Ny4zMTguMzc1NjV6bTQ3LjMyOSAzOS4zNDktLjAxMTEgNDEuMzQtNDcuMzE4LTYuNjc4NC0uMDY2My0zNC43Mzl6IiBmaWxsPSIjMDBhZGVmIi8+PC9zdmc+) * **iOS:** XCUITest (9.3+), UIAutomation (8.0 to 9.3) * **Android:** UiAutomator (4.2+) * **Windows:** Windows (10+) *** ## isKeyboardShown[​](#iskeyboardshown "Direct link to isKeyboardShown") Whether or not the soft keyboard is shown.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#iskeyboardshown). ### Usage[​](#usage-19 "Direct link to Usage") ``` await driver.isKeyboardShown() ``` ### Returns[​](#returns-13 "Direct link to Returns") * **\** **`isKeyboardShown`:** True if the keyboard is shown ### Support[​](#support-10 "Direct link to Support") ![Support for XCUITest (9.3+), UIAutomation (8.0 to 9.3)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) ![Support for Windows (10+)](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4OCA4OCI+PHBhdGggZD0ibTAgMTIuNDAyIDM1LjY4Ny00Ljg2MDIuMDE1NiAzNC40MjMtMzUuNjcuMjAzMTN6bTM1LjY3IDMzLjUyOS4wMjc3IDM0LjQ1My0zNS42Ny00LjkwNDEtLjAwMi0yOS43OHptNC4zMjYxLTM5LjAyNSA0Ny4zMTgtNi45MDZ2NDEuNTI3bC00Ny4zMTguMzc1NjV6bTQ3LjMyOSAzOS4zNDktLjAxMTEgNDEuMzQtNDcuMzE4LTYuNjc4NC0uMDY2My0zNC43Mzl6IiBmaWxsPSIjMDBhZGVmIi8+PC9zdmc+) * **iOS:** XCUITest (9.3+), UIAutomation (8.0 to 9.3) * **Android:** UiAutomator (4.2+) * **Windows:** Windows (10+) *** ## pushFile[​](#pushfile "Direct link to pushFile") Place a file onto the device in a particular place.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#pushfile). ### Usage[​](#usage-20 "Direct link to Usage") ``` await driver.pushFile(path, data) ``` ### Parameters[​](#parameters-12 "Direct link to Parameters") | Name | Type | Details | | ------ | -------- | --------------------------- | | `path` | `string` | path to install the data to | | `data` | `string` | contents of file in base64 | ### Support[​](#support-11 "Direct link to Support") ![Support for XCUITest (9.3+), UIAutomation (8.0 to 9.3)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) ![Support for Windows (10+)](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4OCA4OCI+PHBhdGggZD0ibTAgMTIuNDAyIDM1LjY4Ny00Ljg2MDIuMDE1NiAzNC40MjMtMzUuNjcuMjAzMTN6bTM1LjY3IDMzLjUyOS4wMjc3IDM0LjQ1My0zNS42Ny00LjkwNDEtLjAwMi0yOS43OHptNC4zMjYxLTM5LjAyNSA0Ny4zMTgtNi45MDZ2NDEuNTI3bC00Ny4zMTguMzc1NjV6bTQ3LjMyOSAzOS4zNDktLjAxMTEgNDEuMzQtNDcuMzE4LTYuNjc4NC0uMDY2My0zNC43Mzl6IiBmaWxsPSIjMDBhZGVmIi8+PC9zdmc+) * **iOS:** XCUITest (9.3+), UIAutomation (8.0 to 9.3) * **Android:** UiAutomator (4.2+) * **Windows:** Windows (10+) *** ## pullFile[​](#pullfile "Direct link to pullFile") Retrieve a file from the device's file system.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#pullfile). ### Usage[​](#usage-21 "Direct link to Usage") ``` await driver.pullFile(path) ``` ### Parameters[​](#parameters-13 "Direct link to Parameters") | Name | Type | Details | | ------ | -------- | ------------------------------------ | | `path` | `string` | path on the device to pull file from | ### Returns[​](#returns-14 "Direct link to Returns") * **\** **`response`:** Contents of file in base64 ### Support[​](#support-12 "Direct link to Support") ![Support for XCUITest (9.3+), UIAutomation (8.0 to 9.3)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) ![Support for Windows (10+)](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4OCA4OCI+PHBhdGggZD0ibTAgMTIuNDAyIDM1LjY4Ny00Ljg2MDIuMDE1NiAzNC40MjMtMzUuNjcuMjAzMTN6bTM1LjY3IDMzLjUyOS4wMjc3IDM0LjQ1My0zNS42Ny00LjkwNDEtLjAwMi0yOS43OHptNC4zMjYxLTM5LjAyNSA0Ny4zMTgtNi45MDZ2NDEuNTI3bC00Ny4zMTguMzc1NjV6bTQ3LjMyOSAzOS4zNDktLjAxMTEgNDEuMzQtNDcuMzE4LTYuNjc4NC0uMDY2My0zNC43Mzl6IiBmaWxsPSIjMDBhZGVmIi8+PC9zdmc+) * **iOS:** XCUITest (9.3+), UIAutomation (8.0 to 9.3) * **Android:** UiAutomator (4.2+) * **Windows:** Windows (10+) *** ## pullFolder[​](#pullfolder "Direct link to pullFolder") Retrieve a folder from the device's file system.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#pullfolder). ### Usage[​](#usage-22 "Direct link to Usage") ``` await driver.pullFolder(path) ``` ### Parameters[​](#parameters-14 "Direct link to Parameters") | Name | Type | Details | | ------ | -------- | -------------------------------------- | | `path` | `string` | path to an entire folder on the device | ### Returns[​](#returns-15 "Direct link to Returns") * **\** **`response`:** Zip file of the folder contents in base64 ### Support[​](#support-13 "Direct link to Support") ![Support for XCUITest (9.3+), UIAutomation (8.0 to 9.3)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) ![Support for Windows (10+)](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4OCA4OCI+PHBhdGggZD0ibTAgMTIuNDAyIDM1LjY4Ny00Ljg2MDIuMDE1NiAzNC40MjMtMzUuNjcuMjAzMTN6bTM1LjY3IDMzLjUyOS4wMjc3IDM0LjQ1My0zNS42Ny00LjkwNDEtLjAwMi0yOS43OHptNC4zMjYxLTM5LjAyNSA0Ny4zMTgtNi45MDZ2NDEuNTI3bC00Ny4zMTguMzc1NjV6bTQ3LjMyOSAzOS4zNDktLjAxMTEgNDEuMzQtNDcuMzE4LTYuNjc4NC0uMDY2My0zNC43Mzl6IiBmaWxsPSIjMDBhZGVmIi8+PC9zdmc+) * **iOS:** XCUITest (9.3+), UIAutomation (8.0 to 9.3) * **Android:** UiAutomator (4.2+) * **Windows:** Windows (10+) *** ## getDeviceTime[​](#getdevicetime "Direct link to getDeviceTime") Get the time on the device.

Appium command. More details can be found in the [official protocol docs](https://appium.github.io/appium.io/docs/en/commands/device/system/system-time/). ### Usage[​](#usage-23 "Direct link to Usage") ``` await driver.getDeviceTime() ``` ### Returns[​](#returns-16 "Direct link to Returns") * **\** **`time`:** Time on the device ### Support[​](#support-14 "Direct link to Support") ![Support for XCUITest (9.3+), UIAutomation (8.0 to 9.3)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) * **iOS:** XCUITest (9.3+), UIAutomation (8.0 to 9.3) * **Android:** UiAutomator (4.2+) *** ## getSettings[​](#getsettings "Direct link to getSettings") Retrieve the current session settings.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#getsettings). ### Usage[​](#usage-24 "Direct link to Usage") ``` await driver.getSettings() ``` ### Returns[​](#returns-17 "Direct link to Returns") * **\** **`settings`:** JSON hash of all the currently specified settings, see Settings API ### Support[​](#support-15 "Direct link to Support") ![Support for XCUITest (9.3+), UIAutomation (8.0 to 9.3)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) ![Support for Windows (10+)](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4OCA4OCI+PHBhdGggZD0ibTAgMTIuNDAyIDM1LjY4Ny00Ljg2MDIuMDE1NiAzNC40MjMtMzUuNjcuMjAzMTN6bTM1LjY3IDMzLjUyOS4wMjc3IDM0LjQ1My0zNS42Ny00LjkwNDEtLjAwMi0yOS43OHptNC4zMjYxLTM5LjAyNSA0Ny4zMTgtNi45MDZ2NDEuNTI3bC00Ny4zMTguMzc1NjV6bTQ3LjMyOSAzOS4zNDktLjAxMTEgNDEuMzQtNDcuMzE4LTYuNjc4NC0uMDY2My0zNC43Mzl6IiBmaWxsPSIjMDBhZGVmIi8+PC9zdmc+) * **iOS:** XCUITest (9.3+), UIAutomation (8.0 to 9.3) * **Android:** UiAutomator (4.2+) * **Windows:** Windows (10+) *** ## updateSettings[​](#updatesettings "Direct link to updateSettings") Update the session settings.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#updatesettings). ### Usage[​](#usage-25 "Direct link to Usage") ``` await driver.updateSettings(settings) ``` ### Parameters[​](#parameters-15 "Direct link to Parameters") | Name | Type | Details | | ---------- | -------- | ---------------------------------------- | | `settings` | `object` | key/value object with settings to update | ### Support[​](#support-16 "Direct link to Support") ![Support for XCUITest (9.3+), UIAutomation (8.0 to 9.3)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) ![Support for Windows (10+)](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4OCA4OCI+PHBhdGggZD0ibTAgMTIuNDAyIDM1LjY4Ny00Ljg2MDIuMDE1NiAzNC40MjMtMzUuNjcuMjAzMTN6bTM1LjY3IDMzLjUyOS4wMjc3IDM0LjQ1My0zNS42Ny00LjkwNDEtLjAwMi0yOS43OHptNC4zMjYxLTM5LjAyNSA0Ny4zMTgtNi45MDZ2NDEuNTI3bC00Ny4zMTguMzc1NjV6bTQ3LjMyOSAzOS4zNDktLjAxMTEgNDEuMzQtNDcuMzE4LTYuNjc4NC0uMDY2My0zNC43Mzl6IiBmaWxsPSIjMDBhZGVmIi8+PC9zdmc+) * **iOS:** XCUITest (9.3+), UIAutomation (8.0 to 9.3) * **Android:** UiAutomator (4.2+) * **Windows:** Windows (10+) *** ## executeDriverScript[​](#executedriverscript "Direct link to executeDriverScript") Execute a script in a child process. This approach helps minimize potential latency associated with each command. ***Using this command in Appium 2 or later requires installing the [`execute-driver`](https://github.com/appium/appium/tree/master/packages/execute-driver-plugin) plugin.***

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/plugins/#executedriverscript). ### Usage[​](#usage-26 "Direct link to Usage") ``` await driver.executeDriverScript(script, type, timeout) ``` ### Parameters[​](#parameters-16 "Direct link to Parameters") | Name | Type | Details | | ------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | | `script` | `string` | The script to execute. It has access to a 'driver' object which represents a WebdriverIO session attached to the current server. | | `type`
*optional* | `string` | The language/framework used in the script. Currently, only 'webdriverio' is supported and is the default. | | `timeout`
*optional* | `number` | The number of milliseconds the script should be allowed to run before being killed by the Appium server. Defaults to the equivalent of 1 hour. | ### Returns[​](#returns-18 "Direct link to Returns") * **\** **`result`:** An object containing two fields: 'result', which is the return value of the script itself, and 'logs', which contains 3 inner fields, 'log', 'warn', and 'error', which hold an array of strings logged by console.log, console.warn, and console.error in the script's execution. *** ## getEvents[​](#getevents "Direct link to getEvents") Get events logged in the current session.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#getlogevents). ### Usage[​](#usage-27 "Direct link to Usage") ``` await driver.getEvents(type) ``` ### Parameters[​](#parameters-17 "Direct link to Parameters") | Name | Type | Details | | ---------------------- | ------------------ | ----------------------------------------------------- | | `type`
*optional* | `string, string[]` | One or more event types to filter the returned events | ### Returns[​](#returns-19 "Direct link to Returns") * **\** **`result`:** A JSON hash of events like `{'commands' => [{'cmd' => 123455, ....}], 'startTime' => 1572954894127, }`. ### Support[​](#support-17 "Direct link to Support") ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) ![Support for XCUITest (9.3+)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) * **Android:** UiAutomator (4.2+) * **iOS:** XCUITest (9.3+) *** ## logEvent[​](#logevent "Direct link to logEvent") Log a custom event.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/appium/#logcustomevent). ### Usage[​](#usage-28 "Direct link to Usage") ``` await driver.logEvent(vendor, event) ``` ### Parameters[​](#parameters-18 "Direct link to Parameters") | Name | Type | Details | | -------- | -------- | ------------------------------------------------------- | | `vendor` | `string` | Name of the namespace (vendor) used to prefix the event | | `event` | `string` | Name of the event | ### Support[​](#support-18 "Direct link to Support") ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) ![Support for XCUITest (9.3+)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) * **Android:** UiAutomator (4.2+) * **iOS:** XCUITest (9.3+) *** ## compareImages[​](#compareimages "Direct link to compareImages") Compare two images using the specified mode of comparison. ***Using this command in Appium 2 or later requires installing the [`images`](https://github.com/appium/appium/tree/master/packages/images-plugin) plugin.***

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/plugins/#compareimages). ### Usage[​](#usage-29 "Direct link to Usage") ``` await driver.compareImages(mode, firstImage, secondImage, options) ``` ### Parameters[​](#parameters-19 "Direct link to Parameters") | Name | Type | Details | | ----------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------ | | `mode` | `string` | One of possible comparison modes: 'matchFeatures', 'getSimilarity', 'matchTemplate'. | | `firstImage` | `string` | Base64-encoded image file. | | `secondImage` | `string` | Base64-encoded image file. | | `options=[object Object]`
*optional* | `object` | The supported values of this property depend on the `mode` value. See Appium documentation for more details. | ### Returns[​](#returns-20 "Direct link to Returns") * **\** **`result`:** The content of the resulting dictionary depends on the `mode` and `options` values. See Appium documentation for more details. *** ## availableIMEEngines[​](#availableimeengines "Direct link to availableIMEEngines") List all available IME engines on the device. To use an engine, it has to be present in this list.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/jsonwp/#availableimeengines). ### Usage[​](#usage-30 "Direct link to Usage") ``` await driver.availableIMEEngines() ``` ### Returns[​](#returns-21 "Direct link to Returns") * **\** **`engines`:** A list of available engines ### Support[​](#support-19 "Direct link to Support") ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) * **Android:** UiAutomator (4.2+) *** ## getActiveIMEEngine[​](#getactiveimeengine "Direct link to getActiveIMEEngine") Get the name of the active IME engine. The name string is platform specific.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/jsonwp/#getactiveimeengine). ### Usage[​](#usage-31 "Direct link to Usage") ``` await driver.getActiveIMEEngine() ``` ### Returns[​](#returns-22 "Direct link to Returns") * **\** **`engine`:** The name of the active IME engine ### Support[​](#support-20 "Direct link to Support") ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) * **Android:** UiAutomator (4.2+) *** ## isIMEActivated[​](#isimeactivated "Direct link to isIMEActivated") Indicates whether IME input is active at the moment

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/jsonwp/#isimeactivated). ### Usage[​](#usage-32 "Direct link to Usage") ``` await driver.isIMEActivated() ``` ### Returns[​](#returns-23 "Direct link to Returns") * **\** **`isActive`:** true if IME input is available and currently active, false otherwise ### Support[​](#support-21 "Direct link to Support") ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) * **Android:** UiAutomator (4.2+) *** ## deactivateIMEEngine[​](#deactivateimeengine "Direct link to deactivateIMEEngine") De-activates the currently-active IME engine.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/jsonwp/#deactivateimeengine). ### Usage[​](#usage-33 "Direct link to Usage") ``` await driver.deactivateIMEEngine() ``` ### Support[​](#support-22 "Direct link to Support") ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) * **Android:** UiAutomator (4.2+) *** ## activateIMEEngine[​](#activateimeengine "Direct link to activateIMEEngine") Activates an IME engine.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/jsonwp/#activateimeengine). ### Usage[​](#usage-34 "Direct link to Usage") ``` await driver.activateIMEEngine(engine) ``` ### Parameters[​](#parameters-20 "Direct link to Parameters") | Name | Type | Details | | -------- | -------- | ------------------------------ | | `engine` | `string` | name of the engine to activate | ### Support[​](#support-23 "Direct link to Support") ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) * **Android:** UiAutomator (4.2+) *** ## getOrientation[​](#getorientation "Direct link to getOrientation") Get the current device orientation.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/jsonwp/#getorientation). ### Usage[​](#usage-35 "Direct link to Usage") ``` await driver.getOrientation() ``` ### Returns[​](#returns-24 "Direct link to Returns") * **\** **`orientation`:** The current orientation corresponding to a value defined in ScreenOrientation: `LANDSCAPE|PORTRAIT`. ### Support[​](#support-24 "Direct link to Support") ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) ![Support for XCUITest (9.3+)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) * **Android:** UiAutomator (4.2+) * **iOS:** XCUITest (9.3+) *** ## setOrientation[​](#setorientation "Direct link to setOrientation") Set the device orientation

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/jsonwp/#setorientation). ### Usage[​](#usage-36 "Direct link to Usage") ``` await driver.setOrientation(orientation) ``` ### Parameters[​](#parameters-21 "Direct link to Parameters") | Name | Type | Details | | ------------- | -------- | ---------------------------------------------------------------------------------- | | `orientation` | `string` | the new browser orientation as defined in ScreenOrientation: `LANDSCAPE\|PORTRAIT` | ### Support[​](#support-25 "Direct link to Support") ![Support for UiAutomator (4.2+)](/assets/images/android-d941e94d5839760141de31c8446b67ce.svg) ![Support for XCUITest (9.3+)](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjQ5Ni4yNTVweCIgaGVpZ2h0PSI2MDguNzI4cHgiIHZpZXdCb3g9IjAgMCA0OTYuMjU1IDYwOC43MjgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Ni4yNTUgNjA4LjcyODsiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIHN0eWxlPSJmaWxsOiM5OTk5OTk7IiBkPSJNMjczLjgxLDUyLjk3M0MzMTMuODA2LDAuMjU3LDM2OS40MSwwLDM2OS40MSwwczguMjcxLDQ5LjU2Mi0zMS40NjMsOTcuMzA2CgljLTQyLjQyNiw1MC45OC05MC42NDksNDIuNjM4LTkwLjY0OSw0Mi42MzhTMjM4LjI0Myw5OS44NSwyNzMuODEsNTIuOTczeiIvPgo8cGF0aCBzdHlsZT0iZmlsbDojOTk5OTk5OyIgZD0iTTI1Mi4zODUsMTc0LjY2MmMyMC41NzYsMCw1OC43NjQtMjguMjg0LDEwOC40NzEtMjguMjg0Yzg1LjU2MiwwLDExOS4yMjIsNjAuODgzLDExOS4yMjIsNjAuODgzCglzLTY1LjgzMywzMy42NTktNjUuODMzLDExNS4zMzFjMCw5Mi4xMzMsODIuMDEsMTIzLjg4NSw4Mi4wMSwxMjMuODg1cy01Ny4zMjgsMTYxLjM1Ny0xMzQuNzYyLDE2MS4zNTcKCWMtMzUuNTY1LDAtNjMuMjE1LTIzLjk2Ny0xMDAuNjg4LTIzLjk2N2MtMzguMTg4LDAtNzYuMDg0LDI0Ljg2MS0xMDAuNzY2LDI0Ljg2MUM4OS4zMyw2MDguNzMsMCw0NTUuNjY2LDAsMzMyLjYyOAoJYzAtMTIxLjA1Miw3NS42MTItMTg0LjU1NCwxNDYuNTMzLTE4NC41NTRDMTkyLjYzOCwxNDguMDc0LDIyOC40MTYsMTc0LjY2MiwyNTIuMzg1LDE3NC42NjJ6Ii8+Cjwvc3ZnPgo=) * **Android:** UiAutomator (4.2+) * **iOS:** XCUITest (9.3+) *** ## getGeoLocation[​](#getgeolocation "Direct link to getGeoLocation") Get the current geo location.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/jsonwp/#getgeolocation). ### Usage[​](#usage-37 "Direct link to Usage") ``` await driver.getGeoLocation() ``` ### Returns[​](#returns-25 "Direct link to Returns") * **\** **`location`:** The current geo location. *** ## setGeoLocation[​](#setgeolocation "Direct link to setGeoLocation") Set the current geo location.

Appium command. More details can be found in the [official protocol docs](https://appium.io/docs/en/latest/reference/api/jsonwp/#setgeolocation). ### Usage[​](#usage-38 "Direct link to Usage") ``` await driver.setGeoLocation(location) ``` ### Parameters[​](#parameters-22 "Direct link to Parameters") | Name | Type | Details | | ---------- | -------- | ---------------------------------------------------------------------------- | | `location` | `object` | the new location (`{latitude: number, longitude: number, altitude: number}`) | --- # The Browser Object **Extends:** [EventEmitter](https://nodejs.org/api/events.html#class-eventemitter) The browser object is the session instance you use to control the browser or mobile device with. If you use the WDIO test runner, you can access the WebDriver instance through the global `browser` or `driver` object or import it using [`@wdio/globals`](/docs/api/globals.md). If you use WebdriverIO in standalone mode the browser object is returned by the [`remote`](/docs/api/modules.md#remoteoptions-modifier) method. The session is initialized by the test runner. The same goes for ending the session. This is also done by the test runner process. ## Properties[​](#properties "Direct link to Properties") A browser object has the following properties: | Name | Type | Details | | ----------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `capabilities` | `Object` | Assigned capabilities from the remote server.
**Example:**``` { acceptInsecureCerts: false, browserName: 'chrome', browserVersion: '105.0.5195.125', chrome: { chromedriverVersion: '105.0.5195.52', userDataDir: '/var/folders/3_/pzc_f56j15vbd9z3r0j050sh0000gn/T/.com.google.Chrome.76HD3S' }, 'goog:chromeOptions': { debuggerAddress: 'localhost:64679' }, networkConnectionEnabled: false, pageLoadStrategy: 'normal', platformName: 'mac os x', proxy: {}, setWindowRect: true, strictFileInteractability: false, timeouts: { implicit: 0, pageLoad: 300000, script: 30000 }, unhandledPromptBehavior: 'dismiss and notify', 'webauthn:extension:credBlob': true, 'webauthn:extension:largeBlob': true, 'webauthn:virtualAuthenticators': true } ``` | | `requestedCapabilities` | `Object` | Capabilities requested from the remote server.
**Example:**``` { browserName: 'chrome' } ``` | | `sessionId` | `String` | Session id assigned from the remote server. | | `options` | `Object` | WebdriverIO [options](/docs/configuration.md) depending on how the browser object was created. See more [setup types](/docs/setuptypes.md). | | `commandList` | `String[]` | A list of commands registered to the browser instance | | `isChrome` | `Boolean` | Indicates if this Chrome instance | | `isFirefox` | `Boolean` | Indicates if this Firefox instance | | `isBidi` | `Boolean` | Indicates if this session uses Bidi | | `isSauce` | `Boolean` | Indicates if this session is Running on Sauce Labs | | `isMacApp` | `Boolean` | Indicates if this session is Running for a native Mac App | | `isWindowsApp` | `Boolean` | Indicates if this session is Running for a native Windows App | | `isMobile` | `Boolean` | Indicates a mobile session. See more under [Mobile Flags](#mobile-flags). | | `isIOS` | `Boolean` | Indicates an iOS session. See more under [Mobile Flags](#mobile-flags). | | `isAndroid` | `Boolean` | Indicates an Android session. See more under [Mobile Flags](#mobile-flags). | | `isNativeContext` | `Boolean` | Indicates if the mobile is in the `NATIVE_APP` context. See more under [Mobile Flags](#mobile-flags). | | `mobileContext` | `string` | The will provide the **current** context the driver is in, for example `NATIVE_APP`, `WEBVIEW_` for Android or `WEBVIEW_` for iOS. It will save an extra WebDriver to `driver.getContext()`. See more under [Mobile Flags](#mobile-flags). | ## Methods[​](#methods "Direct link to Methods") Based on the automation backend used for your session, WebdriverIO identifies which [Protocol Commands](/docs/api/protocols.md) will be attached to the [browser object](/docs/api/browser.md). For example if you run an automated session in Chrome, you will have access to Chromium specific commands like [`elementHover`](/docs/api/chromium.md#elementhover) but not any of the [Appium commands](/docs/api/appium.md). Furthermore WebdriverIO provides a set of convenient methods that are recommended to use, to interact with the [browser](/docs/api/browser.md) or [elements](/docs/api/element.md) on the page. In addition to that the following commands are available: | Name | Parameters | Details | | -------------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `addCommand` | - `commandName` (Type: `String`)
- `fn` (Type: `Function`)
- `attachToElement` (Type: `boolean`) | Allows to define custom commands that can be called from the browser object for composition purposes. Read more in the [Custom Command](/docs/customcommands.md) guide. | | `overwriteCommand` | - `commandName` (Type: `String`)
- `fn` (Type: `Function`)
- `attachToElement` (Type: `boolean`) | Allows to overwrite any browser command with custom functionality. Use carefully as it can confuse framework users. Read more in the [Custom Command](/docs/customcommands.md#overwriting-native-commands) guide. | | `addLocatorStrategy` | - `strategyName` (Type: `String`)
- `fn` (Type: `Function`) | Allows to define a custom selector strategy, read more in the [Selectors](/docs/selectors.md#custom-selector-strategies) guide. | ## Remarks[​](#remarks "Direct link to Remarks") ### Mobile Flags[​](#mobile-flags "Direct link to Mobile Flags") If you need to modify your test based on whether or not your session runs on a mobile device, you can access the mobile flags to check. For example, given this config: ``` // wdio.conf.js export const config = { // ... capabilities: \\{ platformName: 'iOS', app: 'net.company.SafariLauncher', udid: '123123123123abc', deviceName: 'iPhone', // ... } // ... } ``` You can access these flags in your test like so: ``` // Note: `driver` is the equivalent to the `browser` object but semantically more correct // you can choose which global variable you want to use console.log(driver.isMobile) // outputs: true console.log(driver.isIOS) // outputs: true console.log(driver.isAndroid) // outputs: false ``` This can be useful if, for example, you want to define selectors in your [page objects](/docs/pageobjects.md) based on the device type, like this: ``` // mypageobject.page.js import Page from './page' class LoginPage extends Page { // ... get username() { const selectorAndroid = 'new UiSelector().text("Cancel").className("android.widget.Button")' const selectorIOS = 'UIATarget.localTarget().frontMostApp().mainWindow().buttons()[0]' const selectorType = driver.isAndroid ? 'android' : 'ios' const selector = driver.isAndroid ? selectorAndroid : selectorIOS return $(`${selectorType}=${selector}`) } // ... } ``` You can also use these flags to run only certain tests for certain device types: ``` // mytest.e2e.js describe('my test', () => { // ... // only run test with Android devices if (driver.isAndroid) { it('tests something only for Android', () => { // ... }) } // ... }) ``` ### Events[​](#events "Direct link to Events") The browser object is an EventEmitter and a couple of events are emitted for your use cases. Here is a list of events. Keep in mind that this is not the full list of available events yet. Feel free to contribute to update the document by adding descriptions of more events here. #### `command`[​](#command "Direct link to command") This event is emitted whenever WebdriverIO sends a WebDriver Classic command. It contains the following information: * `command`: the command name, e.g. `navigateTo` * `method`: the HTTP method used to send the command request, e.g. `POST` * `endpoint`: the command endpoint, e.g. `/session/fc8dbda381a8bea36a225bd5fd0c069b/url` * `body`: the command payload, e.g. `{ url: 'https://webdriver.io' }` #### `result`[​](#result "Direct link to result") This event is emitted whenever WebdriverIO receives a result of a WebDriver Classic command. It contains the same information as the `command` event with the addition of the following information: * `result`: the command result #### `bidiCommand`[​](#bidicommand "Direct link to bidicommand") This event is emitted whenever WebdriverIO sends a WebDriver Bidi command to the browser driver. It contains information about: * `method`: WebDriver Bidi command method * `params`: associated command parameter (see [API](/docs/api/webdriverBidi.md)) * `id`: the command id, the same as in the `bidiResult` event of this command #### `bidiResult`[​](#bidiresult "Direct link to bidiresult") In case of a successful command execution, the event payload will be: * `type`: `success` * `id`: the command id * `result`: the command result (see [API](/docs/api/webdriverBidi.md)) In case of a command error, the event payload will be: * `type`: `error` * `id`: the command id * `error`: the error code, e.g. `invalid argument` * `message`: details about the error * `stacktrace`: a stack trace #### `request.start`[​](#requeststart "Direct link to requeststart") This event is fired before a WebDriver request is sent to the driver. It contains information about the request and its payload. ``` browser.on('request.start', (ev: RequestInit) => { // ... }) ``` #### `request.end`[​](#requestend "Direct link to requestend") This event is fired once the request to the driver received a response. The event object either contains the response body as result or an error if the WebDriver command failed. ``` browser.on('request.end', (ev: { result: unknown, error?: Error }) => { // ... }) ``` #### `request.retry`[​](#requestretry "Direct link to requestretry") The retry event can notify you when WebdriverIO attempts to retry running the command, e.g. due to a network issue. It contains information about the error that caused the retry and the amount of retries already done. ``` browser.on('request.retry', (ev: { error: Error, retryCount: number }) => { // ... }) ``` #### `request.performance`[​](#requestperformance "Direct link to requestperformance") This is an event to measure WebDriver level operations. Whenever WebdriverIO sends a request to the WebDriver backend, this event will be emitted with some useful information: * `durationMillisecond`: Time duration of the request in millisecond. * `error`: Error object if the request failed. * `request`: Request object. You can find url, method, headers, etc. * `retryCount`: If it's `0`, the request was the first attempt. It will increase when WebDriverIO retries under the hood. * `success`: Boolean to represent the request was succeeded or not. If it's `false`, `error` property will be provided as well. An example event: ``` Object { "durationMillisecond": 0.01770925521850586, "error": [Error: Timeout], "request": Object { ... }, "retryCount": 0, "success": false, }, ``` ### Custom Commands[​](#custom-commands "Direct link to Custom Commands") You can set custom commands on the browser scope to abstract away workflows that are commonly used. Check out our guide on [Custom Commands](/docs/customcommands.md#adding-custom-commands) for more information. --- # $ The `$` command is a short and handy way in order to fetch a single element on the page. You can also pass in an object as selector where the object contains a property `element-6066-11e4-a52e-4f735466cecf` with the value of a reference to an element. The command will then transform the reference to an extended WebdriverIO element. Note: chaining `$` and `$$` commands only make sense when you use multiple selector strategies. You will otherwise make unnecessary requests that slow down the test (e.g. `$('body').$('div')` will trigger two request whereas `$('body div')` does literally the same with just one request) **Note:** only use these element objects if you are certain they still exist on the page, e.g. using the `isExisting` command. WebdriverIO is unable to refetch them given that there are no selector information available. As of v10 this command is **strict**: if the selector resolves to more than one element it throws a `StrictSelectorError` rather than silently returning the first match. Use `$$` when you expect multiple elements, pass `{ strict: false }` to opt out for a single call, or set `strictSelectors: false` in your config to opt out globally. See the [Selectors](/docs/selectors.md#strict-mode) guide for details. Using the wdio testrunner this command is a global variable, see [Globals](https://webdriver.io/docs/api/globals) for more information. Using WebdriverIO within a [standalone](https://webdriver.io/docs/setuptypes#standalone-mode) script it will be located on the browser object instead (e.g. `browser.$$`). You can chain `$` or `$$` together without wrapping individual commands into `await` in order to walk down the DOM tree, e.g.: ``` const imageSrc = await $$('div')[1].nextElement().$$('img')[2].getAttribute('src') ``` info For more information on how to select specific elements, check out the [Selectors](/docs/selectors.md) guide. ## Usage[​](#usage "Direct link to Usage") ``` await browser.$(selector, { strict }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | -------------------------------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | `selector` | `String, Function, Matcher` | selector, JS Function, or Matcher object to fetch a certain element | | `options`
*optional* | `Object` | command options | | `options.strict`
*optional* | `Boolean` | throw if the selector matches more than one element (default: the `strictSelectors` config option, which defaults to `true`) | ## Examples[​](#examples "Direct link to Examples") example.html ``` loading... ``` [View on GitHub]() singleElements.js ``` loading... ``` [View on GitHub]() singleElements.js ``` loading... ``` [View on GitHub]() singleElements.js ``` loading... ``` [View on GitHub]() $.js ``` it('should use Androids DataMatcher or ViewMatcher selector', async () => { const menuItem = await $({ "name": "hasEntry", "args": ["title", "ViewTitle"], "class": "androidx.test.espresso.matcher.ViewMatchers" }); await menuItem.click(); const menuItem = await $({ "name": "hasEntry", "args": ["title", "ViewTitle"] }); await menuItem.click(); }); ``` ## Returns[​](#returns "Direct link to Returns") * **\** --- # $$ `$$` fetches every element that matches a selector. It returns a `WebdriverIO.ElementArray` immediately: a real array (`Array.isArray` is `true`) that stays thenable until the query finishes. `custom$$`, `react$$` and `shadow$$` return the same kind of list, including when you call them on an element (`$('parent').$$('child')`). Await the list when you want it resolved. `length` is then a number, each index is an element, and a normal `for...of` loop works: ``` const buttons = await $$('button') console.log(buttons.length) // 3 for (const button of buttons) { console.log(await button.getText()) } ``` The query does not run until something reads the list (`await`, `for await`, `.length`, an index, or an iterator method such as `map`). Until then: * `length` is a `Promise`. Use `await $$('button').length`, not `$$('button').length > 0`. * `$$('button')[0]` is a chainable element, so `await $$('button')[0].getText()` works without awaiting the list first. * `for await (const button of $$('button'))` yields each element. * `for (const button of $$('button'))` throws `Cannot synchronously iterate over an element list that has not resolved yet`. Await the list first, or use `for await`. An index past the end of the list waits and refetches until `waitforTimeout`, the same way a missing single element does. That wait still happens after the list has resolved (`const items = await $$('li'); await items[items.length]`). A [`slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice) or a `filter` does not: `$$('li').slice(0, 2)[3]` stays outside that window, and an index past a filtered list does not resolve to an element the filter excluded. `.at()` uses the same index conversion as a plain array, so `.at(1.5)` is element 1 and `.at(NaN)` is element 0. When the list still does not reach the index after that wait, the item is a "not found" element, like `$('.missing')`: `isDisplayed()` and `isExisting()` give `false`, and a matcher such as `expect($$('li')[5]).not.toBeDisplayed()` passes. A command that needs the element, for example `click()`, throws `Index out of bounds! $$(li) returned only 3 elements.` The index already waited, so that command does not wait a second time: it looks for the item once more, and uses it if the list now reaches the index. To wait for an item that can appear later, call `waitForExist()` or `expect(item).toExist()` before the command. Using the wdio testrunner this command is a global variable, see [Globals](https://webdriver.io/docs/api/globals) for more information. Using WebdriverIO within a [standalone](https://webdriver.io/docs/setuptypes#standalone-mode) script it will be located on the browser object instead (e.g. `browser.$$`). You can chain `$` or `$$` together without wrapping individual commands into `await` in order to walk down the DOM tree, e.g.: ``` const imageSrc = await $$('div')[1].nextElement().$$('img')[2].getAttribute('src') ``` ### Iterating over elements[​](#iterating-over-elements "Direct link to Iterating over elements") The list also provides asynchronous versions of the `Array` iteration methods `forEach`, `map`, `find`, `findIndex`, `some`, `every`, `filter` and `reduce`. They accept `async` callbacks and can be called on `$$` directly. `filter` and `filterSeries` return a new `ElementArray`, so the selector and the command that found the elements are kept: ``` const texts = await $$('h3').map((h3) => h3.getText()) for await (const img of $$('img')) { console.log(await img.getAttribute('src')) } ``` Every method except `reduce` also has a `*Series` variant (`forEachSeries`, `mapSeries`, and so on). The base method runs all callbacks **concurrently**, while the `*Series` variant runs **one callback at a time**, in list order. `reduce` always runs one callback at a time. Use a `*Series` variant when the order of your interactions with the page matters. The concurrent `find` and `findIndex` resolve with the first match to finish, which is not necessarily the earliest match in the list, and the concurrent `find`, `findIndex`, `some` and `every` keep running the remaining callbacks after the result is known. Use the `*Series` variant to get the earliest match and stop there. info For more information on how to select specific elements, check out the [Selectors](/docs/selectors.md) guide. ## Usage[​](#usage "Direct link to Usage") ``` await browser.$$(selector) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ---------- | ------------------ | -------------------------------------------------- | | `selector` | `String, Function` | selector or JS Function to fetch multiple elements | ## Examples[​](#examples "Direct link to Examples") example.html ``` loading... ``` [View on GitHub]() multipleElements.js ``` loading... ``` [View on GitHub]() multipleElements.js ``` loading... ``` [View on GitHub]() multipleElements.js ``` loading... ``` [View on GitHub]() ## Returns[​](#returns "Direct link to Returns") * **\** --- # action The action command is a low-level interface for providing virtualized device input actions to the web browser. For simple key presses, use [`browser.keys()`](https://webdriver.io/docs/api/browser/keys) instead. To perform multiple action chains at once, such as holding `Control` while clicking, use [`browser.actions()`](https://webdriver.io/docs/api/browser/actions). In addition to high level commands such like `scrollIntoView`, `doubleClick`, the Actions API provides granular control over exactly what designated input devices can do. WebdriverIO provides an interface for 3 kinds of input sources: * a key input for keyboard devices * a pointer input for a mouse, pen or touch devices * and wheel inputs for scroll wheel devices Every chain of action commands has to be completed calling `perform` in order to trigger the set of actions. This causes actions [to be released](https://w3c.github.io/webdriver/#release-actions) and events to be fired. You can skip this by passing in `true` (e.g. `browser.actions(...).perform(true)`). info Support for this command and specific actions can differ based on the environment. Progress on the development can be followed on [wpt.fyi](https://wpt.fyi/results/webdriver/tests/perform_actions?label=experimental\&label=master\&aligned). For mobile you might want to use Appium specific gesture commands on [iOS](https://appium.github.io/appium-xcuitest-driver/latest/guides/gestures/) and [Android](https://appium.github.io/appium-uiautomator2-driver/latest/reference/execute-methods/#gestures). ### Key input source[​](#key-input-source "Direct link to Key input source") A key input source is an input source that is associated with a keyboard-type device. It can be triggered by using the `key` type parameters. e.g.: ``` browser.action('key') ``` It returns a `KeyAction` object that supports the following actions: * `down(value: string)`: generates a key down action * `up(value: string)`: generates a key up action * `pause(ms: number)`: indicate that an input source does nothing during a particular tick #### Special Characters[​](#special-characters "Direct link to Special Characters") If you like to use special characters like e.g. `Control`, `Page Up` or `Shift`, make sure to import the [`Key`](/docs/api/modules.md#key) object from the `webdriverio` package like so: ``` import { Key } from 'webdriverio' ``` The `Key` object provides constants for all special keys including `Key.Ctrl` (cross-platform), `Key.Enter`, `Key.Tab`, `Key.ArrowLeft`, arrow keys, function keys, and more. See the [Key API docs](/docs/api/modules.md#key) for a complete list. ### Pointer input source[​](#pointer-input-source "Direct link to Pointer input source") A pointer input source is an input source that is associated with a pointer-type input device. The type can be specified when invoking the `action` command, e.g.: ``` browser.action('pointer', { parameters: { pointerType: 'mouse' } // "mouse" is default value, also possible: "pen" or "touch" }) ``` It returns a `PointerAction` object that supports the following actions: * `down (button: 'left' | 'middle' | 'right')`: creates an action to press a single key * `down (params: PointerActionParams)`: creates an action to press a single key with detailed parameters * `move (x: number, y: number)`: Creates an action for moving the pointer `x` and `y` pixels from the viewport * `move (params: PointerActionMoveParams)`: Creates an action for moving the pointer `x` and `y` pixels from the specified `origin`. The `origin` may be defined as the pointers current position (e.g. "pointer"), the viewport (e.g. "viewport") or the center of a specific element. * `up (button: 'left' | 'middle' | 'right')`: creates an action to release a single key * `up (params: PointerActionUpParams)`: creates an action to release a single key with detailed parameters * `cancel()`: An action that cancels this pointer's current input. * `pause(ms: number)`: indicate that an input source does nothing during a particular tick You can find detailed information on the [`PointerActionParams`](https://github.com/webdriverio/webdriverio/blob/8ca026c75bf7c27ef9d574f0ec48d8bc13658602/packages/webdriverio/src/utils/actions/pointer.ts#L20-L35), [`PointerActionMoveParams`](https://github.com/webdriverio/webdriverio/blob/8ca026c75bf7c27ef9d574f0ec48d8bc13658602/packages/webdriverio/src/utils/actions/pointer.ts#L20-L42) and [`PointerActionUpParams`](https://github.com/webdriverio/webdriverio/blob/8ca026c75bf7c27ef9d574f0ec48d8bc13658602/packages/webdriverio/src/utils/actions/pointer.ts#L13-L19) parameter types in the project type definition. ### Wheel input source[​](#wheel-input-source "Direct link to Wheel input source") A wheel input source is an input source that is associated with a wheel-type input device. ``` browser.action('wheel') ``` It returns a `WheelAction` object that supports the following actions: * `scroll (params: ScrollParams)`: scrolls a page to given coordinates or origin * `pause(ms: number)`: indicate that an input source does nothing during a particular tick You can find detailed information on the [`ScrollParams`](https://github.com/webdriverio/webdriverio/blob/8ca026c75bf7c27ef9d574f0ec48d8bc13658602/packages/webdriverio/src/utils/actions/wheel.ts#L4-L29) parameter type in the project type definition. ## Usage[​](#usage "Direct link to Usage") ``` browser.action() ``` ## Examples[​](#examples "Direct link to Examples") pointer-action.js ``` it('drag and drop using pointer action command', async () => { const origin = await $('#source') const targetOrigin = await $('#target') return browser.action('pointer') .move({ duration: 0, origin, x: 0, y: 0 }) .down({ button: 0 }) // left button .pause(10) .move({ duration: 0, origin: targetOrigin }) .up({ button: 0 }) .perform() }); ``` key-action.js ``` import { Key } from 'webdriverio' it('should emit key events using key action commands', async () => { const elem = await $('input') await elem.click() // make element active await browser.action('key') .down('f') .down('o') .down('o') .up('f') .up('o') .up('o') .perform() console.log(await elem.getValue()) // returns "foo" // copy value out of input element await browser.action('key') .down(Key.Ctrl).down('c') .pause(10) .up(Key.Ctrl).up('c') .perform() }) ``` wheel-action.js ``` it('should scroll using wheel action commands', async () => { console.log(await browser.execute(() => window.scrollY)) // returns 0 await browser.action('wheel').scroll({ deltaX: 0, deltaY: 500, duration: 200 }).perform() console.log(await browser.execute(() => window.scrollY)) // returns 500 }) ``` --- # actions Allows to run multiple action interactions at once, e.g. to simulate a pinch zoom or hold a modifier key while clicking. Build each action chain with [`browser.action()`](/docs/api/browser/action.md), then pass the chains to this command. ## Usage[​](#usage "Direct link to Usage") ``` await browser.actions() ``` ## Example[​](#example "Direct link to Example") action.js ``` it('run multiple actions at once for a pinch zoom', async () => { await browser.actions([ browser.action('pointer') .move(500, 500) .down() .move(250, 250) .up(), browser.action('pointer') .move(500, 500) .down() .move(750, 750) .up() ]) }); ``` --- # addCommand The browser method `addCommand` helps you to write your own set of commands. info You can find more information on adding custom commands in the [custom command](/docs/customcommands.md#adding-custom-commands) guide. ## Usage[​](#usage "Direct link to Usage") ``` browser.addCommand(name, callback, { attachToElement, disableElementImplicitWait }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ---------------------------------------------------- | ---------- | ------------------------------------------------------- | | `name` | `string` | name of the custom command | | `callback` | `Function` | function to be called | | `options`
*optional* | `Object` | options object with the following properties: | | `options.attachToElement`
*optional* | `Boolean` | extend the Element object instead of the Browser object | | `options.disableElementImplicitWait`
*optional* | `Boolean` | disable implicit wait for element commands | ## Example[​](#example "Direct link to Example") execute.js ``` // Basic usage with browser scope await browser.addCommand('getUrlAndTitle', async function (customParam) { // `this` refers to the `browser` scope return { url: await this.getUrl(), title: await this.getTitle(), customParam: customParam } }) // Element scope using options object (RECOMMENDED) await browser.addCommand('waitAndClick', async function () { // `this` refers to the `element` scope await this.waitForClickable() await this.click() }, { attachToElement: true }) // Advanced usage with options await browser.addCommand('fastClick', async function () { // `this` refers to the `element` scope await this.click() }, { attachToElement: true, disableElementImplicitWait: true // Skip implicit wait for faster execution }) //usage it('should use my add command', async () => { await browser.url('https://webdriver.io') const result = await browser.getUrlAndTitle('foobar') assert.strictEqual(result.url, 'https://webdriver.io') assert.strictEqual(result.title, 'WebdriverIO · Next-gen browser and mobile automation test framework for Node.js | WebdriverIO') assert.strictEqual(result.customParam, 'foobar') // Using element commands const element = await $('button') await element.waitAndClick() await element.fastClick() }) ``` --- # addInitScript Adds a script which would be evaluated in one of the following scenarios: * Whenever the page is navigated. * Whenever the child frame is attached or navigated. In this case, the script is evaluated in the context of the newly attached frame. The script is evaluated after the document was created but before any of its scripts were run. In order to remove the initialization script from the page again, call the function that got returned by this function. This is useful to amend the JavaScript environment, e.g. to seed Math.random. ## Usage[​](#usage "Direct link to Usage") ``` await browser.addInitScript(script, args) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | -------- | ------------------------- | ------------------------------------------------ | | `script` | `Function` | function to be injected as initialization script | | `args` | `number, string, boolean` | parameters for the script | ## Examples[​](#examples "Direct link to Examples") addInitScript.js ``` const script = await browser.addInitScript((seed) => { Math.random = () => seed }, 42) await browser.url('https://webdriver.io') console.log(await browser.execute(() => Math.random())) // returns 42 await reset() await browser.url('https://webdriver.io') console.log(await browser.execute(() => Math.random())) // returns a random number hermore you can also use the `emit` function to send data back to the Node.js environment. is useful if you want to observe certain events in the browser environment, e.g.: ``` addInitScriptWithEmit.js ``` const script = await browser.addInitScript((emit) => { const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { emit(mutation.target.nodeName) } }) observer.observe(document, { childList: true, subtree: true }) }) script.on('data', (data) => { console.log(data) // prints: BODY, DIV, P, ... }) ``` --- # back Go one step back in the joint session history of the current top-level browsing context. This is equivalent to pressing the browser back button or calling `window.history.back()`. The command takes no arguments and resolves with no value. On a WebDriver BiDi session it calls [`browsingContext.traverseHistory`](https://w3c.github.io/webdriver-bidi/#command-browsingContext-traverseHistory) with `delta: -1` for the top-level context. A frame selected with [`switchFrame`](/docs/api/browser/switchFrame.md) does not change that target. After the traversal is accepted, the command waits for the same document readiness [`url`](/docs/api/browser/url.md) maps from `pageLoadStrategy`: * `none` does not wait * `eager` waits for `browsingContext.domContentLoaded` * `normal` (the default) waits for `browsingContext.load` The wait uses the session page-load timeout (`timeouts.pageLoad`, 300000 ms when it has not been set). A same-document traversal, such as a fragment change, finishes without a load event. A back-forward cache restore commits a document that is already complete and does not emit `browsingContext.load`; the command returns once that document's `readyState` matches the strategy. A classic session posts to the WebDriver [back](/docs/api/webdriver.md#back) endpoint. There is no previous entry in either mode when the command rejects with `no such history entry`. ## Usage[​](#usage "Direct link to Usage") ``` await browser.back() ``` ## Example[​](#example "Direct link to Example") back.js ``` it('should go back and forward', async () => { await browser.url('https://webdriver.io') await browser.url('https://webdriver.io/docs/gettingstarted') await browser.back() console.log(await browser.getUrl()) // outputs the first page await browser.forward() console.log(await browser.getUrl()) // outputs the second page }); ``` --- # browsingContexts Get every open tab and window of the session as a [browsing context](/docs/api/browsingContext.md), in the order the browser reports them. This includes tabs the page opened itself, e.g. through `target="_blank"` or `window.open()`. Frames are not in this list, get them with [`frame()`](/docs/api/browsingContext/frame.md) on their tab. Only available in a WebDriver BiDi session. ## Usage[​](#usage "Direct link to Usage") ``` await browser.browsingContexts() ``` ## Example[​](#example "Direct link to Example") browsingContexts.js ``` it('finds a tab the page opened', async () => { const page = await browser.url('https://the-internet.herokuapp.com/windows') await page.$('a[href="/windows/new"]').click() const tab = await browser.waitUntil(async () => ( (await browser.browsingContexts()).find((context) => context.url.endsWith('/windows/new')) )) console.log(await tab.$('h3').getText()) // outputs: "New Window" }) ``` ## Returns[​](#returns "Direct link to Returns") * **\** **`return`:** the open tabs and windows --- # call You can use `call` to execute any async action within your test spec. It accepts promises and stops the execution until the promise has been resolved. info With WebdriverIO deprecating synchronous usage (see [RFC](https://github.com/webdriverio/webdriverio/discussions/6702)) this command is not very useful anymore. ## Usage[​](#usage "Direct link to Usage") ``` await browser.call(callback) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ---------- | ---------- | --------------------- | | `callback` | `Function` | function to be called | ## Example[​](#example "Direct link to Example") call.js ``` it('some testing here', async () => { await browser.url('http://google.com') // make an asynchronous call using any 3rd party library supporting promises // e.g. call to backend or db to inject fixture data await browser.call(() => { return somePromiseLibrary.someMethod().then(() => { // ... }) }) // example for async call to 3rd party library that doesn't support promises const result = await browser.call(() => { return new Promise((resolve, reject) => { someOtherNodeLibrary.someMethod(param1, (err, res) => { if (err) { return reject(err) } resolve(res) }) }) }) }); ``` --- # custom$ The `custom$` allows you to use a custom strategy declared by using `browser.addLocatorStrategy`. Read more on custom selector stratgies in the [Selector docs](/docs/selectors.md#custom-selector-strategies). ## Usage[​](#usage "Direct link to Usage") ``` await browser.custom$(strategyName, strategyArguments) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ------------------- | -------- | ------- | | `strategyName` | `string` | | | `strategyArguments` | `*` | | ## Examples[​](#examples "Direct link to Examples") customStrategy.js ``` loading... ``` [View on GitHub]() example.html ``` loading... ``` [View on GitHub]() customStrategy.js ``` loading... ``` [View on GitHub]() example.js ``` it('should fetch the project title', async () => { await browser.url('https://webdriver.io') browser.addLocatorStrategy('myStrat', (selector) => { return document.querySelectorAll(selector) }) const projectTitle = await browser.custom$('myStrat', '.projectTitle') console.log(await projectTitle.getText()) // WEBDRIVER I/O }) ``` ## Returns[​](#returns "Direct link to Returns") * **\** --- # custom$$ The `customs$$` allows you to use a custom strategy declared by using `browser.addLocatorStrategy`. It returns a [`WebdriverIO.ElementArray`](/docs/api/browser/$$.md), the same list as [`$$`](/docs/api/browser/$$.md): await it, or use `for await` and the async array methods before it resolves. Read more on custom selector strategies in the [Selector docs](/docs/selectors.md#custom-selector-strategies). ## Usage[​](#usage "Direct link to Usage") ``` await browser.custom$$(strategyName, strategyArguments) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ------------------- | -------- | ------- | | `strategyName` | `string` | | | `strategyArguments` | `*` | | ## Example[​](#example "Direct link to Example") example.js ``` it('should get all the plugin wrapper buttons', async () => { await browser.url('https://webdriver.io') await browser.addLocatorStrategy('myStrategy', (selector) => { return document.querySelectorAll(selector) }) const pluginWrapper = await browser.custom$$('myStrategy', '.pluginWrapper') console.log(await pluginWrapper.length) // 4 }) ``` ## Returns[​](#returns "Direct link to Returns") * **\** --- # debug This command helps you to debug your integration tests. It stops the running browser and gives you time to jump into it and check the state of your application (e.g. using dev tools). Your terminal transforms into a [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) interface that will allow you to try out certain commands, find elements and test actions on them. [![WebdriverIO REPL](https://webdriver.io/img/repl.gif)](https://webdriver.io/img/repl.gif) If you run the WDIO testrunner make sure you increase the timeout property of the test framework you are using (e.g. Mocha or Jasmine) in order to prevent test termination due to a test timeout. Also avoid executing the command with multiple capabilities running at the same time. ## Usage[​](#usage "Direct link to Usage") ``` await browser.debug() ``` ## Example[​](#example "Direct link to Example") debug.js ``` it('should demonstrate the debug command', async () => { await $('#input').setValue('FOO') await browser.debug() // jumping into the browser and change value of #input to 'BAR' const value = await $('#input').getValue() console.log(value) // outputs: "BAR" }) ``` --- # deleteCookies Delete cookies visible to the current page. By providing a cookie name it just removes the single cookie or more when multiple names are passed. ## Usage[​](#usage "Direct link to Usage") ``` await browser.deleteCookies(filter) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | -------- | ----------------------- | ------------------------------------------------------------------------------------------- | | `filter` | `StorageCookieFilter[]` | Use the filter property to identify and delete specific cookies based on matching criteria. | ## Examples[​](#examples "Direct link to Examples") example.js ``` loading... ``` [View on GitHub]() example.js ``` loading... ``` [View on GitHub]() --- # downloadFile Download a file from the remote computer running Selenium node to local file system by using the [`downloadFile`](https://webdriver.io/docs/api/selenium#downloadFile) command. info Note that this command is only supported if you use a [Selenium Grid](https://www.selenium.dev/documentation/en/grid/) with Chrome, Edge or Firefox and have the `se:downloadsEnabled` flag set in the capabilities. ## Usage[​](#usage "Direct link to Usage") ``` await browser.downloadFile(fileName, targetDirectory) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ----------------- | -------- | --------------------------------- | | `fileName` | `string` | remote path to file | | `targetDirectory` | `string` | target location on local computer | --- # emulate Emulation commands that take `contexts` require a top-level traversable. A held top-level context is its own target. On the browser it is the current top-level context, never a frame the user has switched into. ## Usage[​](#usage "Direct link to Usage") ``` await browser.emulate() ``` --- # execute Inject a snippet of JavaScript into the page for execution in the context of the currently selected frame. The executed script is assumed to be synchronous and the result of evaluating the script is returned to the client. An `async` function is awaited on both WebDriver Classic and BiDi, which replaces `executeAsync`. The script argument defines the script to execute in the form of a function body. The value returned by that function will be returned to the client. The function will be invoked with the provided args array and the values may be accessed via the arguments object in the order specified. Arguments may be any JSON-primitive, array, or JSON object. JSON objects that define a WebElement reference will be converted to the corresponding DOM element. Likewise, any WebElements in the script result will be returned to the client as WebElement JSON objects. BiDi sessions preserve `Blob` and `File` results. The value arrives in the test as a `Blob` or `File`; read it with `text()` or `arrayBuffer()`. A `Blob` or `File` nested in an array, plain object, class instance, `Map`, or `Set` is preserved the same way. A `FileList` that contains files is returned as an array of `File` objects. A cyclic reference inside a value that also contains a `Blob` or `File` is returned as `null`. ## Usage[​](#usage "Direct link to Usage") ``` await browser.execute(script, arguments) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | --------------------------- | ------------------ | ---------------------- | | `script` | `String, Function` | The script to execute. | | `arguments`
*optional* | `*` | script arguments | ## Examples[​](#examples "Direct link to Examples") execute.js ``` it('should inject javascript on the page', async () => { const result = await browser.execute((a, b, c, d) => { // browser context - you may not access client or console return a + b + c + d }, 1, 2, 3, 4) // node.js context - client and console are available console.log(result) // outputs: 10 }); ``` blob.js ``` it('should return a blob from the browser', async () => { const blob = await browser.execute(() => new Blob(['hello'], { type: 'text/plain' })) console.log(blob.type) // outputs: text/plain console.log(await blob.text()) // outputs: hello }); ``` ## Returns[​](#returns "Direct link to Returns") * **<\*>** **`return`:** The script result. --- # forward Go one step forward in the joint session history of the current top-level browsing context. This is equivalent to pressing the browser forward button or calling `window.history.forward()`. The command takes no arguments and resolves with no value. On a WebDriver BiDi session it calls [`browsingContext.traverseHistory`](https://w3c.github.io/webdriver-bidi/#command-browsingContext-traverseHistory) with `delta: 1` for the top-level context. A frame selected with [`switchFrame`](/docs/api/browser/switchFrame.md) does not change that target. After the traversal is accepted, the command waits for the same document readiness [`url`](/docs/api/browser/url.md) maps from `pageLoadStrategy`: * `none` does not wait * `eager` waits for `browsingContext.domContentLoaded` * `normal` (the default) waits for `browsingContext.load` The wait uses the session page-load timeout (`timeouts.pageLoad`, 300000 ms when it has not been set). A same-document traversal, such as a fragment change, finishes without a load event. A back-forward cache restore commits a document that is already complete and does not emit `browsingContext.load`; the command returns once that document's `readyState` matches the strategy. A classic session posts to the WebDriver [forward](/docs/api/webdriver.md#forward) endpoint. There is no next entry in either mode when the command rejects with `no such history entry`. ## Usage[​](#usage "Direct link to Usage") ``` await browser.forward() ``` ## Example[​](#example "Direct link to Example") forward.js ``` it('should go back and forward', async () => { await browser.url('https://webdriver.io') await browser.url('https://webdriver.io/docs/gettingstarted') await browser.back() await browser.forward() console.log(await browser.getUrl()) // outputs the second page }); ``` --- # getCookies Retrieve a [cookie](https://w3c.github.io/webdriver/webdriver-spec.html#cookies) visible to the current page. You can query a specific cookie by providing the cookie name or retrieve all. ## Usage[​](#usage "Direct link to Usage") ``` await browser.getCookies(filter, sourceOrigin) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | -------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `filter` | `remote.StorageCookieFilter` | an object that allows to filter for cookies with specific attributes | | `sourceOrigin` | `string, null` | an optional source origin to fetch cookies for, if not provided it will default to the current page's origin, if explicitly set to null it will fetch cookies without a partition (only supported in BiDi). Inside a parallel test, null drops only the origin; cookies stay limited to the test's user context | ## Example[​](#example "Direct link to Example") getCookies.js ``` it('should return a cookie for me', async () => { await browser.setCookies([ {name: 'test', value: '123'}, {name: 'test2', value: '456'} ]) const testCookie = await browser.getCookies({ name: 'test' }) console.log(testCookie); // outputs: [{ name: 'test', value: '123' }] const allCookies = await browser.getCookies() console.log(allCookies); // outputs: // [ // { name: 'test', value: '123' }, // { name: 'test2', value: '456' } // ] // filter cookies by domain const stagingCookies = await browser.getCookies({ domain: 'staging.myapplication.com' }) }) ``` ## Returns[​](#returns "Direct link to Returns") * **\** **`return`:** requested cookies --- # getPuppeteer Get the [Puppeteer Browser instance](https://pptr.dev/#?product=Puppeteer\&version=v5.1.0\&show=api-class-browser) to run commands with Puppeteer. Note that all Puppeteer commands are asynchronous by default so in order to interchange between sync and async execution make sure to wrap your Puppeteer calls within a `browser.call` commands as shown in the example. info Note that using Puppeteer requires support for Chrome DevTools protocol and e.g. can not be used when running automated tests in the cloud. Chrome DevTools protocol is not installed by default, use `npm install puppeteer-core` to install it. Find out more in the [Automation Protocols](/docs/automationProtocols.md) section. info Note: Puppeteer is currently **not** supported when running [component tests](/docs/component-testing.md). ## Usage[​](#usage "Direct link to Usage") ``` await browser.getPuppeteer() ``` ## Example[​](#example "Direct link to Example") getPuppeteer.test.js ``` it('should allow me to use Puppeteer', async () => { // WebDriver command await browser.url('https://webdriver.io') const puppeteerBrowser = await browser.getPuppeteer() // switch to Puppeteer const metrics = await browser.call(async () => { const pages = await puppeteerBrowser.pages() pages[0].setGeolocation({ latitude: 59.95, longitude: 30.31667 }) return pages[0].metrics() }) console.log(metrics.LayoutCount) // returns LayoutCount value }) ``` ## Returns[​](#returns "Direct link to Returns") * **\** **`return`:** initiated puppeteer instance connected to the browser --- # getWindowSize Returns browser window size. ## Usage[​](#usage "Direct link to Usage") ``` await browser.getWindowSize() ``` ## Example[​](#example "Direct link to Example") getWindowSize.js ``` it('should return browser window size', async () => { const windowSize = await browser.getWindowSize(); console.log(windowSize); // outputs `{ width: 1280, height: 767 }` }); ``` ## Returns[​](#returns "Direct link to Returns") * **\** **`return`:** `{ x, y, width, height }` for W3C or `{ width, height }` for non W3C browser --- # installExtension Same hosts `wdio session` treats as a local browser in `packages/wdio-session/src/actions/interact.ts`. ## Usage[​](#usage "Direct link to Usage") ``` await browser.installExtension() ``` --- # keys Send a sequence of key strokes to the "active" element. You can make an input element active by just clicking on it. To use special characters like "ArrowLeft", "Enter", or "Backspace", import the `Key` object from the WebdriverIO package: ``` import { Key } from 'webdriverio' ``` The `Key` object provides constants for all special keys including: * Navigation: `Key.ArrowLeft`, `Key.ArrowUp`, `Key.ArrowRight`, `Key.ArrowDown`, `Key.PageUp`, `Key.PageDown`, `Key.Home`, `Key.End` * Editing: `Key.Enter`, `Key.Tab`, `Key.Backspace`, `Key.Delete`, `Key.Insert` * Modifiers: `Key.Ctrl` (cross-platform), `Key.Shift`, `Key.Alt`, `Key.Control`, `Key.Command` * Function keys: `Key.F1` through `Key.F12` * Numpad: `Key.Numpad0` through `Key.Numpad9`, `Key.Multiply`, `Key.Add`, `Key.Subtract`, `Key.Divide` * And more: `Key.Escape`, `Key.Space`, `Key.Clear`, `Key.Pause`, etc. See the [Key API docs](/docs/api/modules.md#key) for a complete list. Modifier keys like `Control`, `Shift`, `Alt` and `Command` will stay pressed throughout the sequence and will be released at the end. To combine keyboard input with pointer actions, build separate input-source chains with [`browser.action()`](https://webdriver.io/docs/api/browser/action) and submit them together with [`browser.actions()`](https://webdriver.io/docs/api/browser/actions). Cross-Platform Modifier The `Key.Ctrl` constant provides a convenient way to use the "control" modifier across different operating systems. On macOS, it maps to the `Command` key, while on Windows and Linux it maps to the `Control` key. This is useful for keyboard shortcuts like select-all (`[Key.Ctrl, 'a']`), copy, or paste. ## Usage[​](#usage "Direct link to Usage") ``` await browser.keys(value) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ------- | ------------------ | ------------------------------------------------------------------ | | `value` | `String, String[]` | The sequence of keys to type. An array or string must be provided. | ## Example[​](#example "Direct link to Example") keys.js ``` loading... ``` [View on GitHub]() --- # mock Mock the response of a request. You can define a mock based on a matching [URLPattern](https://developer.mozilla.org/en-US/docs/Web/API/URLPattern) and corresponding header and status code. Calling the mock method returns a stub object that you can use to modify the response of the web resource. With the stub object you can then either return a custom response or have the request fail. There are 3 ways to modify the response: * return a custom JSON object (for stubbing API request) * replace web resource with a local file (serve a modified JavaScript file) or * redirect resource to a different url info Note that using the `mock` command requires support for WebDriver Bidi. That is usually the case when running tests locally in a Chromium based browser or on Firefox as well as if you use a Selenium Grid v4 or higher. If you run tests in the cloud, make sure that your cloud provider supports WebDriver Bidi. info The `URLPattern` is an experimental technology and not yet supported in some environments, e.g. Node.js. We recommend to import [a polyfill](https://www.npmjs.com/package/urlpattern-polyfill) until the feature is more widely supported. info A second `mock` with the same URL pattern and the same filter options replaces the first one: the first mock is restored, so it no longer changes requests or records calls. In a URL pattern, `*` already matches any characters, `/` included, and in a string pattern WebdriverIO changes `**` to `*`: `'**' + '/api'` and `'*' + '/api'` are the same pattern. To keep both mocks, give them different filter options. WebdriverIO does not change a `URLPattern` object: use a single `*` in it, as repeated wildcards before fixed text can make the match very slow and freeze a test. info On a [multi-remote](https://webdriver.io/docs/multiremote) browser, `mock` returns a [`MultiRemoteMock`](https://webdriver.io/docs/api/mock#multi-remote) instead of a single mock. `instances` lists the browser names, `getInstance(name)` returns that browser's mock, and `respond()`, `restore()`, and the other mock methods run on every instance. Captured requests stay on each mock: `mock.getInstance('myChromeBrowser').calls`. ## Usage[​](#usage "Direct link to Usage") ``` await browser.mock(url, { method, requestHeaders, responseHeaders, postData, statusCode }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ----------------------------------------------- | -------------------- | -------------------------------------------- | | `url` | `String, URLPattern` | url to mock | | `filterOptions`
*optional* | `MockFilterOptions` | filter mock resource by additional options | | `filterOptions.method`
*optional* | `String, Function` | filter resource by HTTP method | | `filterOptions.requestHeaders`
*optional* | `Object, Function` | filter resource by specific request headers | | `filterOptions.responseHeaders`
*optional* | `Object, Function` | filter resource by specific response headers | | `filterOptions.postData`
*optional* | `String, Function` | filter resource by request postData | | `filterOptions.statusCode`
*optional* | `Number, Function` | filter resource by response statusCode | ## Example[​](#example "Direct link to Example") mock.js ``` it('should mock network resources', async () => { // via static string const userListMock = await browser.mock('*' + '/users/list') // you can also specifying the mock even more by filtering resources // by request or response headers, status code, postData, e.g. mock only responses with specific // header set and statusCode const strictMock = await browser.mock('*', { // mock all json responses statusCode: 200, requestHeaders: { 'Content-Type': 'application/json' }, responseHeaders: { 'Cache-Control': 'no-cache' }, postData: 'foobar' }) // comparator function const apiV1Mock = await browser.mock('*' + '/api/v1', { statusCode: (statusCode) => statusCode >= 200 && statusCode <= 203, requestHeaders: (headers) => headers['Authorization'] && headers['Authorization'].startsWith('Bearer '), responseHeaders: (headers) => headers['Impersonation'], postData: (data) => typeof data === 'string' && data.includes('foo') }) }) it('should modify API responses', async () => { // filter by method const todoMock = await browser.mock('*' + '/todos', { method: 'get' }) // mock an endpoint with a fixed fixture todoMock.respond([{ title: 'Injected Todo', order: null, completed: false, url: "http://todo-backend-express-knex.herokuapp.com/916" }]) // respond with different status code or header todoMock.respond([{ title: 'Injected Todo', order: null, completed: false, url: "http://todo-backend-express-knex.herokuapp.com/916" }], { statusCode: 404, headers: { 'x-custom-header': 'foobar' } }) }) it('should modify text assets', async () => { const scriptMock = await browser.mock('*' + '/script.min.js') scriptMock.respond('./tests/fixtures/script.js') }) it('should redirect web resources', async () => { const headerMock = await browser.mock('*' + '/header.png') headerMock.respond('https://media.giphy.com/media/F9hQLAVhWnL56/giphy.gif') const pageMock = await browser.mock('https://google.com/') pageMock.respond('https://webdriver.io') await browser.url('https://google.com') console.log(await browser.getTitle()) // returns "WebdriverIO · Next-gen browser and mobile automation test framework for Node.js" }) ``` ## Returns[​](#returns "Direct link to Returns") * **\** **`return`:** a mock object to modify the response --- # mockClearAll Resets all information stored in all registered mocks of the session. ## Usage[​](#usage "Direct link to Usage") ``` await browser.mockClearAll() ``` ## Example[​](#example "Direct link to Example") mockClearAll.js ``` it('should clear all mocks', async () => { const docMock = await browser.mock('**', { headers: { 'Content-Type': 'text/html' } }) const jsMock = await browser.mock('**', { headers: { 'Content-Type': 'application/javascript' } }) await browser.url('https://guinea-pig.webdriver.io/') console.log(docMock.calls.length, jsMock.calls.length) // returns "1 4" await browser.url('https://guinea-pig.webdriver.io/') console.log(docMock.calls.length, jsMock.calls.length) // returns "2 4" (JavaScript comes from cache) await browser.mockClearAll() console.log(docMock.calls.length, jsMock.calls.length) // returns "0 0" }) ``` --- # mockRestoreAll Restores all mock information and behavior stored in all registered mocks of the session. ## Usage[​](#usage "Direct link to Usage") ``` await browser.mockRestoreAll() ``` ## Example[​](#example "Direct link to Example") mockRestoreAll.js ``` it('should restore all mocks', async () => { const googleMock = await browser.mock('https://google.com/') googleMock.respond('https://webdriver.io') const wdioMock = await browser.mock('https://webdriver.io') wdioMock.respond('http://json.org') await browser.url('https://google.com/') console.log(await browser.getTitle()) // JSON await browser.mockRestoreAll() await browser.url('https://google.com/') console.log(await browser.getTitle()) // Google }) ``` --- # navigateInContext The desired state the requested resource should be in before finishing the command. ## Usage[​](#usage "Direct link to Usage") ``` await browser.navigateInContext() ``` --- # newWindow Open a new window or tab and wait until its page has loaded, the equivalent of `window.open()`. This command does not work in mobile environments. In a WebDriver BiDi session (the default since v10) it returns the new [browsing context](/docs/api/browsingContext.md) and does not switch to it: run commands on the returned context, while `browser.url()` keeps navigating the first one. In a WebDriver Classic session the command switches to the new window and returns `{ handle, type }`. ## Usage[​](#usage "Direct link to Usage") ``` await browser.newWindow(url, { type, referenceContext }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ------------------------------------------ | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | `url` | `string` | website URL to open | | `options`
*optional* | `NewWindowOptions` | newWindow command options | | `options.type`
*optional* | `string` | type of new window: 'tab' or 'window' | | `options.referenceContext`
*optional* | `string, BrowsingContext` | top-level browsing context to open the new tab or window from (BiDi only). In parallel mode, the default is the window of the test | ## Example[​](#example "Direct link to Example") newWindow\.js ``` it('should open a new tab', async () => { const page = await browser.url('https://webdriver.io') const tab = await browser.newWindow('https://webdriver.io/docs/api', { type: 'tab' }) console.log(await tab.getTitle()) // the title of the API page console.log(await page.getTitle()) // the first tab still answers commands await tab.closeWindow() }); ``` ## Returns[​](#returns "Direct link to Returns") * **\** **`return`:** In a BiDi session, the new browsing context. In a Classic session, `{handle, type}`. ## Throws[​](#throws "Direct link to Throws") * **Error**: If `url` is invalid, if the command is used on mobile, or `type` is not 'tab' or 'window'. --- # overwriteCommand The browser method `overwriteCommand` helps you to overwrite the browser's and element's native commands like `pause` and `click`. info You can view more information on this in the [custom command](/docs/customcommands.md#overwriting-native-commands) section. ## Usage[​](#usage "Direct link to Usage") ``` browser.overwriteCommand(name, callback, { attachToElement }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ----------------------------------------- | ---------- | ------------------------------------------------------- | | `name` | `string` | name of the original command | | `callback` | `Function` | pass original function | | `options`
*optional* | `Object` | options object | | `options.attachToElement`
*optional* | `Boolean` | extend the Element object instead of the Browser object | ## Example[​](#example "Direct link to Example") execute.js ``` // print milliseconds before pause and return its value. await browser.overwriteCommand('pause', function (origPauseFunction, ms) { console.log(`Sleeping for ${ms}`) origPauseFunction(ms) return ms }) // overwrite an element command await browser.overwriteCommand('click', function (origClickFunction) { console.log('clicking') return origClickFunction() }, { attachToElement: true }) // usage it('should use my overwrite command', async () => { await browser.url('https://webdriver.io') await browser.pause(1000) // outputs "Sleeping for 1000" }) ``` --- # pause Pauses execution for a specific amount of time. It is recommended to not use this command to wait for an element to show up. In order to avoid flaky test results it is better to use commands like [`waitForExist`](/docs/api/element/waitForExist.md) or other waitFor\* commands. ## Usage[​](#usage "Direct link to Usage") ``` await browser.pause(milliseconds) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | -------------- | -------- | ---------- | | `milliseconds` | `number` | time in ms | ## Example[​](#example "Direct link to Example") pause.js ``` it('should pause the execution', async () => { const starttime = new Date().getTime() await browser.pause(3000) const endtime = new Date().getTime() console.log(endtime - starttime) // outputs: 3000 }); ``` --- # react$ The `react$` command is a useful command to query React Components by their actual name and filter them by props and state. info The command works with applications using React v16 to v19, with `createRoot` or `ReactDOM.render`. Read more about React selectors in the [Selectors](/docs/selectors.md#react-selectors) guide. ## Usage[​](#usage "Direct link to Usage") ``` await browser.react$(selector, { props, state }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ------------------------------- | --------------------------------------------- | -------------------------------------- | | `selector` | `string` | of React component | | `options`
*optional* | `ReactSelectorOptions` | React selector options | | `options.props`
*optional* | `Object` | React props the element should contain | | `options.state`
*optional* | `Array, number, string, object, boolean` | React state the element should be in | ## Example[​](#example "Direct link to Example") pause.js ``` it('should calculate 7 * 6', async () => { await browser.url('https://ahfarmer.github.io/calculator/'); const appWrapper = await $('div#root') await browser.react$('t', { props: { name: '7' } }).click() await browser.react$('t', { props: { name: 'x' } }).click() await browser.react$('t', { props: { name: '6' } }).click() await browser.react$('t', { props: { name: '=' } }).click() console.log(await $('.component-display').getText()); // prints "42" }); ``` ## Returns[​](#returns "Direct link to Returns") * **\** --- # react$$ The `react$$` command is a useful command to query multiple React Components by their actual name and filter them by props and state. It returns a [`WebdriverIO.ElementArray`](/docs/api/browser/$$.md), the same list as [`$$`](/docs/api/browser/$$.md). info The command works with applications using React v16 to v19, with `createRoot` or `ReactDOM.render`. Read more about React selectors in the [Selectors](/docs/selectors.md#react-selectors) guide. ## Usage[​](#usage "Direct link to Usage") ``` await browser.react$$(selector, { props, state }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ------------------------------- | --------------------------------------------- | -------------------------------------- | | `selector` | `string` | of React component | | `options`
*optional* | `ReactSelectorOptions` | React selector options | | `options.props`
*optional* | `Object` | React props the element should contain | | `options.state`
*optional* | `Array, number, string, object, boolean` | React state the element should be in | ## Example[​](#example "Direct link to Example") pause.js ``` it('should calculate 7 * 6', async () => { await browser.url('https://ahfarmer.github.io/calculator/'); const orangeButtons = await browser.react$$('t', { props: { orange: true } }) console.log(await orangeButtons.map((btn) => btn.getText())); // prints "[ '÷', 'x', '-', '+', '=' ]" }); ``` ## Returns[​](#returns "Direct link to Returns") * **\** --- # reloadSession Creates a new Selenium session with your current capabilities. This is useful if you test highly stateful application where you need to clean the browser session between the tests in your spec file to avoid creating hundreds of single test files with WDIO. Be careful though, this command affects your test time tremendously since spawning new Selenium sessions is very time consuming especially when using cloud services. Connection parameters such as hostname, port, protocol, etc. can be added along side browserName when you want to connect to a different remote service. This is useful in a situation, for example, where you start a test in native app and need to verify data in web app. If you start from remote service, you can pass in 0.0.0.0 for hostname if you want to switch to local drivers. ## Usage[​](#usage "Direct link to Usage") ``` await browser.reloadSession(newCapabilities) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | --------------------------------- | -------------------------- | ----------------------------------------- | | `newCapabilities`
*optional* | `WebdriverIO.Capabilities` | new capabilities to create a session with | ## Example[​](#example "Direct link to Example") reloadSync.js ``` it('should reload my session with current capabilities', async () => { console.log(browser.sessionId) // outputs: e042b3f3cd5a479da4e171825e96e655 await browser.reloadSession() console.log(browser.sessionId) // outputs: 9a0d9bf9d4864160aa982c50cf18a573 }) it('should reload my session with new capabilities', async () => { console.log(browser.capabilities.browserName) // outputs: chrome await browser.reloadSession({ browserName: 'firefox' }) console.log(browser.capabilities.browserName) // outputs: firefox }) it('should reload my session with new remote', async () => { console.log(browser.capabilities.browserName) // outputs: chrome await browser.reloadSession({ protocol: 'https', host: '0.0.0.1', port: 4444, path: '/wd/hub', browserName: 'firefox' }) console.log(browser.capabilities.browserName) // outputs: firefox }) ``` --- # restore This command restores specific or all emulated behaviors that were set using the `emulate` command. ## Usage[​](#usage "Direct link to Usage") ``` await browser.restore() ``` ## Example[​](#example "Direct link to Example") restore.js ``` before(async () => { await browser.emulate('geolocation', { latitude: 52.52, longitude: 13.405 }) await browser.emulate('userAgent', 'foobar') await browser.emulate('colorScheme', 'dark') await browser.emulate('onLine', false) }) it('should restore all emulated behavior', async () => { await browser.url('https://webdriver.io') // test within an emulated environment... }) after(async () => { // restore all emulated behavior await browser.restore() // or only restore specific emulated behavior // await browser.restore(['geolocation', 'userAgent']) }) ``` --- # savePDF Prints the page of the current browsing context to a PDF file on your OS. `savePDF(filepath, options?)` writes the PDF and returns the same bytes as a `Buffer`. `filepath` is resolved from the execution directory and must end with `.pdf`. A WebDriver BiDi session (`browser.isBidi`) renders the PDF with [`browsingContext.print`](https://w3c.github.io/webdriver-bidi/#command-browsingContext-print). That is how Chrome, Edge, and Firefox print, headed and headless. Headed and headless Chrome both return a non-empty PDF on this path. Only options you set are sent, so the browser keeps its defaults for the rest. `context` is the current top-level browsing context. If the browser rejects the command with `unsupported operation`, that error is returned as-is. The command does not fall back to Classic `printPage`. A WebDriver Classic session renders the PDF with [`printPage`](https://w3c.github.io/webdriver/#print-page). Chrome's Classic endpoint was limited to [headless mode](/docs/capabilities.md#run-browser-headless) ([crbug 753118](https://bugs.chromium.org/p/chromium/issues/detail?id=753118)). That limit is specific to Classic `printPage`. Current Chrome can also print from a headed Classic session; an older Chrome that still refuses it should use a BiDi session or run Classic Chrome headless. Lengths are centimeters. Defaults match both protocols: `portrait`, scale `1`, background `false`, shrink-to-fit `true`, page `21.59` × `27.94` cm, and margins of `1` cm. `pageRanges` entries are page numbers or range strings such as `'1-3'`. ## Usage[​](#usage "Direct link to Usage") ``` await browser.savePDF(filepath, { orientation, scale, background, width, height, top, bottom, left, right, shrinkToFit, pageRanges }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ------------------------------------- | ----------------------- | ----------------------------------------------------------------------------------------- | | `filepath` | `string` | path to the generated PDF (`.pdf` suffix is required) relative to the execution directory | | `options`
*optional* | `PDFPrintOptions` | print options, in centimeters | | `options.orientation`
*optional* | `string` | page orientation: `portrait` or `landscape`. Default: `portrait` | | `options.scale`
*optional* | `number` | page scale from `0.1` to `2`. Default: `1` | | `options.background`
*optional* | `boolean` | include the page background. Default: `false` | | `options.width`
*optional* | `number` | page width in cm. Default: `21.59` | | `options.height`
*optional* | `number` | page height in cm. Default: `27.94` | | `options.top`
*optional* | `number` | top margin in cm. Default: `1` | | `options.bottom`
*optional* | `number` | bottom margin in cm. Default: `1` | | `options.left`
*optional* | `number` | left margin in cm. Default: `1` | | `options.right`
*optional* | `number` | right margin in cm. Default: `1` | | `options.shrinkToFit`
*optional* | `boolean` | shrink the page to fit. Default: `true` | | `options.pageRanges`
*optional* | `Array` | pages to include, as numbers or range strings such as `'1-3'`. Default: `[]` | ## Example[​](#example "Direct link to Example") savePDF.js ``` it('should save a PDF of the browser view', async () => { const pdf = await browser.savePDF('./some/path/page.pdf'); console.log(pdf.subarray(0, 5).toString()); // outputs: "%PDF-" }); it('should save a landscape PDF with a custom margin', async () => { await browser.savePDF('./some/path/landscape.pdf', { orientation: 'landscape', left: 2 }); }); ``` ## Returns[​](#returns "Direct link to Returns") * **\** **`return`:** PDF buffer ## Throws[​](#throws "Direct link to Throws") * **Error**: if `filepath` is not a string ending in `.pdf`, or if `orientation` is not `portrait` or `landscape` --- # saveRecordingScreen Save a video started by [`startRecordingScreen`](/docs/api/appium.md#startrecordingscreen) command to file. info This command is only supported for mobile sessions running on [Appium](https://appium.github.io/appium.io/docs/en/commands/device/recording-screen/start-recording-screen/). ## Usage[​](#usage "Direct link to Usage") ``` await browser.saveRecordingScreen(filepath) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ---------- | -------- | ----------------------------------------------------------------------- | | `filepath` | `String` | full or relative to the execution directory path to the generated video | ## Example[​](#example "Direct link to Example") saveRecordingScreen.js ``` it('should save a video', async () => { await browser.startRecordingScreen() await $('~BUTTON').click() await browser.saveRecordingScreen('./some/path/video.mp4') }) ``` ## Returns[​](#returns "Direct link to Returns") * **\** **`return`:** video buffer --- # saveScreenshot Save a screenshot of the current browsing context to a PNG file on your OS. Be aware that some browser drivers take screenshots of the whole document (e.g. Geckodriver with Firefox) and others only of the current viewport (e.g. Chromedriver with Chrome). ## Usage[​](#usage "Direct link to Usage") ``` await browser.saveScreenshot(filepath, { fullPage, format, quality, clip }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ---------------------------------------- | --------- | ------------------------------------------------------------------------------------------- | | `filepath` | `String` | path to the generated image (`.png` suffix is required) relative to the execution directory | | `options` | `Object` | screenshot options | | `options.fullPage=false`
*optional* | `Boolean` | whether to take a screenshot of the full page or just the current viewport | | `options.format='png'`
*optional* | `String` | the format of the screenshot (either `png` or `jpeg`) | | `options.quality=100`
*optional* | `Number` | the quality of the screenshot in case of JPEG format in range 0-100 percent | | `options.clip`
*optional* | `Object` | clipping a rectangle of the screenshot | ## Examples[​](#examples "Direct link to Examples") saveScreenshot.js ``` it('should save a screenshot of the browser viewport', async () => { await browser.saveScreenshot('./some/path/screenshot.png'); }); it('should save a screenshot of the full page', async () => { await browser.saveScreenshot('./some/path/screenshot.png', { fullPage: true }); }); it('should save a screenshot of a specific rectangle', async () => { await browser.saveScreenshot('./some/path/screenshot.png', { clip: { x: 0, y: 0, width: 100, height: 100 } }); }); it('should save a screenshot of the full page in JPEG format', async () => { await browser.saveScreenshot('./some/path/screenshot.jpeg', { fullPage: true, format: 'jpeg' }); }); it('should save a screenshot of the full page in JPEG format with quality 50', async () => { await browser.saveScreenshot('./some/path/screenshot.jpeg', { fullPage: true, format: 'jpeg', quality: 50 }); }); running from a hook, make sure to explicitly define the hook as async: ``` wdio.conf.js ``` afterTest: async function(test) { await browser.saveScreenshot('./some/path/screenshot.png'); } ``` ## Returns[​](#returns "Direct link to Returns") * **\** **`return`:** screenshot buffer --- # scroll Scroll within the browser viewport. Note that `x` and `y` coordinates are relative to the current scroll positon, therefore `browser.scroll(0, 0)` is a non operation. ## Usage[​](#usage "Direct link to Usage") ``` await browser.scroll(x, y) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | --------------------- | -------- | ----------------------------------------- | | `x=0`
*optional* | `number` | horizontal scroll position (default: `0`) | | `y=0`
*optional* | `number` | vertical scroll position (default: `0`) | ## Example[​](#example "Direct link to Example") scroll.js ``` it('should demonstrate the scroll command', async () => { await browser.url('https://webdriver.io') console.log(await browser.execute(() => window.scrollY)) // returns 0 await browser.scroll(0, 200) console.log(await browser.execute(() => window.scrollY)) // returns 200 }); ``` --- # setCookies Sets one or more [cookies](https://w3c.github.io/webdriver/#cookies) for the current page. Make sure you are on the page that should receive the cookie. You can't set a cookie for an arbitrary page without being on that page. ## Usage[​](#usage "Direct link to Usage") ``` await browser.setCookies({ name, value, path, domain, secure, httpOnly, expiry, sameSite }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | --------------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | `cookie` | `Array, WebDriverCookie` | cookie object or object array. | | `cookie.name`
*optional* | `String` | The name of the cookie. | | `cookie.value`
*optional* | `String` | The cookie value. | | `cookie.path`
*optional* | `String` | The cookie path. Defaults to "/" if omitted when adding a cookie. | | `cookie.domain`
*optional* | `String` | The domain the cookie is visible to. Defaults to the current browsing context’s active document’s URL domain if omitted when adding a cookie. | | `cookie.secure`
*optional* | `Boolean` | Whether the cookie is a secure cookie. Defaults to false if omitted when adding a cookie. | | `cookie.httpOnly`
*optional* | `Boolean` | Whether the cookie is an HTTP only cookie. Defaults to false if omitted when adding a cookie. | | `cookie.expiry`
*optional* | `Number` | When the cookie expires, specified in seconds since Unix Epoch. Must not be set if omitted when adding a cookie. | | `cookie.sameSite`
*optional* | `String` | Whether the cookie applies to a SameSite policy. Defaults to None if omitted when adding a cookie. Can be set to either "Lax" or "Strict". | ## Example[​](#example "Direct link to Example") setCookies.js ``` it('should set a cookie for the page', async () => { await browser.url('/') // set a single cookie await browser.setCookies({ name: 'test1', value: 'one' // The below options are optional // path: '/foo', // The cookie path. Defaults to "/" // domain: '.example.com', // The domain the cookie is visible to. Defaults to the current browsing context’s active document’s URL domain // secure: true, // Whether the cookie is a secure cookie. Defaults to false // httpOnly: true, // Whether the cookie is an HTTP only cookie. Defaults to false // expiry: 1551393875 // When the cookie expires, specified in seconds since Unix Epoch }) // set multiple cookies await browser.setCookies([ {name: 'test2', value: 'two'}, {name: 'test3', value: 'three'} ]) const cookies = await browser.getCookies() console.log(cookies); // outputs: // [ // {name: 'test1', value: 'one', domain: 'www.example.com'}, // {name: 'test2', value: 'two', domain: 'www.example.com'}, // {name: 'test3', value: 'three', domain: 'www.example.com'} // ] }); ``` --- # setTimeout Sets the timeouts associated with the current session, timeout durations control such behaviour as timeouts on script injection, document navigation, and element retrieval. For more information and examples, see [timeouts guide](https://webdriver.io/docs/timeouts#selenium-timeouts). info It is not recommended to set `implicit` timeouts as they impact WebdriverIO's behavior and can cause errors in certain commands, e.g. `waitForExist` with reverse flag. WebDriver BiDi has no script timeout, so in a BiDi session WebdriverIO applies the `script` timeout to [`execute`](/docs/api/browser/execute.md) itself: a script that does not finish in time fails with a `script timeout` error, as with WebDriver Classic. Every BiDi command also stops after [`bidiResponseTimeout`](/docs/configuration.md#bidiresponsetimeout) (180 seconds by default), so a longer `script` timeout needs a longer `bidiResponseTimeout` too. ## Usage[​](#usage "Direct link to Usage") ``` await browser.setTimeout({ implicit, pageLoad, script }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ----------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `timeouts` | `Timeouts` | Object containing session timeout values | | `timeouts.implicit`
*optional* | `Number` | Time in milliseconds to retry the element location strategy when finding an element. | | `timeouts.pageLoad`
*optional* | `Number` | Time in milliseconds to wait for the document to finish loading. | | `timeouts.script`
*optional* | `Number` | Scripts injected with [`execute`](https://webdriver.io/docs/api/browser/execute) will run until they hit the script timeout duration, which is also given in milliseconds. Async functions are awaited and count against this timeout. | ## Example[​](#example "Direct link to Example") setTimeout.js ``` it('should change timeout duration for session with long code duration', async () => { await browser.setTimeout({ 'pageLoad': 10000, 'script': 60000 }); // Execute code which takes a long time await browser.execute(async () => { console.log('Wake me up before you go!'); await new Promise((resolve) => setTimeout(resolve, 59000)); }); }); ``` --- # setViewport Resizes the browser viewport within the browser. As oppose to `setWindowSize`, this command changes the viewport size, not the window size. ## Usage[​](#usage "Direct link to Usage") ``` await browser.setViewport({ width, height, devicePixelRatio }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | -------------------------- | -------------------- | --------------------------- | | `options` | `SetViewportOptions` | command arguments | | `options.width` | `number` | viewport width in pixels | | `options.height` | `number` | viewport height in pixels | | `options.devicePixelRatio` | `number` | pixel ratio of the viewport | ## Returns[​](#returns "Direct link to Returns") * **<`Promise`>** --- # setWindowSize Resizes browser window outer size according to provided width and height. Based on your operating system some browser windows might now allow you so have a smaller width than `500px`. If you want to mimic the viewport of e.g. an iPhone you should consider using the `setViewport` command. ## Usage[​](#usage "Direct link to Usage") ``` await browser.setWindowSize(width, height) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | -------- | -------- | ------------------------------------------ | | `width` | `number` | browser will be resized to provided width | | `height` | `number` | browser will be resized to provided height | ## Returns[​](#returns "Direct link to Returns") * **\** **`return`:** Null for *NO*W3C browser and Object `{x, y, width, height}` for W3C browser --- # switchFrame Switch the Classic session into a frame. In a WebDriver BiDi session this command throws. Hold the browsing context from `browser.url()` or `browser.newWindow()` and call `context.frame()`. `context.parent` is the frame you came from. There is no `switchFrame(null)`. In a Classic session, pass an element or `null` for the top frame. A string or a function is rejected. ## Usage[​](#usage "Direct link to Usage") ``` await browser.switchFrame(context) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | --------- | --------------- | --------------------------------------------------------- | | `context` | `Element, null` | frame element, or `null` for the top frame (Classic only) | ## Example[​](#example "Direct link to Example") switchFrame.js ``` // Classic await browser.switchFrame($('iframe')) await browser.switchFrame(null) // BiDi const page = await browser.url('https://example.com') const child = await page.frame('iframe') console.log(await child.getTitle()) ``` ## Returns[​](#returns "Direct link to Returns") * **\** --- # switchWindow Switch focus to a particular tab / window (Classic sessions). In a WebDriver BiDi session this command throws. `browser.url()` and `browser.newWindow()` return the browsing context, and `browser.browsingContexts()` lists the open top-level contexts. Commands run on the context you hold. ## Usage[​](#usage "Direct link to Usage") ``` await browser.switchWindow(matcher) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | --------- | ---------------- | ------------------------------------------------------------------------------------------------------------- | | `matcher` | `String, RegExp` | String or regular expression that matches either the page title or URL, the window name, or the window handle | ## Example[​](#example "Direct link to Example") switchWindow\.js ``` it('should switch to another window', async () => { // Classic await browser.url('https://google.com') const handle = await browser.getWindowHandle() await browser.newWindow('https://webdriver.io') await browser.switchWindow('google.com') await browser.switchWindow(handle) // BiDi const google = await browser.url('https://google.com') const docs = await browser.newWindow('https://webdriver.io') console.log(await docs.getTitle()) console.log(await google.getTitle()) }); ``` --- # throttleCPU Throttles the CPU to emulate a slower processor. info Note that using the `throttleCPU` command requires support for Chrome DevTools protocol and e.g. can not be used when running automated tests in the cloud. Chrome DevTools protocol is not installed by default, use `npm install puppeteer-core` to install it. Find out more in the [Automation Protocols](/docs/automationProtocols.md) section. ## Usage[​](#usage "Direct link to Usage") ``` await browser.throttleCPU(factor) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | -------- | -------- | --------------------------------------------------------- | | `factor` | `number` | slowdown factor (1 is no throttle, 2 is 2x slowdown, etc) | ## Example[​](#example "Direct link to Example") throttleCPU.js ``` it('should throttle the CPU', async () => { await browser.throttleCPU(2) // 2x slowdown }); ``` --- # throttleNetwork Throttle the network capabilities of the browser. This can help to emulate certain scenarios where a user loses their internet connection and your app needs to address that. There are many presets available with default configurations for ease of use. They are `offline`, `GPRS`, `Regular2G`, `Good2G`, `Regular3G`, `Good3G`, `Regular4G`, `DSL`, `WiFi`, `online`. You can see the values for these presets [in the source code](https://github.com/webdriverio/webdriverio/blob/6824e4eb118a8d20685f12f4bc42f13fd56f8a25/packages/webdriverio/src/commands/browser/throttleNetwork.js#L29). info Service workers initiate requests through their own network stack. This command applies the throttling conditions to every service worker that is registered at the time of the call. If your app registers a service worker afterwards, call `throttleNetwork` again to cover it. Note that using the `throttleNetwork` command requires support for Chrome DevTools protocol and e.g. can not be used when running automated tests in the cloud. Chrome DevTools protocol is not installed by default, use `npm install puppeteer-core` to install it. Find out more in the [Automation Protocols](/docs/automationProtocols.md) section. ## Usage[​](#usage "Direct link to Usage") ``` await browser.throttleNetwork({ offline, latency, downloadThroughput, uploadThroughput }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | --------------------------- | ----------------- | ------------------------------------------------------------------------------------ | | `params` | `ThrottleOptions` | parameters for throttling | | `params.offline` | `boolean` | True to emulate internet disconnection. | | `params.latency` | `number` | Minimum latency from request sent to response headers received (ms). | | `params.downloadThroughput` | `number` | Maximal aggregated download throughput (bytes/sec). -1 disables download throttling. | | `params.uploadThroughput` | `number` | Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling. | ## Example[​](#example "Direct link to Example") throttleNetwork.js ``` it('should throttle the network', async () => { // via static string preset await browser.throttleNetwork('Regular3G') // via custom values await browser.throttleNetwork({ offline: false, downloadThroughput: 200 * 1024 / 8, uploadThroughput: 200 * 1024 / 8, latency: 20 }) }); ``` --- # uninstallExtension Uninstall a web extension that was installed with [`installExtension`](/docs/api/browser/installExtension.md). Pass the extension id string that `installExtension` returned. There is no restore-function wrapper: the id is what you keep, and this command matches [`webExtension.uninstall`](https://w3c.github.io/webdriver-bidi/#command-webExtension-uninstall). ## Usage[​](#usage "Direct link to Usage") ``` await browser.uninstallExtension(extensionId) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ------------- | -------- | ------------------------------------------- | | `extensionId` | `string` | extension id returned by `installExtension` | ## Example[​](#example "Direct link to Example") uninstallExtension.js ``` const id = await browser.installExtension('./dist') await browser.uninstallExtension(id) ``` --- # url The `url` command loads an URL in the browser. If a baseUrl is specified in the config, it will be prepended to the url parameter using node's url.resolve() method. Calling `browser.url('...')` with the same url as last time will trigger a page reload. However, if the url contains a hash, the browser will not trigger a new navigation and the user has to [refresh](/docs/api/webdriver.md#refresh) the page to trigger one. In a WebDriver BiDi session the command returns the browsing context it navigated. That is the session's initial top-level context: a later `browser.url()` navigates the same context, and load metadata is `context.request`. In a Classic session the command still returns `void`. `context.request` contains information about the request and response data of the page load: ``` interface WebdriverIO.Request { id?: string url: string timestamp: number navigation?: string redirectChain?: string[], headers: Record cookies?: NetworkCookie[] \/** * Error message if request failed *\/ error?: string response?: { fromCache: boolean headers: Record mimeType: string status: number }, /** * List of all requests that were made due to the main request. * Note: the list may be incomplete and does not contain request that were * made after the command has finished. * * The property will be undefined if the request is not a document request * that was initiated by the browser. *\/ children?: Request[] } ``` The command supports the following options: note These features unfortunately won't be available to you if your remote environment doesn't support WebDriver Bidi. You can check if Bidi is support in your session by looking into the `browser.isBidi` property. ### wait[​](#wait "Direct link to wait") The desired state the requested resource should be in before finishing the command. It supports the following states: * `none`: no wait after the page request is made and the response is received * `interactive`: wait until the page is interactive * `complete`: wait until the DOM tree of the page is fully loaded * `networkIdle`: wait until there are no pending network requests ### headers[​](#headers "Direct link to headers") Headers to be sent with the request. **Default:** `{}` ### auth[​](#auth "Direct link to auth") Basic authentication credentials. Note: this will overwrite the existing `Authorization` header if provided in the `headers` option. ### timeout[​](#timeout "Direct link to timeout") If set to a number, the command will wait for the specified amount of milliseconds for the page to load all responses before returning. Note: for this to have an impact, it requires the `wait` option to be set to `networkIdle`. **Default:** `5000` ## Usage[​](#usage "Direct link to Usage") ``` await browser.url(url, { wait, timeout, onBeforeLoad, auth, headers }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | -------------------------------------- | -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `url`
*optional* | `string` | the URL to navigate to | | `options`
*optional* | `UrlOptions` | navigation options | | `options.wait`
*optional* | `'none', 'interactive', 'networkIdle', 'complete'` | The desired state the requested resource should be in before finishing the command. Default: 'complete' | | `options.timeout`
*optional* | `number` | If set to a number, the command will wait for the specified amount of milliseconds for the page to load
all responses before returning. Default: 5000 | | `options.onBeforeLoad`
*optional* | `Function` | A function that is being called before your page has loaded all of its resources. It allows you to easily
mock the environment, e.g. overwrite Web APIs that your application uses. | | `options.auth`
*optional* | `{user: string, pass: string}` | basic authentication credentials | | `options.headers`
*optional* | `Record` | headers to be sent with the request | ## Examples[​](#examples "Direct link to Examples") url.js ``` // navigate to a new URL const context = await browser.url('https://webdriver.io'); console.log(context.url); // outputs: "https://webdriver.io" console.log(context.request?.response?.status); // outputs: 200 console.log(context.request?.response?.headers); // outputs: { 'content-type': 'text/html; charset=UTF-8' } ``` baseUrlResolutions.js ``` // With a base URL of http://example.com/site, the following url parameters resolve as such: // When providing a scheme: // https://webdriver.io await browser.url('https://webdriver.io'); // When not starting with a slash, the URL resolves relative to the baseUrl // http://example.com/site/relative await browser.url('relative'); // When starting with a slash, the URL resolves relative to the root path of the baseUrl // http://example.com/rootRelative await browser.url('/rootRelative'); ``` basicAuth.js ``` // navigate to a URL with basic authentication await browser.url('https://the-internet.herokuapp.com/basic_auth', { auth: { user pass } }); await expect($('p=Congratulations! You must have the proper credentials.').toBeDisplayed(); ``` onBeforeLoad.js ``` // navigate to a URL and mock the battery API await browser.url('https://pazguille.github.io/demo-battery-api/', { onBeforeLoad (win) { // mock "navigator.battery" property // returning mock charge object win.navigator.getBattery = () => Promise.resolve({ level: 0.5, charging: false, chargingTime: Infinity, dischargingTime: 3600, // seconds }) } }) // now we can assert actual text - we are charged at 50% await expect($('.battery-percentage')).toHaveText('50%') // and has enough juice for 1 hour await expect($('.battery-remaining')).toHaveText('01:00) ``` ## Returns[​](#returns "Direct link to Returns") * **\** **`returns`:** the [browsing context](/docs/api/browsingContext.md) that was navigated. In a WebDriver Classic --- # waitUntil This wait command is your universal weapon if you want to wait on something. It expects a condition and waits until that condition is fulfilled with a truthy value to be returned. A common example is to wait until a certain element contains a certain text (see example). ## Usage[​](#usage "Direct link to Usage") ``` await browser.waitUntil(condition, { timeout, timeoutMsg, interval }) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | ------------------------------------ | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `condition` | `Function` | condition to wait on until returning a truthy value | | `options`
*optional* | `WaitUntilOptions` | command options | | `options.timeout`
*optional* | `Number` | time in ms (default set based on [`waitforTimeout`](/docs/configuration.md#waitfortimeout) config value) | | `options.timeoutMsg`
*optional* | `String, Function` | error message to throw when waitUntil times out. A function is evaluated only after the timeout, so the message can include state from that moment. | | `options.interval`
*optional* | `Number` | interval between condition checks (default set based on [`waitforInterval`](/docs/configuration.md#waitforinterval) config value) | ## Examples[​](#examples "Direct link to Examples") index.html ``` loading... ``` [View on GitHub]() waitUntilExample.js ``` loading... ``` [View on GitHub]() ## Returns[​](#returns "Direct link to Returns") * **\** **`return`:** true if condition is fulfilled --- # The BrowsingContext Object A browsing context is a tab, a window or a frame that you hold as an object. Commands you call on it run in that tab or frame, while the session and every other context stay where they are. Since v10 this is how WebdriverIO works with tabs, windows and frames in a WebDriver BiDi session, and it replaces `switchWindow()` and `switchFrame()` there. test/specs/tabs.e2e.ts ``` import { browser, expect } from '@wdio/globals' describe('browsing contexts', () => { it('works with two tabs and a frame at the same time', async () => { const page = await browser.url('https://the-internet.herokuapp.com/nested_frames') const docs = await browser.newWindow('https://webdriver.io/docs/api', { type: 'tab' }) const top = await page.frame({ selector: 'frame[name="frame-top"]' }) const middle = await top.frame({ selector: 'frame[name="frame-middle"]' }) await expect(middle.$('#content')).toHaveText('MIDDLE') await expect(docs.$('h1')).toBeDisplayed() console.log(await page.getTitle(), await docs.getTitle()) }) }) ``` ## Get a browsing context[​](#get-a-browsing-context "Direct link to Get a browsing context") | Call | Returns | | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | [`browser.url(url)`](/docs/api/browser/url.md) | The session's first top-level context, after navigating it. `browser.url()` always navigates this one. | | [`browser.newWindow(url, { type })`](/docs/api/browser/newWindow.md) | A new tab (`type: 'tab'`) or window, once its page has loaded. The session does not switch to it. | | [`browser.browsingContexts()`](/docs/api/browser/browsingContexts.md) | Every open top-level context (tabs and windows, not frames), e.g. a tab the page opened itself. | | [`context.frame(query)`](/docs/api/browsingContext/frame.md) | A frame of a context, also cross-origin and nested ones. | Hold on to the object and call commands on it. There is no "current" tab or frame to switch between, so contexts can also be used in parallel: ``` const [titleA, titleB] = await Promise.all([pageA.getTitle(), pageB.getTitle()]) ``` ## WebDriver BiDi and Classic sessions[​](#webdriver-bidi-and-classic-sessions "Direct link to WebDriver BiDi and Classic sessions") Browsing contexts need a WebDriver BiDi session, which is the default since v10 for Chrome, Edge and Firefox. In a WebDriver Classic session, e.g. with Appium or Safari, there is only the session's current context. There: * `browser.url()` returns a stand-in for the browser. Commands like `$`, `execute` or `getTitle` run on the browser, `url`, `isFrame` and `parent` describe the current page, and `contextId` is `undefined`. * `frame()`, `navigate()` and `activate()` reject and name the Classic command to use instead: [`browser.switchFrame()`](/docs/api/browser/switchFrame.md), [`browser.url()`](/docs/api/browser/url.md) or [`browser.switchWindow()`](/docs/api/browser/switchWindow.md). Check `browser.isBidi` when the same code runs in both kinds of session. ## Properties[​](#properties "Direct link to Properties") | Name | Type | Details | | -------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `contextId` | `String` | The WebDriver BiDi browsing context id. `undefined` in a Classic session. | | `url` | `String` | The URL the context was last navigated to with `browser.url()`, `navigate()` or `newWindow()`. Navigations the page does itself (links, `location`, `history.pushState`) only show after [`getUrl()`](/docs/api/browsingContext/getUrl.md). | | `isFrame` | `Boolean` | `true` for a frame, `false` for a tab or window. | | `parent` | `BrowsingContext \| undefined` | For a frame, the context `frame()` was called on (or the frame in between, for a frame nested deeper). `undefined` for a tab or window. | | `browser` | `Browser` | The [browser object](/docs/api/browser.md) of the session. | | `request` | `Request \| undefined` | Load information of the last navigation through `browser.url()` or `navigate()`: URL, headers, response, redirects and the requests the page made. | | `sessionId` | `String` | Session id, the same as `browser.sessionId`. | | `capabilities` | `Object` | Session capabilities, the same as `browser.capabilities`. | | `options` | `Object` | WebdriverIO options, the same as `browser.options`. | | `isBidi` | `Boolean` | Whether the session uses WebDriver BiDi. | | `isMobile` | `Boolean` | Whether the session automates a mobile device. | ## Methods[​](#methods "Direct link to Methods") ### Commands of a browsing context[​](#commands-of-a-browsing-context "Direct link to Commands of a browsing context") These commands act on the context they are called on. Each has its own reference page. | Command | Details | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | [`frame`](/docs/api/browsingContext/frame.md) | Get a frame of this context as a browsing context of its own. | | [`navigate`](/docs/api/browsingContext/navigate.md) | Navigate this context, with the same options as `browser.url()`. | | [`refresh`](/docs/api/browsingContext/refresh.md) | Reload this context. A frame reloads only its own document. | | [`back`](/docs/api/browsingContext/back.md) / [`forward`](/docs/api/browsingContext/forward.md) | Move through the history of this tab or window. | | [`activate`](/docs/api/browsingContext/activate.md) | Bring this tab or window to the front. | | [`closeWindow`](/docs/api/browsingContext/closeWindow.md) | Close this tab or window. | | [`getTitle`](/docs/api/browsingContext/getTitle.md) / [`getUrl`](/docs/api/browsingContext/getUrl.md) | Read the title or URL of the document shown in this context. | | [`acceptAlert`](/docs/api/browsingContext/acceptAlert.md) / [`dismissAlert`](/docs/api/browsingContext/dismissAlert.md) / [`getAlertText`](/docs/api/browsingContext/getAlertText.md) | Answer or read the user prompt open in this context. | ### Browser commands that run in a context[​](#browser-commands-that-run-in-a-context "Direct link to Browser commands that run in a context") These are the [browser commands](/docs/api/browser.md) of the same name, applied to this context instead of the session's first one. They take the same arguments. | Command | In a browsing context | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | | [`$`](/docs/api/browser/$.md), [`$$`](/docs/api/browser/$$.md), [`custom$`](/docs/api/browser/custom$.md), [`custom$$`](/docs/api/browser/custom$$.md), [`react$`](/docs/api/browser/react$.md), [`react$$`](/docs/api/browser/react$$.md) | Find elements in this context's document. | | [`execute`](/docs/api/browser/execute.md) | Run a script in this context's document. | | [`action`](/docs/api/browser/action.md), [`actions`](/docs/api/browser/actions.md), [`keys`](/docs/api/browser/keys.md), [`scroll`](/docs/api/browser/scroll.md) | Send input to this context, also when it is a background tab. | | [`saveScreenshot`](/docs/api/browser/saveScreenshot.md), [`savePDF`](/docs/api/browser/savePDF.md) | Capture this context. | | [`getCookies`](/docs/api/browser/getCookies.md), [`setCookies`](/docs/api/browser/setCookies.md), [`deleteCookies`](/docs/api/browser/deleteCookies.md) | Read and change the cookies of this context's storage partition. | | [`setViewport`](/docs/api/browser/setViewport.md) | Resize the viewport of this tab or window. | | [`addInitScript`](/docs/api/browser/addInitScript.md) | Run a script before the page scripts, in this tab or window only. | | [`mock`](/docs/api/browser/mock.md), [`mockClearAll`](/docs/api/browser/mockClearAll.md), [`mockRestoreAll`](/docs/api/browser/mockRestoreAll.md) | Mock the requests of this tab or window only. A mock ends when its tab closes. | | [`emulate`](/docs/api/browser/emulate.md) | Emulate a device property, e.g. geolocation or the clock, in this tab or window only. | | [`restore`](/docs/api/browser/restore.md) | Restore emulations, the same as `browser.restore()`. | | [`waitUntil`](/docs/api/browser/waitUntil.md), [`pause`](/docs/api/browser/pause.md) | The same as on the browser. | test/specs/mock.e2e.ts ``` import { browser, expect } from '@wdio/globals' it('mocks the requests of one tab only', async () => { const page = await browser.url('https://webdriver.io') const tab = await browser.newWindow('https://webdriver.io', { type: 'tab' }) const mock = await tab.mock('**/api/users') mock.respond([{ name: 'Mocked user' }]) // requests of `tab` get the mocked response, requests of `page` reach the server }) ``` ### Top-level only[​](#top-level-only "Direct link to Top-level only") A frame shares its tab's history, viewport, network and emulation, so these commands reject on a frame with `` `` is only available on a top-level browsing context ``. Call them on the tab: `frame.parent` until `parent` is `undefined`, or the context you called `frame()` on. `back`, `forward`, `activate`, `closeWindow`, `setViewport`, `addInitScript`, `mock`, `mockClearAll`, `mockRestoreAll`, `emulate`, `restore` ### Not available on a browsing context[​](#not-available-on-a-browsing-context "Direct link to Not available on a browsing context") Session commands, such as `deleteSession`, `newWindow` or `browsingContexts`, are only on the [browser object](/docs/api/browser.md). Custom commands are too: [`addCommand`](/docs/customcommands.md) and `overwriteCommand` reject on a context, register them on `browser`. ### Events[​](#events "Direct link to Events") `on`, `once`, `off`, `emit`, `removeListener` and `removeAllListeners` register listeners on the browser, so the events are those of the whole session. For example, a [`dialog`](/docs/api/dialog.md) event fires for a prompt in any tab or frame. ## Elements of a browsing context[​](#elements-of-a-browsing-context "Direct link to Elements of a browsing context") An element you get through a context belongs to that context. Element commands such as `click`, `setValue` or `getText` run in that context's document, also when it is a background tab or a frame. They follow the WebDriver spec like the drivers do, so they return the same results and the same errors (e.g. `element click intercepted`) as for an element of the page in front. `getComputedRole` and `getComputedLabel` reject for an element of a context other than the session's first one. ``` const page = await browser.url('https://the-internet.herokuapp.com/nested_frames') const bottom = await page.frame({ selector: 'frame[name="frame-bottom"]' }) const body = await bottom.$('body') console.log(await body.getText()) // outputs: "BOTTOM" ``` ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") | Error | Cause and fix | | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | | `` `switchFrame` was removed for WebDriver BiDi sessions in WebdriverIO v10. `` | Call [`frame()`](/docs/api/browsingContext/frame.md) on the context returned by `browser.url()` or `browser.newWindow()`. | | `` `switchWindow` was removed for WebDriver BiDi sessions in WebdriverIO v10. `` | Hold the context returned by `browser.url()` or `browser.newWindow()`, or find one with `browser.browsingContexts()`. | | `` `frame()` needs a WebDriver BiDi session, but this session uses WebDriver Classic `` | The session is a Classic session (e.g. Appium or Safari). Use the Classic command the message names. | | `` `` is only available on a top-level browsing context `` | The command was called on a frame. Call it on the frame's tab, see [Top-level only](#top-level-only). | | `` `addCommand` is only available on the browser, not on a browsing context `` | Register custom commands on `browser`. | | `no such frame: the frame "…" was discarded because the page it belongs to navigated away` | The page that contained the frame navigated. Get the frame again with `frame()` on the new page. | ## Related[​](#related "Direct link to Related") * [The Browser Object](/docs/api/browser.md) * [Migrate to v10: `switchToFrame`](/docs/v10-migration.md#switchtoframe) * [Dialogs](/docs/api/dialog.md) --- # acceptAlert Accept the user prompt (`alert`, `confirm` or `prompt`) that is open in this browsing context. Prompts in other tabs stay open. WebdriverIO dismisses prompts automatically unless something listens to the `dialog` event, so register a listener first. In a listener you can also answer with the [dialog object](/docs/api/dialog.md) directly. ## Usage[​](#usage "Direct link to Usage") ``` const context = await browser.url('https://webdriver.io') await context.acceptAlert(userText) ``` ## Parameters[​](#parameters "Direct link to Parameters") | Name | Type | Details | | -------------------------- | -------- | ----------------------------- | | `userText`
*optional* | `string` | text to enter into a `prompt` | ## Example[​](#example "Direct link to Example") acceptAlert.js ``` it('accepts a confirm in a background tab', async () => { browser.on('dialog', () => {}) // keep prompts open await browser.url('https://webdriver.io') const tab = await browser.newWindow('https://webdriver.io', { type: 'tab' }) const opened = new Promise((resolve) => browser.once('dialog', resolve)) await tab.execute(() => setTimeout(() => window.confirm('Continue?'))) await opened await tab.acceptAlert() }) ``` --- # activate Bring the tab or window of this browsing context to the front and focus it. Commands run in every held browsing context whether it is in front or not, so you only need this when the page reacts to focus or visibility, or before a visual check. It does not change which context `browser.url()` navigates. Only a top-level browsing context can be activated, a frame rejects. ## Usage[​](#usage "Direct link to Usage") ``` const context = await browser.url('https://webdriver.io') await context.activate() ``` ## Example[​](#example "Direct link to Example") activate.js ``` it('brings a background tab to the front', async () => { const page = await browser.url('https://webdriver.io') const tab = await browser.newWindow('https://webdriver.io/docs/api', { type: 'tab' }) await page.activate() // the first tab is in front again console.log(await tab.getTitle()) // the tab behind it still answers commands }) ``` --- # back Go back one entry in the history of this tab or window, like the browser's back button, and wait until that page is ready (following the `pageLoadStrategy` capability, like `browser.back()`). Other tabs keep their page. Only a top-level browsing context has its own history, a frame rejects. ## Usage[​](#usage "Direct link to Usage") ``` const context = await browser.url('https://webdriver.io') await context.back() ``` ## Example[​](#example "Direct link to Example") back.js ``` it('goes back in one tab', async () => { const page = await browser.url('https://webdriver.io') await page.navigate('https://webdriver.io/docs/api') await page.back() console.log(await page.getUrl()) // outputs: "https://webdriver.io/" }) ``` --- # closeWindow Close the tab or window of this browsing context. Other tabs and windows stay open, and the session keeps running as long as one of them is left. Commands on the closed context, and on frames of it, reject afterwards. Mocks made on the context end with it. Only a top-level browsing context can be closed, a frame rejects. ## Usage[​](#usage "Direct link to Usage") ``` const context = await browser.url('https://webdriver.io') await context.closeWindow() ``` ## Example[​](#example "Direct link to Example") closeWindow\.js ``` it('closes a tab it opened', async () => { const page = await browser.url('https://webdriver.io') const tab = await browser.newWindow('https://webdriver.io/docs/api', { type: 'tab' }) await tab.closeWindow() console.log((await browser.browsingContexts()).length) // outputs: 1 console.log(await page.getTitle()) // the first tab is unchanged }) ``` --- # dismissAlert Dismiss the user prompt (`alert`, `confirm` or `prompt`) that is open in this browsing context, like pressing "Cancel". Prompts in other tabs stay open. WebdriverIO dismisses prompts automatically unless something listens to the `dialog` event, so register a listener first when you want to answer yourself. ## Usage[​](#usage "Direct link to Usage") ``` const context = await browser.url('https://webdriver.io') await context.dismissAlert() ``` ## Example[​](#example "Direct link to Example") dismissAlert.js ``` it('dismisses a confirm in one tab only', async () => { browser.on('dialog', () => {}) // keep prompts open const page = await browser.url('https://webdriver.io') const opened = new Promise((resolve) => browser.once('dialog', resolve)) await page.execute(() => setTimeout(() => window.confirm('Leave?'))) await opened await page.dismissAlert() }) ``` --- # forward Go forward one entry in the history of this tab or window, like the browser's forward button, and wait until that page is ready (following the `pageLoadStrategy` capability, like `browser.forward()`). Other tabs keep their page. Only a top-level browsing context has its own history, a frame rejects. ## Usage[​](#usage "Direct link to Usage") ``` const context = await browser.url('https://webdriver.io') await context.forward() ``` ## Example[​](#example "Direct link to Example") forward.js ``` it('goes forward in one tab', async () => { const page = await browser.url('https://webdriver.io') await page.navigate('https://webdriver.io/docs/api') await page.back() await page.forward() console.log(await page.getUrl()) // outputs: "https://webdriver.io/docs/api/" }) ``` --- # frame Get a frame (`