Jest / TypeScript / Mono-Repository … where is my code coverage ?

28 / 10 / 2020

I have been working on a project using a mono-repo layout to build well scoped modules. Of course some unit tests are available to ensure good quality and maintainability over time. However, one thing didn’t work properly: coverage.

Seems there is an issue with the underlying libs (ts-jest, Istanbul, jest, ….) to make the coverage feature in Jest works properly. There is an open issue on Github.

After some research and tries …. I have managed to find a weird combo that make the coverage works.

To make it short, Jest has introduced a while back a way to split configuration per project inside a repository. This feature allows to trick how Jest and other libs work together.

The projects key property is an array of object, each object represents a project within the repository. It is possible to reuse almost all main configurations for each project. It is a neat feature if you need specific rules per folder (or project…)!

So, in my use cases, I have created 2 projects one for packages and one for examples.

{
  "projects": [{
    "displayName": {
      "name": "Packages",
      "color": "magenta"
    },
    "preset": "ts-jest",
    "testMatch": [
      "<rootDir>/packages/*/src/*.test.ts",
      "<rootDir>/packages/*/src/**/*.test.ts"
    ]
  }, {
    "displayName": {
      "name": "Examples",
      "color": "blue"
    },
    "preset": "ts-jest",
    "testMatch": [
      "<rootDir>/examples/api-contentful/**/*.test.ts"
    ]
  }]
 }

The important part of the trick is to make sure the collectCoverageFrom is well configured with no base root defined. Something like this:

"collectCoverageFrom": [
  "**/*.{ts,tsx}",
  "!**/*.test.{ts,tsx}",
  "!**/dist/**"
]

With projects + collectCoverageFrom you can now have a proper working coverage for ts-jest + mono-repository. The code might used different paths to resolve what files are being used or not using the projects settings