Test Driving a change to a React-Redux application — Step By Step

Working with Ruby for so many years TDD is really an essential part of my workflow and I don’t see myself living without it.

One of my recent projects @ Gogobot is to rebuild one of the most critical user-facing application with React-Redux to make it faster and easier to change.

Even before launching it I had to change a single part of it and I thought it’s a great showcase to how I test-drive changes in applications using TDD.

Here’s a screenshot

The change is to replace the tabs with toggle. Instead of a user only able to see 1 of each type or ALL a user will be able to toggle place types on/off easily.

Here’s the current component

As you can see it’s a NavBar (from bootstrap) and it has a selected prop passed in from the state.

The selected state is a single string.

Planning

  • Make the state an array of strings
  • Once a toggle button is clicked, we want to toggle that items from/to the selected state and pass it on
  • The selected state of each button needs to check whether the item type is included in the selected state.

Reducer change

Our current reducer looks like this

Now, instead of just returning the itemType from the action, we’ll have to get the current state and “toggle” the item from the selected array.

So, lets test drive this

Writing the test

As you can see here we are testing for both scenarios. Adding an item to the array and also removing an item.

The action remains almost identical but renamed to `TOGGLE_ITEM_TYPE` for better clarity on what it actually does.

Implementing the reducer

This code is a bit ugly, but with TDD we just need to make it pass first and refactor later

This makes out tests pass and makes us happy. However, we are not done yet.

In our application we have code like this to check whether we show the map pin or not

visible = { this.props.selected.indexOf(marker.display_type || this.props.selected == itemConstants.ALL_ITEM_TYPES_SELECTED }

We’ll need to refactor this code to make sure it’s compatible with an array type.

visible = { this.props.selected.indexOf(marker.display_type) > -1 }

This will suffice for now, we’ll refactor this into a helper later on

Refactoring the component

Before we refactor the component and make it look nice, this is the initial version. We have a link to each with a “selected” class name.

Now our component works great with our current state. All I needed to change was just the action name.

Since I TDD’d everything it “just worked” on first refresh.

Takeaways

I intentionally did not update the test code and put it like the first time I wrote it. Looking at it later though, I realized that I did not test against returning an empty array as a result of a bug. So if the code has a bug that didn’t filter the array right it would still return an empty array. Better test would be to return a single item array filtered

One more good addition would be that I am dispatching the right action. This would make the action renaming task less prone to errors.

Show your support

Clapping shows how much you appreciated Avi Zurel’s story.