PAUL RYANCODES

Up & Running with JEST

Goal of this Article

The goal of this article is to give you the fundamentals of testing a React component with Jest, with this knowledge you can hit the ground running when you start testing your own components. Ready? Let's start.

Sample Component

I have created a simple Card component in Codesandbox.

Picture of Component

This component accepts a prop which handles when the Discover button is clicked.

Here is the Codesandbox so you can follow along:

Codesandbox has still a ways to go when it comes to testing, I failed even getting a snapshot test to work so I recommend cloning down my repo here and following along on your local machine.

Installing JEST

The first thing we need to do before we can start using Jest is to install it. To install Jest run the following command: npm install -D jest react-test-renderer

Thankfully, create-react-app has this handled so we can just run npm test to run our tests :)

Creating our tests directory

Jest looks for tests in directories named __tests__, add the __tests__ directory to your Card component.

Next thing we need to do is to create a test file in the __tests__ directory, we will call our file card.test.js

Your folder structure should now look like the following:

Folder Structure

Creating a snapshot test

First run the command: npm test

This will start Jest in watch mode, so any time we make changes our tests will rereun.

The first test we will write is a snapshot test.

Add the following code to your card.test.js file:

import React from "react"
import Card from ".."
import Renderer from "react-test-renderer"

it("renders correctly", () => {
  const tree = Renderer.create(<Card />).toJSON()
  expect(tree).toMatchSnapshot()
})

This will create a JSON snapshot of our component in a directory called __snapshots__, which means anytime the component changes this test will fail. Go ahead and change something in the component such as the text and you will get the following: Image of failure

To remedy this, you simply need to update the snapshot by just pressing u.

Testing the callback function

We are now going to use the library enzyme to help us out, it gives us a lot of handy utils and saves us a lot of headaches.

We need to install a few dependencies: npm install enzyme enzyme-adapter-react-16 --save-dev

Now add the following to the top of your test file:

import Adapter from "enzyme-adapter-react-16"
import { mount, configure } from "enzyme"
configure({ adapter: new Adapter() })

For Enzyme to work we need to create an adapter, the adapter gets Enzyme working with your React version i.e. React 16.

Now let's add a new test:

it("triggers the callback function", () => {})

Now let's fill out the body, I have commented each line so it is easy to understand.

// in order to test the callback function we first need to mock it
const onClickCallback = jest.fn()
// pass our mock function as the prop the Card
let card = mount(<Card handleClick={onClickCallback} />)
// find out button i.e. the button that triggers the callback and click it
const button = card.find("button").simulate("click")
// our mock function should have been called once
expect(onClickCallback).toHaveBeenCalledTimes(1)

Test that the correct value is passed from the callback function

Our callback function passes back the hardcoded string discover, let's test to make sure that this is being passed correctly.

The function is similar to above except for the last line:

it("callback function is the passed the string discover", () => {
  // in order to test the callback function we first need to mock it
  const onClickCallback = jest.fn()
  // pass our mock function as the prop the Card
  let card = mount(<Card handleClick={onClickCallback} />)
  // find out button i.e. the button that triggers the callback and click it
  const button = card.find("button").simulate("click")
  // test to see if our function was called with the right param
  expect(onClickCallback).toHaveBeenCalledWith("discover")
})

Thanks for reading.

I hope you gained some knowledge, I will continue adding to this article so consider this draft 1 :)