Configuration for Jest
Tags: testing, typescript, jest
Published: 2021-09-04 12:24:04

##Testing framework
Besides development, **testing** plays an important role, it helps us to make sure any developed feature works as expected. Especially in *the refactoring codebase process*, the business has to be the same, so we just basically go through all the test cases without changing them. If all of them are passed, our new codebase is good to go.

There are a lot of testing framework for Javascript (JS), which has thier own strength and weakness. Please take a look on this [Comparing JS testing framework](https://openbase.com/categories/js/best-nodejs-testing-framework-libraries) to find one. In this post I will use **Jest**.

##Configuration
###My configuration
I use the configuration below in most of my Typescript projects. Because there are some important parts, I will explant them later, but for others, you can search in [configuration files](https://jestjs.io/docs/configuration)
```
import path from 'path';
const rootDirector = path.resolve(__dirname);

export default {
  clearMocks: true,
  collectCoverage: true,
  coverageDirectory: 'coverage',
  coverageProvider: 'v8',
  coverageThreshold: {
    global: {
      branches: 70,
      function: 80,
      lines: 80,
      statements: 80,
    },
  },
  globals: {
    'ts-jest': {
      tsconfig: path.resolve(__dirname, 'tsconfig.json'),
    },
  },
  moduleDirectories: ['node_modules'],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  moduleNameMapper: {
    '@server(.*)$': `${rootDirector}/src$1`,
    '@config(.*)$': `${rootDirector}/src/config$1`,
    '@tests(.*)$': `${rootDirector}/__tests__$1`,
    '@domain(.*)$': `${rootDirector}/src/domain$1`,
    '@controller(.*)$': `${rootDirector}/src/controller$1`,
    '@middleware(.*)$': `${rootDirector}/src/middleware$1`,
  },
  reporters: [
    'default',
    [
      path.resolve(__dirname, 'node_modules', 'jest-html-reporter'),
      {
        pageTitle: 'Demo test Report',
        outputPath: 'test-report.html',
      },
    ],
  ],
  rootDir: rootDirector,
  roots: [rootDirector],
  setupFilesAfterEnv: [`${rootDirector}/__tests__/setup.ts`],
  testPathIgnorePatterns: [
    '/node_modules/',
    '<rootDir>/build',
    `${rootDirector}/__tests__/fixtures`,
    `${rootDirector}/__tests__/setup.ts`,
  ],
  transform: {
    '^.+\\.ts$': 'ts-jest',
  },
  testRegex: ['((/__tests__/.*)|(\\.|/)(test|spec))\\.tsx?$'],
};
```

###To use
- Yup, first step is always installing the [package](https://www.npmjs.com/package/jest), we can use the below command to do it. Besides, we are going to setup Jest config for **TS** project, so remember to install [ts-test](https://www.npmjs.com/package/ts-test) also.
```
#For npm
npm install --save-dev jest ts-jest

#For yarn
yarn add --dev jest ts-jest
```

- Create a file `jest.config.ts` or `jest.config.js` at the root level, and copy the configuration above to this file.
- Add a script `"test": "jest"` to `scripts` in our **package.json**. By default, without the flag `--config`, **jest** will search in root level for the configuration file, otherwise, we need to evaluate value for `--config`, and also update options in the config, like `ts-jest`, `reporters`, and so on.
```
# Root level
"scripts": {
    "test": "jest",
},

# With config flag
"scripts": {
    "test": "jest --config='./jest-config/jest.config.ts'",
},
```

###Explaination
- **Importing Path module**: the module helps us navigate directory easier. In case we let `jest.config.ts` in other folder, let say `jest-config`:
  - `<rootDir>` in this case is the directory that we put in flag `--config`, so now the value for `setupFilesAfterEnv` must be `['<rootDir>/../__tests__/setup.ts']`
  - if we use `path` module, `rootDirector` will point to root level. 
```
#Without path module
setupFilesAfterEnv: [`<rootDir>/../__tests__/setup.ts`]

#With path module
setupFilesAfterEnv: [`${rootDirector}/__tests__/setup.ts`]
```
- **globals**: because **Jest** can't undestand **TS**, we need to install additional module `ts-test`, and also define `ts-test` config in this option.
- **moduleNameMapper**: in the post [tsconfig.json](https://dev.to/maithanhdanh/configuration-for-tsconfig-json-3bg5), I use `module-alias` to simlify importing modules, so I need to register those mappings again.
- **transform**: it is the place for us to define pattern filename for each testing framework. In my config, I just use ts-test to test my TS modules.
- **testRegex**: this option is used to let **Jest** know how our test files look like, where they are.

_To be honest, [Mock](https://jestjs.io/docs/mock-functions) is the most important term in testing. If you want to follow developer journey, I suggest you fully understand this term_

[Paypal](https://paypal.me/DantisMai).

_I hope this post helps you with config testing environment for your project. I am really happy to receive your feedback on this article. Thanks for your precious time reading this._