Using WebdriverIO to test React Web Apps (Part 2)

Ranvir Chhina
Tauk Blog
Published in
6 min readJun 30, 2022

WebdriverIO allows ReactJS developers to use selectors, which leverage concepts of the React paradigm. In addition to using regular CSS selectors to find elements in your automation tests, WebdriverIO also provides an API which allows you to find a React Component with its component name. Under the hood, WebdriverIO allows you to find elements from the React VirtualDOM directly.

In this guide, we will go over how to use React selectors to select components by their name, props, and state. In addition, we will install React DevTools extension and use it to discover components from a website built using React.

React DevTools

For this guide, we will be using Google Chrome as the browser in which we install React DevTools. However, React DevTools are also available on other browsers. To install the React DevTools on Chrome, you will have to open the React DevTools extension’s page on the Chrome Web Store.

Next, you need to click the Add to Chrome > Add Extension buttons to install this extension.

Then, for the installation to work, you will need to restart chrome. You can do so by typing the following in your address bar and hitting enter.

chrome://restart

Once chrome has restarted, you should see the React Developer Tools extension in your extension dropdown.

Using React DevTools

Launch your application that is built using React. For this tutorial, we will be using the Flipboard website which using React. After navigating to this website, open Chrome Developer Tools. You should see two new tabs: Components and Profiler.

In the Components tab, you can search and select React components. In the breadcrumbs section, you can see specific information about the React Component. It will show you the location of the component across the Component Tree and its props and state.

You can click on the top left of this Components Tab and enable the select mode to select the component. You can even search a specific component name in the Hierarchy tree.

Let’s put this to use. We will try to find an element within this React VirtualDOM using its props.

Using WebDriverIO REPL

WebdriverIO provides a REPL interface to learn and experiment its API without having to set up and tests. You can use this REPL to test browser commands and debug your automation tests.

To launch this REPL, we will run the command

npx wdio repl chrome

It will ask you to install wdio package on your system and then help you configure the WebdriverIO in you local system. After its setup, this will launch an instance of chromedriver and take you to a blank page. These were the options that I selected during the WDIO setup.

=========================
WDIO Configuration Helper
=========================
? Where is your automation backend located? On my local machine
? Which framework do you want to use? mocha
? Do you want to use a compiler? TypeScript (<https://www.typescriptlang.org/>)
? Where are your test specs located? ./test/specs/**/*.ts
? Do you want WebdriverIO to autogenerate some test files? Yes
? Do you want to use page objects (<https://martinfowler.com/bliki/PageObject.html>)? Yes
? Where are your page objects located? ./test/pages
? Which reporter do you want to use? spec
? Do you want to add a plugin to your test setup?
? Do you want to add a service to your test setup? chromedriver
? What is the base url? <https://flipboard.com/>
? Do you want me to run `npm install` Yes

In the REPL, you can type the following command to navigate to your desired website.

› browser.url("www.flipboard.com")
2022-06-27T16:11:06.547Z INFO devtools: COMMAND navigateTo("<http://www.flipboard.com/>")
2022-06-27T16:11:10.400Z INFO devtools: RESULT null
null

We will now use the REPL to find a React Component by its Props.

WebDriverIO react$ Command

The WebdriverIO browser.react$() and browser.react$$() commands help you locate React components. The former returns the first match for the selector in the VirtualDOM and the latter returns an Array with all of the matches. They will return WebdriverIO elements which can used within test cases to perform actions or inspect properties.

On the Flipboard website, let us find a post that has a certain author. If you inspect the DOM in the React DevTools, you will find that each post on the website is a React Element, with props describing its properties, like image, author name, etc.

You can find a particular post using the following command:

› browser.react$("a", {props: {item: {authorDisplayName: "Sherry Colb"}}})
2022-06-27T16:24:23.902Z INFO devtools: COMMAND executeScript(<fn>, <object>)
2022-06-27T16:24:23.908Z INFO devtools: RESULT true
2022-06-27T16:24:23.910Z INFO devtools: COMMAND executeScript(<fn>, <object>)
2022-06-27T16:24:23.917Z INFO devtools: COMMAND executeScript(<fn>, <object>)
2022-06-27T16:24:24.007Z INFO devtools: RESULT { 'element-6066-11e4-a52e-4f735466cecf': 'ELEMENT-1' }
Element {
sessionId: '6aaa592a-18a6-4a77-82ed-28f96e66df89',
elementId: 'ELEMENT-1',
'element-6066-11e4-a52e-4f735466cecf': 'ELEMENT-1',
selector: 'a',
parent: Browser {
sessionId: '6aaa592a-18a6-4a77-82ed-28f96e66df89',
capabilities: {
browserName: 'Chrome',
browserVersion: '102.0.5005.115',
platformName: 'darwin',
platformVersion: '21.4.0',
'goog:chromeOptions': [Object]
},
addCommand: [Function (anonymous)],
overwriteCommand: [Function (anonymous)],
addLocatorStrategy: [Function (anonymous)]
},
emit: [Function: bound ],
isReactElement: true,
addCommand: [Function (anonymous)],
overwriteCommand: [Function (anonymous)]
}

Let’s summarize the command and result from above:

  • The browser.react$ command accepts two arguments: a selector and an object called ReactSelectorOptions.
  • The selector is a string which is equal to the component name.
  • The ReactSelectorOptions object has two properties props and state. By setting these properties to certain values, you can filter the VirtualDOM.
  • In the example above, we filtered the VirtualDOM and looked for a component named a that has prop containing {authorDisplayName: "Sherry Colb"}

This prop does not have to be an exhaustive match of all the properties but can be a partial match. For example, the actual a component actually had many other props that we did not mention. You could have also selected it using description, excerpt, and hundreds of other props.

You can use this method to find React components and chain additional WebdriverIO commands to them. For example, to click an element you would do the following:

› browser.react$("a", {props: {item: {authorDisplayName: "Sherry Colb"}}}).click()
2022-06-27T16:24:38.495Z INFO devtools: COMMAND executeScript(<fn>, <object>)
2022-06-27T16:24:38.501Z INFO devtools: RESULT true
2022-06-27T16:24:38.504Z INFO devtools: COMMAND executeScript(<fn>, <object>)
2022-06-27T16:24:38.512Z INFO devtools: COMMAND executeScript(<fn>, <object>)
2022-06-27T16:24:38.600Z INFO devtools: RESULT { 'element-6066-11e4-a52e-4f735466cecf': 'ELEMENT-2' }
2022-06-27T16:24:38.604Z INFO devtools: COMMAND elementClick("ELEMENT-2")
2022-06-27T16:24:38.818Z INFO devtools: RESULT null
null

As you can see, we use the same react$ command as before and chain a click() method to it. This allows us to effectively use WebDriverIO commands on React components allowing us to leverage existing functionality without making many changes.

Conclusion

The react$ and react$$ commands can be used in tandem with your existing tests and utilize selector strategies that are more suited towards a React application. You need not completely forego your existing CSS selectors, but can use a mix of them in your Page Object model approach.

Lastly, if you have any questions about this blog post, you can reach out to us by joining our Discord server:

💡 Also, you can integrate your iOS UI XCTests with Tauk! You can try it for free here: https://www.tauk.com/welcome

--

--