Jest React Master

Thomas Hagström
crossplatform
Published in
4 min readJan 15, 2019

One year ago in an apartment not so far from this chair my React-Native journey began.

One of the great things about the platform is the great power of the Jest; being able to unit test your components without expensive test farms!

As we started publishing open source packages on NPM test coverage became even more important. So how to configure it? Start in jest.config.js. If you’re configuring Jest straight in package.json (don’t) syntax varies.

We use TypeScript for all JS development, because proper type checking and autocompletion rules.

Table of Contents

Jest Collect Code Coverage

When you now run Jest it will tell you your level of Jest mastery. This is from react-native-cross-cognito at the time of writing. Notice the “% Stmts” part. This is percent of test coverage. And looking at “Uncovered lines” will tell you exactly what lines your tests are missing!

Jest test coverage (TypeScript)

Upload to Codecov and badge

It will also generate a /coverage folder containing the above report.

This can be turned into a cool Markdown badge (because badges are cool) for Codecov.io as seen below. Pretty neat right? Setup your codecov account and you’ll get one just as nice.

Simply upload the report using codecov cli, preferably in a CI build step:

Jest React state manipulation

Here’s the Jedi tricks you need to succeed. What I know is based on the excellent lessons of Russell Briggs right here on Medium. As seen, we’ve dropped Enzyme entirely in favour for the awesome react-native-test-renderer:

I will brake it down in slightly more concrete examples as seen in our library here. Also, if you’re in to AWS Cognito using Amplify, give it a go :)

Full source of tests in below examples:

Setting React state in Jest test

Our component CognitoLogin exposes it’s state object: ICognitoLoginState to the world. Say we want to simulate it’s state.formState being “Register”? Easy peasy. root.instance provides access to the real component instance.

setState of a test renderer

Find React children in Jest test

A basic requirement is to identify children. While you could search by some props they happen to have, that’s pretty generic and unreliable. Each React component has a testID property, and you can add such to your custom components. This property makes it a breeze to identify the child in a test.
CognitoLogin.tsx contains this child:

<ForgotForm testID=’ForgotForm’ />

Which we can now look up in the test:

In this scenario findByType would have worked as well, but required us to import the child component.

Read React state in Jest test

When you’ve acted in the test and want to assert the result, reading the React component state becomes critical. Turns out, not so hard.

I’m using the excellent library Lodash, which no JS developer should live without, so the imports are included here for clarity. You could just do wrapper.root.instance.state and then read off any property in state.

React functions in Jest

Now that we can set and read state, let’s call our functions.

Jest call direct function in React Component

So you have a component with some functions (declared as arrow functions) and want to test those directly. No problemo! So assuming our component looks something like this:

React component with arrow function

We want to test onEmailChanged

Once again root.instance provides access and let us call any function within the component.

Jest callback on React child function

If you did the “Find React children” part then you have access to the child already. Now you can use the child instance props property to call any function on the child, such as button onSubmit or any custom function.

In this example CrossButton has a child of type FontAwesome.Button. Looks something like this:

So we create a callback handler for the onPress event in the test. After finding the React child we use it’s props to call the event. onCalled will update the called field.

Async calls in Jest tests

This is can be a little confusing sometimes. Why not just await your async function? Well you should, but you also have to tell Jest the test is done.

So the key parts are

  • Decorate test function with async
  • Add the done parameter to test function
  • Call the done(); function before test exit.

Mock module in single test

In some cases you might need to mock a module in a single test.
There are two key parts involved here:

  • Import the class you wish to mock (“Auth”) and create a spy using jest.spyOn
  • After evaluation of result, call mockRestore() on the spy

Cool. Your mastering the Jest.

--

--