Introduction
Here I am again with some new post about React unit testing. I spend some time reading about Enzyme and at some point I thought itâs good to make a post about it. In this article Iâll lead you through different types of Enzyme rendering, differences between Enzyme and Jest, some examples of how to test more complex components which use asynchonous calls
Hope you will like it!
Enzyme
Enzyme [1] as you can read in their documentation is a:
As I first read about I though it works more or less like puppeteer [11] or Selenium WebDriver [2] environment which allows to simulate whole web browser to perform tests. Such tests are usually hard to write and maintain since they are not connected to codebase of application and you donât use them to test single components
Enzyme gladly works differently but with its huge amount of features allows you to perform almost same test as you would do while simulating whole browser
Jest
Jest as itâs claimed on their main webiste is a
It allows you to run test suites and supports many different frameworks like. I havenât really test if it works good with them but when you read how Jest creates snapshots of HTML itâs pretty convincing that you can use it for multiple frameworks
In this article I wonât focus on how Jest makes usage of Components snapshots but if you are curious this part of their docs describe whole process and itâs more or less 1 min read
Enzyme vs Jest
Ok some text was written about Enzyme and Jest but whatâs the real difference between them? From documentation of both itâs not really obvious except that Jest can also work with different frameworks that React. Thatâs why I checked other articles including this one [12] which I highly recomend to read
So differences between Enzyme and Jest:
Jest | Enzyme |
---|---|
Fully-featured testing framework which allows to test JS code and itâs not realated to any library like React,Angular,Vue. | Works only with React components. |
Compare React components by taking snapshots of HTML code that you need to maintain. | Works with API which analyze React components which means no HTML to maintain. |
Can work without Enzyme. | Cannot work without Jest or other library that would start tests and make assersions |
Shallow Rendering API [3]
Itâs a type of rendering provided by Enzyme which allows only to render component that will be passed to shallow
function.
Not only itâs faster than Full Rendering but it also does not render child components which can help you reduce the scope of
unit test
Full Rendering API [4]
At first sight itâs not really different from Shallow Rendering as API to query elements is similar. The main difference is that
Full Rendering renders whole website. That means all child components of the component you pass to mount
function will be
rendered
Itâs slower than Shallow Rendering but it allows to write much complex tests. In some cases you can even create full integration test of the app. Such test will be usually hard to maintain but it can fully test functionality with proper rendering of elements and order of function calls
Static Rendering API [5]
It allows to generate HTML from React Components and then query HTML elements via Enzyme API. It might be useful when you want to compare HTML of components and you are not using Jest for snapshots
Setup with react-create-app
All setup for my examples is based on react-create-app [13] which I highly recommend you to start with. Setting up React Typescript app with some test framework is time consuming and if you want to play around React react-create-app should fully satisfy your needs
Ok letâs start. To make your first React application which will support Enzyme framework first you need to create it.
Depending on what Node tooling you have installed you can use npx,npm or yarn
. In my examples Iâll use npx
but if you want to use
something different check official react-create-app documentation
As at the time of writing this React version is set to 16 you need to use @types/enzyme-adapter-react-16. More about different types of adapters and official Enzyme installation guide can be found here
And thatâs it! From now on you should be able to work with Enzyme Typescript environment!
Examples
Ok, get ready for some Enzyme testing as shit is about to get real from now on. I prepared 3 examples which will show you how to use Enzyme and make usage of Shallow Rendering and Full Rendering. Hope you find it interesting and will come back to these examples in case of troubles with Enzyme
Example 1 - shallow rendering
To start I created simple React Component. Functional/Class Component it does not really matter
So in first file we create simple React Component SimpleButton
which renders button
element with props.name
.
What I would like to test here if is when I pass name
to this component it should render button
which contains text passed from props
Letâs move to something slightly bigger
Example 2 - different renderings
In this example Iâll show you the difference between Shallow and Full rendering and when to use them
For that we will need two components. First one is SimpleButton
which renders button
element with some text.
The second one ComplexComponent
should render p
tag with text and previously created SimpleButton
Letâs focus on the tests
First test is created to show you what is really rendered by Enzyme when you use Shallow and Full rendering.
As you can see in the output of tests for mount
(Full Rendering) and shallow
render different things
The main difference is that mount
renders whole ComplexComponent
and shallow
only component passed to it without child components
In this simple example I showed you that when you use mount
function the component that you want to test can be tested even when it has child components
Example 3 - async actions
Full Rendering with asynchronous code mock
Letâs get into some real life example. Usually when you create some components that send data they work on promises which take some time to fulfill. And here is the first big disadvantage of Enzyme that I couldnât bypass with something that does not look like a dirty hack
The problem is that whenever you make some async behavior inside component and trigger it on shadow
/mount
Enzyme component the invoked
function callback is not resolved immediatly after it is called
More about this weird behavior you can find here on Enzyme github but because itâs really messy and and solutions created in the comment of this issue are mostly horrible please check this blog [6] for more information
To conclude. As we want to make our test wait till Promise is resolved we need to have some utility function that will wait till all promises are resolved. This is the only semi-clean way I found and people usually suggest to follow this approach
What this pice of code does it creates a new Promise
which is executed in the next iteration of the event loop. [7]. What this allows us to do
is to wait till all promises are resolved. Whenever we call this function after asynchronous piece of code we will make sure that everything after
await flushPromises()
will be invoked when all promisses are resolved
Now to our tests
CovidList.tsx
import React from 'react';
export interface CovidListProps {
patients: string[];
}
export function CovidList(props: CovidListProps) {
return (
{props.patients.map((patient) => - {patient}
)}
);
}
I created some API for fetching list of patients and CovidDownloader
which uses this API and then display CovidList
of patinents
The tests I prepared first check in shallow render if component itself renders without data. Then next tests checks if when interation with component is made the list is being loaded from API
Conclusion
I think these are real basics which you need to know to make tests with Jest and Enzyme. When I was learning all of this I also found some interesting notes that I would like to share with you
- People complain about Enzyme a lot [6] no only because it has this problem with asynchronous testing but also because it is more focused on testing React Components than their behavior. A lot of people mention that nowdays you if you can choose framework for UI testing you should go with React Testing Library [8]. I havenât try it but a lot of people mention it as a better solution so maybe itâs worth checking before going into full Enzyme setup.
- You probably heard about Mocha [9] framework. It alows you to write test suites similar to Jest but when I tried to set it up with Enzyme it came out that it is not that easy and some config is required. It all comes down to jsdom [14] which is delivered with Jest package and not witk Mocha. So if you want to start using Enzyme without problems I would go with Jest if not this blog post [10] was very helpful when I was working with Mocha + Enzyme
And thatâs it! Hope you found this article interesting
All examples can be found on my github
Sources
https://enzymejs.github.io/enzyme/
[1] âIntroduction â Enzyme.âhttps://www.selenium.dev/downloads/
[2] âSelenium WebDriver.âhttps://github.com/enzymejs/enzyme/blob/9a092dd4cc7c59dcfaa7476a5b204e58e0c49f7e/docs/api/shallow.md
[3] âEnzymeShallow,â GitHub.https://github.com/enzymejs/enzyme/blob/9a092dd4cc7c59dcfaa7476a5b204e58e0c49f7e/docs/api/mount.md
[4] âEnzymeFullRendering,â GitHub.https://github.com/enzymejs/enzyme/blob/9a092dd4cc7c59dcfaa7476a5b204e58e0c49f7e/docs/api/render.md
[5] âEnzymeStatic,â GitHub.https://www.benmvp.com/blog/asynchronous-testing-with-enzyme-react-jest/
[6] âAsynchronous Testing with Enzyme & React in Jest,â Ben Ilegbodu. [7] âUnderstanding setImmediate(),â Understanding setImmediate(). [8] âReact Testing Library â Testing Library.â [9] âMocha - the Fun, Simple, Flexible JavaScript Test Framework.âhttps://semaphoreci.com/community/tutorials/testing-react-components-with-enzyme-and-mocha, Mar. 2016
[10] âTesting React Components with Enzyme and Mocha,â Semaphore.https://github.com/puppeteer/puppeteer, Sep. 2020
[11] âPuppeteer/Puppeteer.âhttps://www.testim.io/blog/what-is-the-difference-between-jest-and-enzyme/, Jan. 2020
[12] âWhat Is the Difference Between Jest and Enzyme?,â Fast authoring of AI-stabilized end-to-end testsâcodeless, coded, or both.https://github.com/facebook/create-react-app, Sep. 2020
[13] âFacebook/Create-React-App.âhttps://github.com/jsdom/jsdom, Nov. 2020
[14] âJsdom/Jsdom.â