Jest for a Typescript-based React app

I recently had to install and configure Jest in a React app written using Typescript and ran into quite a few roadblocks. So, I thought of detailing the steps I followed to overcome the difficulties.

I used Jest as the test runner, and React Testing Library to test the React components.

Installing the dependencies

First, let’s install the needed dependencies.

npm install --save-dev @testing-library/jest-dom @testing-library/react @types/jest jest ts-jest

Here, @testing-library/jest-dom is used to extend the Jest matchers and ts-jest is used to help Jest test Typescript files. @types/jest provides the type definitions for the Jest library.

Configuring Jest

Once installed, then we need to configure Jest. We can do this by creating a key called jest in the package.json file and passing the configurational details into it as a value object.

“jest”:{}

Transforming Typescript files

First, let’s configure Jest to transform all the Typescript files using the ts-jest transformer. Create a key called transform and then pass the file pattern to be transformed and the transformer you want to use as a child key-value pair. Here, both tsx files and ts files will be transformed using the ts-jest transformer.

"jest": {
         "transform": {
             "^.+\\.tsx$": "ts-jest",
             "^.+\\.ts$": "ts-jest"
         }
     }

Declaring global constants

If there are global constants you are using in your project—such as the ones you created using the Webpack DefinePlugin—then you can declare them in the configuration so that Jest can understand the constants in your code. You can use the child key called globals to that end.

"jest": {
        "globals": {
            "APP_NAME": "Demo"
        },
        "transform": {
            "^.+\\.tsx$": "ts-jest",
            "^.+\\.ts$": "ts-jest"
        }, 
    }

Mocking files

Next, we need to mock the static files and stylesheets used in our app. To mock these, first, we need to create two mock files. I created a directory called mocks and created two mock files called file_mock.js and style_mock.js. which export dummy values using the CommonJS module format. This is the content of the mock files.

module.exports = "";

After completing the above steps, we need to tell Jest to mock files using our mock files. To do that, we need to use the moduleNameMapper key. Pass the regex file pattern to match the files you want to mock as the key and the path to the mock files as the value. You can use <rootDir> to refer to the root of your project directory.

 "jest": {
        "globals": {
            "APP_NAME": "Demo"
        },
        "transform": {
            "^.+\\.tsx$": "ts-jest",
            "^.+\\.ts$": "ts-jest"
        },
        "moduleNameMapper": {
            "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/src/mocks/file_mock.js",
            "\\.(css|less)$": "<rootDir>/src/mocks/style_mock.js"
        }
    }

Extending expect of Jest

This configuration should work fine. But when using the React Testing Library, we may have to use additional matchers such as toBeInTheDocument() which are not provided by Jest by default. So, we need to use the extend-expect module provided by @testing-library/jest-dom.

However, whenever we need to use these additional matchers, we need to import the extend-expect module into each and every test file, and this can be really inconvenient.

To solve this issue, we can have Jest import this module once and have it available across all our test files. To do this, first, let’s create a file called setup_test.js. Let’s import the extend-expect module into it.

import "@testing-library/jest-dom/extend-expect";

Now, we need to tell Jest to load it before each test. We can do so by passing the path of the setup_test.js file into the setupFilesAfterEnv array in the jest configuration. Again, <rootDir> can be used to refer to the root of the project. So, your final configuration would like this:

"jest": {
        "globals": {
            "APP_NAME": "Demo"
        },
        "transform": {
            "^.+\\.tsx$": "ts-jest",
            "^.+\\.ts$": "ts-jest"
        },
        "moduleNameMapper": {
            "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/src/mocks/file_mock.js",
            "\\.(css|less)$": "<rootDir>/src/mocks/style_mock.js"
        },
        "setupFilesAfterEnv": [
            "<rootDir>/src/setup_test.ts"
        ]
    },

That’s it, you are good to start writing tests for your app. You can find the sample repo here.

Leave a Reply

placeholder="comment">