UI Testing in React

We always want to build great user interfaces. Usually, we spend most of our time on improving styles and the user experience. We write and change a lot of UI-related code. So, it’s very important to use proper testing methods for the UI code.

In this article, I’ll talk about how we can test React UI components. First, I’ll discuss some concepts, then I will show you how to implement those concepts with the correct tools.

I assume that you are familiar with JavaScript testing tools like mocha, chai and sinon. If not, the internet is your friend. You can also look at some simple repos like react-komposer or try code generators like React CDK.

Idea

UI testing is always hard. There are some things you can automate. And there are some things you need to test manually. We try to minimize the manual testing. But when we want to create a great user experience, manual testing is really important.

I’d like to divide UI testing into two categories:

1. Functional Testing

Here we test the functionality of our components. For example, let’s say we’ve a button component. It should trigger an event if someone clicks on the button.

With functional testing, we test scenarios like that. If our button component doesn’t trigger the event, that’s a test failure.

2. Visual Testing

Visual testing is something that has to be done with human eyes. For example, say we need to

  • check the font size
  • check the font style
  • check the paddings and margins

These things are pretty hard (or impossible) to automate as they involve our taste and human thinking.

Importance

Both types of test are equally important. If a function or a visual test fails, your whole test should fail. That means, there’s an issue somewhere in your app.

Assume our app is an e-commerce product. Let me show you some examples:

Functional Testing Failure

Let’s say the click event of a button in your app is not working. Then it’s a total failure and users might not be able to order products.

Visual Testing Failure

Assume one of your designers has changed the background color for a seasonal offer. Unfortunately now, the background color is the same as the button text color. So, your users can’t locate the order button.

As you can see, a tiny change could destroy your whole app. The failure could be from a functional test or a visual test. So, both types of tests are just as important.

😎: Okay. I got it. Show me how to write these test cases.

Fortunately, React has an amazing set of tools to write these kinds of tests. Let’s have a look at them.

Writing Functional Tests

There are many test runners in JavaScript. Mocha is a popular test runner. I assume you are already familiar with mocha.

Alongside that, we’ll use some other common JavaScript testing tools like chai and sinon.

For testing React components, we’ll use enzyme. It’s simple and has many features.

I’m not going to show you how to set up the test environment. If you want to know how, refer to this post or try a generator like React CDK.

In the following section, we write some tests for a React button component. This is the GitHub repo of that component.

Shallow Rendering

Shallow rendering is very interesting. Only the first level of components is rendered inside your component. The test runner doesn’t need to worry about DOM and the execution environment, which is great for functional testing.

Let’s write a simple test case. Say we are trying to check a button’s onClick event handler. Here’s the code:

With Full DOM Rendering

Sometimes, you need to test your components with a full DOM environment. This is important if your components change the DOM directly, utilize browser features or use React’s life cycle hooks (like the componentDidMount hook).

You can use enzyme’s mount utility instead of shallow. This is how we can modify the above test to utilize full DOM testing:

Diff view on how to use mount instead of shallow.

Other than that, you need to run your tests inside a DOM environment. For that, you have a few options:

  • Using JSDOM — This runs a fake JS environment inside JavaScript and it’s good for 90% of use cases.
  • Using Karma — This runs your tests inside a real browser (or many of them).
😎: Wow! This looks like fun. So, how we are going to do the visual testing?

Writing Visual Tests

We do visual testing with our naked eyes. For the things we can’t automate, we use visual testing.

For that, we have a great tool. It’s React Storybook, which we use to create stories for different scenarios and then test them. A story is a single use case of your component. It’s like a unit test, but a visual test.

Setting up React Storybook is simple.

Once configured, this is how we can write some stories for our button component:

Then, you can visually inspect these stories via the storybook console:

So, you can identify if there are any visual issues.

Development Strategies

There are different ways to write these visual and functional tests depending on the situation.

At first

Initially, we write stories with React Storybook. Its hot reload functionality is great when we are designing and developing the initial version.

Then, once we have a good design, we write our functional tests.

Initially, we usually don’t try to create visually great UIs. We are only looking to build something functional.

For Design Changes

After the initial design, we improve our UIs to create a great user experience.

These design changes may break the functionality. We can check that using the functional tests. So, after a design change, we run the functional tests and see whether the change has broken the functionality.

We can use a utility to run the tests as we edit the code, giving us real-time feedback.

See:

For New Features

If we need to add a new UI feature, we start React Storybook and start working on it. Then we update or create functional tests to match the new features.

After that, we check our other stories manually for any UI regression with this new feature.

Test Automation

Now it’s time to automate our testing setup. This helps us when we are reviewing code, especially when it’s linked with a GitHub pull request.

For functional testing, we can use a Travis CI, Circle CI or similar CI service. For visual testing, you need to run your storybook and check it. For that, you need to build the storybook in a development box.

We are working on a service that simplifies this process. It can build storybooks for each and every commit in your app and you can access them right next to your PR.

We are also planning to add more features like visual diffing and DOM mutation diffing. These will help you to minimize the number of stories you need to inspect manually. We also have some plans to automate most of the visual testing aspects. This will save you time and let you build great products.

😎: How you are going to do that? Are you going to build in AI?

We will build in AI for that someday. But, there are some others ways to do this.


In this article, I showed you some ways to test React UI components. We also discussed why testing is so important and concepts around it.

If you are using a similar technique, you are in good hands. If not, start writing tests today. You may need to spend more time writing tests, which may be longer than the time you spent building the component. But, you’ll see the benefit if there are more people in the team and your project gets bigger.

What do you think? Are you doing React testing in a different way? I’d like to discuss this some more.