JT in Helsinki

Home About RSS

ES6 breaking your Jest tests?

  • javascript, testing, jest

Jest is a library for testing JavaScript code. For me, the biggest benefit of Jest is that it works without having to interact with other testing libraries. Developed by Fcebook, it’s also well suited for React code testing. I like it.

However, as Jest runs off node, if you’ve tried to use Jest to test code that depends on libaries using ES6 code, you have likely run into trouble. Most common is when using dependencies which use ES6 modules.

In my case, I used the Create React Application to seed my project. This gives all the basics to get started however you will need to perform some extra steps to get up and running. If you don’t use the CRA then the configuration files should still be similar.

Steps to Configure

To do this requires the use npm run eject. This will destroy the dependency on the Create React App library. This is a one way operation.

  1. npm run eject inside the root of your project. This will create a number of configuration scripts which can be used to run the application. Remove the Jest and Babel configurations from the project’s package.json.
  2. Upgrade babel. The easist way to do this is to use the Babel-Upgrade tool. This can be found at https://github.com/babel/babel-upgrade. Remove any remaining references to Babel 6.
  3. Delete the node_modules directory and reinstall the updated dependencies running npm install
  4. In the root of your project create the following two files:
    • /babel.config.js ([contents](#babel.config.js))
    • /jest.config.js ([contents](#jest.config.js))
  5. Run the following command to install the required babel plugins and settings:
    • npm install --save-dev @babel/preset-react @babel/preset-env @babel/plugin-transform-modules-commonjs @babel/plugin-syntax-dynamic-import @babel/plugin-syntax-import-meta @babel/plugin-proposal-class-properties @babel/plugin-proposal-json-strings
  6. In the config/jest directory create the following files:
    • /config/jest/setupTests.js ([contents](#contents.js))
    • /config/jest/typescriptTransform.js ([contents](#typescriptTransform.js))
    • /config/jest/cssTransform.js ([contents](#cssTransform.js))
  7. Remove any unused files from the config/jest directory. If it’s not specified in the jest.config.js file then it’s not used.

File Contents

/babel.config.js

The contents of the babel.config.js file should be as follows:

'use strict';

module.exports = {
    env: {
        test: {
            presets: [
                ['@babel/preset-env',
                {
                    debug: true,
                    modules: "commonjs"
                }],
                '@babel/preset-react',
            ],
            plugins: [
                "@babel/plugin-transform-modules-commonjs",
                "@babel/plugin-syntax-dynamic-import",
                "@babel/plugin-syntax-import-meta",
                "@babel/plugin-proposal-class-properties",
                "@babel/plugin-proposal-json-strings"
            ],
        },
    },
};

/jest.config.js

Assuming your tests are in the <PROJECT_ROOT>/test directory. The contents of the jest.config.js file should be as follows:

'use strict';

module.exports = {
    "testEnvironment": "jsdom",
    "setupFilesAfterEnv": [
        "<rootDir>/config/jest/setupTests.js"
    ],
    "coverageReporters": [
        "lcov"
    ],
    "collectCoverageFrom": [
        "<rootDir>/src/**/?(*.)+(spec|test).[jt]s?(x)",
        "!<rootDir>/test/**/?(*.)+(spec|test).[jt]s?(x)",
        "!<rootDir>/src/**/*.d.ts"
    ],
    "coverageThreshold": {
        "global": {
            "branches": 75,
            "functions": 80,
            "lines": 80,
            "statements": 80
        }
    },
    "testMatch": [
        "<rootDir>/test/**/?(*.)+(spec|test).[jt]s?(x)"
    ],
    "transform": {
        "^.+\\.(js|jsx|mjs)$": "<rootDir>/node_modules/babel-jest",
        "^.+\\.(tsx|ts|js|jsx)$": "<rootDir>/config/jest/typescriptTransform.js",
        "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js"
    },
    "transformIgnorePatterns": [
    ],
    "moduleNameMapper": {
        "@src/(.*)": "<rootDir>/src/$1",
        "@test/(.*)": "<rootDir>/test/$1"
    },
    "moduleFileExtensions": [
        "ts",
        "tsx",
        "js",
        "jsx",
        "json",
        "css",
        "node"
    ]
}

/config/jest/setupTests.js

(Assuming you are using Enzyme)

'use strict';

const Enzyme = require('enzyme');
const Adapter = require('enzyme-adapter-react-16');

Enzyme.configure({ adapter: new Adapter() });

/config/jest/typescriptTransform.js

'use strict';

const tsJestPreprocessor = require('ts-jest');

module.exports = tsJestPreprocessor;

/config/jest/cssTransform

'use strict';

module.exports = {
    process() {
        return 'module.exports = {};';
    },
    getCacheKey() {
        // The output is always the same.
        return 'cssTransform';
    },
};