ts-jest: TypeError: mappedCoverage.addStatement is not a function

  • Issue

I updated my project to Jest 20.0.1 and updated ts-jest to 20.0.3 as well. I tried out the new coverage feature and get following error:

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): TypeError: mappedCoverage.addStatement is not a function
  • Expected behavior

Coverage should run.

  • my config
"jest": {
    "globals": {
      "__TS_CONFIG__": "./test/tsconfig.json"
    },
    "transform": {
      ".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
    },
    "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
    "testPathIgnorePatterns": [
      "<rootDir>/build"
    ],
    "snapshotSerializers": [
      "enzyme-to-json/serializer"
    ],
    "setupTestFrameworkScriptFile": "./test/setupTestFramework.ts",
    "mapCoverage": true,
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js"
    ],
    "moduleNameMapper": {
      "\\.(svg|woff|ttf|eot)$": "<rootDir>/test/__mocks__/fileMock.js",
      "\\.(css)$": "<rootDir>/test/__mocks__/styleMock.js"
    },
    "setupFiles": [
      "./test/setupJest.ts"
    ]
  },

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 37 (19 by maintainers)

Commits related to this issue

Most upvoted comments

I’ve had another look into this - the issue (at least with my config) is when allowSyntheticDefaultImports is set to true. If set, the preprocessor runs files through babel-jest and appends a .js extension onto them. When the coverage is generated, both the .ts / .tsx and .ts.js / .tsx.js files are run through the coverage generator, but source maps are only found for .ts.js / .tsx.js files, so the original files encounter the problems I described above with missing source maps.

I’m afraid this is about as far as I can take it in terms of a fix, but I hope the above info is helpful to whoever picks this up.

I had this issue at work last week, but being relatively new to TypeScript I assumed it was some form of configuration I’d set incorrectly. I didn’t find the problem, but I traced it down to istanbul-lib-source-maps - it appears that it’s unable to find a source map, so it just uses a file coverage object for the given file:

https://github.com/istanbuljs/istanbuljs/blob/master/packages/istanbul-lib-source-maps/lib/transformer.js#L161

Then due to this it doesn’t instantiate MappedCoverage:

https://github.com/istanbuljs/istanbuljs/blob/master/packages/istanbul-lib-source-maps/lib/transformer.js#L152

This is when I assumed I’d screwed up generating source maps and went back to experimenting with that, but didn’t get any further before I left for the weekend. Only thing I really tried doing was using inlineSourceMap instead of sourceMap.

The only other bits of info I can give at the moment that may help is that I’m also pretty sure if I put in a check for addStatement being available before it is called (along with addFunction and addBranch which also are missing), it did go ahead and generate everything successfully as far as I could see. I also had it working on a branch that just contained a couple of tests for very basic functions in .ts files, but when .tsx files and Enzyme were threw into the mix as well that’s when the issues started.

LGTM 👍

@Apidcloud babel is used only when allowSyntheticDefaultImports is set to true. The PR for that was accepted in response to issues that users were facing. All these users needed to use babel for one reason or another.

Now, if you need to use allowSyntheticDefaultImports and don’t want to use babel, you can set skipBabel to true in package.json jest > globals > ts-jest > skipBabel

@screendriver - I think that might be a jest cache issue - try running it with --no-cache. It works in my tests, however the coverage numbers are a little off from earlier, and I haven’t had time to look into what is correct. @jrwebdev - Interesting, I think I’ll try monkey patching babel-jest and see if you’re right. @lukescott - interesting. Do you have some code locations you can share where you see this?

To clarify, I get this error whether or not I use allowSyntheticDefaultImports

Repo for repro here: https://github.com/ecozoic/react-starter/tree/typescript-2

UPDATE: Deff seems to be something w/ ts-jest, I swapped out the ts-jest preprocessor for a simple one based on the official examples and I’m able to get coverage reports working (although it doesn’t look like remapping is working…).

const tsc = require('typescript');
const tsConfig = require('../tsconfig.json');

tsConfig.compilerOptions.module = 'commonjs';
tsConfig.compilerOptions.inlineSourceMap = true;
tsConfig.compilerOptions.inlineSources = true;

delete tsConfig.compilerOptions.sourceMap;
delete tsConfig.compilerOptions.outDir;

module.exports = {
  process(src, path) {
    if (path.endsWith('.ts') || path.endsWith('.tsx')) {
      return tsc.transpile(src, tsConfig.compilerOptions, path, []);
    }
    return src;
  },
};

UPDATE 2: Clearing the Jest cache fixed the mapping issues. So that code snippet seems to work.

Removing allowSyntheticDefaultImports didn’t seem to fix it for me, but it definitely seems .tsx file related. If I run my tests only on .ts files, I get coverage reports no problem. Once you put .tsx files in the mix (via testRegex), I get the error. I’m able to specify tsx files in the collegeCoverageFrom and they will show up in the report (0% coverage), but executing the tsx file tests is what causes the error.

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "module": "es2015",
    "moduleResolution": "node",
    "rootDir": "src/client",
    "outDir": "dist",
    "sourceMap": true,
    "lib": ["es2015", "dom"],
    "jsx": "react",
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noUnusedLocals": true,
    "suppressImplicitAnyIndexErrors": true
  }
}

jest.conf.json

{
  "collectCoverage": false,
  "collectCoverageFrom": ["src/client/app/**/*.{ts,tsx}"],
  "coverageDirectory": "<rootDir>/coverage/client",
  "coverageReporters": ["json", "lcov"],
  "mapCoverage": true,
  "moduleFileExtensions": [
    "ts",
    "tsx",
    "js"
  ],
  "moduleNameMapper": {
    "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|ico)$": "<rootDir>/jest/file-mock.js",
    "\\.(css|less|sass|scss|styl)$": "identity-obj-proxy"
  },
  "roots": ["src/client"],
  "snapshotSerializers": ["enzyme-to-json/serializer"],
  "testEnvironment": "jsdom",
  "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx)$",
  "transform": {
    ".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
  }
}