How to Set up React Test with Mocha and Enzyme for TypeScript

Enzyme is created by Airbnb for React component testing. You can easily test components’ output and it works with different testing frameworks like Mocha or Jest. This post focuses on setting up the test environment with Mocha for TypeScript.

If you are used to JavaScript and fairly new to TypeScript, setting up unit test can be cumbersome. Basically, TypeScript complains about almost everything that you used to do with JavaScript. However, once you get your head around it, it becomes easier. When I set this up first time, it took me a long time to figure out why TypeScript is complaining about things like window does not exist on type Global or mount method not working because a global document is not loaded. But, getting this work helped me to understand TypeScript a little bit better.

The complete example can be found on this repo.

Let’s get started.

(1) Install dependencies

With TypeScript, you need to install a regular module and @types module. Most of the common modules has @types available these days. So, you can simply install the regular module as well as the one prefixed with @types. Some modules are written in TypeScript and you don’t need to install @types. For example, a test coverage tool, istanbul is written in TypeScript and does not require any type module.

Using chai for assertion library. ts-node is also required to run TypeScript in the node environment. Later, you need to register ts-node in the mocha command.

npm i chai mocha ts-node --save-dev
npm i @types/chai @types/mocha @types/sinon --save-dev

Now, let’s install dependencies for Enzyme. Mocha doesn’t run tests in a Node environment, not in a browser environment. Therefore, enzyme’s mount API requires a DOM. To simulate a browser environment, we are using JSDOM.

npm i enzyme jsdom jsdom-global enzyme-adapter-react-16
npm i @types/enzyme @types/jsdom @types/enzyme-adapter-react-16 --save-dev

(2) Creating test setup file

Node environment where mocha runs tests does not have browser properties. We first need to add types for required browser environment properties by extending interface and adding properties.Newly created globalNode object has window, document and navigator properties. All we need to do is assign JSDOM window object to the window. This will create window globally.

Here is the entire test set up code. Configuring enzyme adapter is the same as regular JavaScript.

(3) Getting the test script right

In package.json file, you can use the test script as below. Component test uses jsx file because you need to use React. Make sure to include both .ts and .tsx files.

mocha -r ts-node/register -r jsdom-global/register -r unitTestSetup.ts **/test/**/*.ts test/**/*.tsx --recursive --timeout 5000

(4) Simple test example

Here is the sample component test example. It should work by typing npm test

Common Errors

Here are the list of common errors and how to handle them.

It looks like you called mount() without a global document being loaded

  • Mocha doesn’t run the test in a browser environment & enzyme’s mount API requires a DOM. JSDOM is required to simulate a browser environment in a Node environment.

‘window is not defined’

  • It can be overcome by installing jsdom-global and adding -r jsdom-global/register in mocha command

Property ‘window’ does not exist on type ‘Global’ error

  • When we create setup file for JSDOM (unitTestSetup.ts on the root folder), we need to add browser properties to Node global environment as it does not have browser properties. We can extend NodeJS.Global properties by adding interface and redefining the global variable with global Node variable.
Front-End
TypeScript: type aliases to check type equality

This post is to analyse how the type equality check by using type aliases proposed by Matt Pocock in his twitter post. These type aliases allow us to elegantly express type equality checks in unit tests. All we need to do is to pass the output and expected types in …

Front-End
Fixing it.only type error in Jest

If you are getting a type error with it.only in Jest, it could be due to incorrect TypeScript typings or incompatible versions of Jest and TypeScript. To resolve this issue, you can try the following steps: Make sure you have the latest versions of Jest and its TypeScript typings installed …

Front-End
yup conditional validation example

Here’s an example of a Yup validation logic where the first input field is optional but, if filled, it must contain only alphabetic characters, and the second input field is required: import * as Yup from “yup”; const validationSchema = Yup.object().shape({ firstField: Yup.string().matches(/^[A-Za-z]*$/, { message: “First field must contain only …