Writing Easily Testable Code with Stateless Components in React.js

September 12, 2017 0 Comments

Writing Easily Testable Code with Stateless Components in React.js



The use of Stateless Functional Components (a.k.a. “pure” or “dumb” components) in React.js continues to grow since first it was released in React 0.14, and for good reasons. By relying on pure components, developers end up writing reusable code that's extremely easy to test, which leads to better application architecture. Why? A functional stateless component is merely a factory function used to create a React component. Personally, I like the term “pure component” because it's indicative of what the code really is — a pure function sprinkled with some JSX.

"A pure function is a function which: Given the same input, will always return the same output. Produces no side effects.

Relies on no external mutable state."

— Eric Elliott, Master the JavaScript interview: What is a Pure Function

Equipped with the right number of tests, the use of pure functions can help bring peace of mind to developers by ensuring that any scenario that has been tested will not have an unintended result in the application. As you can imagine, this can go a long way when building large scale applications. It should also come as no surprise that pure functions are the heart of Redux, which relies on JavaScript’s reduce function.

In an upcoming post, I’ll go into further detail on how reduce works. For now, I want to continue on with the idea of writing “bullet-proof” React components using pure functions. To best illustrate this, I’m going to show some code that shows a React child component.

// Post.js
const Post = ({ title, content }) =>
<div className="post">

The clean nature of these components make it extremely easy to reason about the code. In this case, we see that the Post is just a function that takes title and content props and then uses these props to produce an element. You may see props being passed in as a parameter but I’ve utilized ES6 destructuring. By doing so, we’re able to pull specific values out of the props object and access props.title and props.content without using dot notation.

Personally, I think this is awesome because it removes any mystery about the props being passed into a component. In programming, mystery is never a good thing, so this allows us to read code faster than others, and allows us to reason with them better, especially as components become more complex!

Why this is important

Although this component may not look like much, it could very well play an integral part of an application. For instance, let's imagine <Post/> rendering articles for a website that has over a million daily users. If that's the case, then we will most likely want these smaller, cohesive blocks of code, as they allow us to easily hammer out every last detail!

You’ll also find that pure components make modifications a breeze and also result in writing code that can be easily ported into other projects. In addition to these benefits, pure components also make it extremely easy to test code with any crazy props that you wish. Like a pure function, pure components will always map the same input to the same output, therefore, if we can think of the scenario, we can test how our component will react.

Diving into Unit Tests

As we just saw, the code for functional components provides us awesome intel for everything we need to know in order to write effective tests. To best illustrate this, I’m going to take you through the code block below, which is a unit test of the <Post /> component.

import test from 'tape';
import dom from 'cheerio';
import Post from './Post';
import { renderToStaticMarkup } from 'react-dom'; test('<Post /> ', assert => {
const msg = 'should render a post with a title and content'; const props = {
title: 'I am the title',
content: 'I am the content!!!!!! Woooooooo!'
const checkProps = RegExp(props); const el = <Post {props} />
const $ = dom.load(render(el));
const output = $('post').html(); const actual = checkProps.test(output);
const expected = true; assert.same(actual, expected, same);

Don’t worry if the code above seems a bit confusing to you — it will all make sense soon.

Step 1 - Set up pre-existing conditions

In this instance, we know that <Post /> takes a title and a content prop so we can test this by simply passing in these values to a props variable. Once we’ve assigned the props we want to test, we can use JavaScript's Regex function to create another variable, checkProps, that will make sure the component being tested contains the props it is being given.

const props = {
title: 'I am the title',
content: 'I am the content!!!!!! Woooooooo!'
const checkProps = RegExp(props);

Step 2 - Render the HTML from <div class="post">

Following this, we will then see the use of cheerio to render our component. Cheerio allows us to traverse and manipulate the DOM using its API. Additionally, Cheerio is lightning fast and as a result of that, it’s at the heart of popular libraries like enzyme.

Taking a look into our code, we can use cheerio's .load method to render our React element. From there, we can simply pass in the selector of the contents we want to check. In our case, it's the .post class. Following our selector, we then see cheerio’s .html() method, which will render the content from our selector and allow us to check for our component’s props.

const el = <Post {...props} />
const $ = dom.load(render(el));
const output = $(‘.post').html();

Step 3 - Test the props

The last thing we need to do is check the props of our output variabe. To do this, we have an actual value which will check to see if our component passes our checkProps test. If it does, that means the actual value will return true and give us a passing test!

const actual = checkProps.test(output);
const expected = true; assert.same(actual, expected, msg); assert.end();

Step 4 - Celebrate (Final Words)

Awesome! You’ve made it to the end. Hopefully by now you’ve got a good understanding of how functional stateless components work in React. Personally, I can’t get enough of them and I hardly ever try to use classes in my code. Why use this if you don’t need to? 😃

If you have any questions and comments, leave a comment below!

Tag cloud