⚠️ This lesson is retired and might contain outdated information.

React Testing: className with Shallow Rendering

Trevor Miller
InstructorTrevor Miller
Share this video with your friends

Social Share Links

Send Tweet
Published 8 years ago
Updated 2 years ago

The React Shallow Renderer test utility lets us inspect the output of a component one level deep. In this lesson, we will examine the rendered output of props, specifically the className prop. We will then use the ES2015 String.includes() method to check that our rendered className includes what we expect.

[00:00] Here we have an app that has a few icon components on the screen. We can see that there's a thumbs-up icon and a trashcan icon. Now we want to write some tests to make sure that these icons are rendering correctly.

[00:13] Here we have a test file where we've imported the React library as well as the React testing library, the Expect assertion library, and the component that we want to test, which is the icon. Let's write a test now. We're going to say that it should render the icon. Now let's set up our shallow renderer.

[00:32] I'll say const renderer = testutils.createrRenderer. Then we'll tell this what to render. We'll say render, and we'll give it the icon component with a name prop. Let's use the Facebook icon. At the end of our test, we're going to assert that the actual value is going to equal the expected value.

[00:57] Our actual value is going to be the renderer. If we get the rendered output of that renderer, we will be getting what was returned from this guy right here. So we're going to get "what is icon name" returned when it's rendered and put it inside of this actual variable.

[01:18] Now let's take a look at what this actual value is going to be. We can see here that the shallow renderer has given us our object representation of our component, so we have this giant object here. But what we're really interested in is this className prop right here.

[01:36] Inside of our root object we have the props object. There's a className which is just a string of classes. Now back in my test file I'm going to remove this log statement. Then, instead of checking the entire object output of my shallow renderer, I'm going to only look at the props and the className prop.

[02:00] Now since we know that the className prop is just a string, we can use the ES2015 string method of includes to check that it includes the className that we're looking for, which is Facebook in this case. The way the includes method works is it will return a Boolean value. If Facebook is found in the className string, it will return true, and, if not, it will return false.

[02:23] So we're going to say that our expected value is going to be true. To review, we created our shallow renderer. We gave it the component we wanted to render. Then we grabbed that rendered output and checked that the className prop included the string that we were looking for. Then we assert that that's the case. That's how we can test className props.

Clinton
Clinton
~ 8 years ago

Hi, I found this course very useful. One thing I'm wondering, are these real tests that you would write in a production app? To me it seems like this would almost never break, unless there was a dramatic update in React OR in your testing library.

https://github.com/trevordmiller/favorite-quotes/blob/master/src/components/Icon.spec.js

Joel Hooks
Joel Hooks
~ 8 years ago

Tests not breaking is a feature, generally. Catching React update issues is definitely a solid use case for a test.

Clinton
Clinton
~ 8 years ago

Gotcha, I'm just wondering if there is any real business value here.

This is a great example of shallow rendering but at it's core it seems like it is really testing that this.props.string = string which isn't hugely valuable on its own.

I'm pretty new to testing in general and I guess I'm just asking in general if it's really worth testing and maintaining a use case like this.

Trevor Miller
Trevor Millerinstructor
~ 8 years ago

Clinton, I think the key to a useful test is that you are testing something that you want to ensure doesn't break without you knowing about it. In the lesson, we look at testing that a string of classnames contains a specific substring to ensure that our icons will be rendered correctly; this is not this.props.string = string but rather this.props.string.includes('substring'). In this situation, the value comes in knowing that our icons are rendering correctly - and we don't have to manually check this in the browser any time we make a change to the Icon component.

There are hundreds of other use cases for this, but the principle is that we...

  1. found something that is important - that we don't want to break accidentally when we refactor or add features in the future (in this case, icons are rendering by type)
  2. figure out what piece of our code will ensure that #1 is working (in this case, the right substring exists in the rendered className prop)
  3. write a test with #2; generally I've found it helpful if the test isn't tied to a specific DOM structure or lots of React specific things, as you pointed out.

I've found generic tests like this to be very useful :)

Trevor Miller
Trevor Millerinstructor
~ 8 years ago

"To me it seems like this would almost never break, unless there was a dramatic update in React OR in your testing library."

This is the beauty of it! The only time this test would break is if we screw up our Icon component where it is no longer rendering the correct Icon types - which is what we want. If the test did break we would want to know about it before our users complain "the icons aren't working anymore". The test provides value because it will let us know immidiately if we have broken our key expected functionality in our component without having to manually check the component output in the browser every time we make a change.

Although the example in this lesson is small and simple, the more tests you have like this, the easier it is to add new features and refactor with confidence, which is the true value of testing.

Merlin Labs
Merlin Labs
~ 8 years ago

expect has a toInclude method that you could use directly!

Trevor Miller
Trevor Millerinstructor
~ 8 years ago

Hey Concierge. Using the expect-jsx methods gives you nice JSX syntax error diffs. Not required but I find it much easier to debug :)

Markdown supported.
Become a member to join the discussionEnroll Today