Ts-jest: Sourcemap support when debugging (Intellij IDEA / Webstorm / others)

Created on 3 Apr 2017  Â·  23Comments  Â·  Source: kulshekhar/ts-jest

When debugging Jest tests in IDEA I set breakpoints but they are never triggered. I assume this is related to sourcemaps somehow.

Jest correctly gives Typescript filename+line when reporting errors / expect failures, so at this level sourcemaps are working.

This is more of a request for help than bug report. Do people have debugging fully working in your preferred IDE when running Jest tests?

For info, Jetbrains recently released integrated Jest support with progress bar, etc.

image

Here is the full command executed by IDEA:

"C:\Program Files\nodejs\node.exe" --debug-brk=7830 --expose_debug_as=v8debug C:\Users\alfie\gb\gb-util\node_modules\jest\bin\jest --config "{\"transform\":{\".ts$\":\"<rootDir>/node_modules/ts-jest/dist/preprocessor.js\"},\"testRegex\":\"(/__tests__/.*|\\.(test|spec))\\.(ts|tsx)$\",\"moduleFileExtensions\":[\"ts\",\"tsx\",\"js\"],\"rootDir\":\"C:\\Users\\alfie\\gb\\gb-util\",\"transformIgnorePatterns\":[\"/node_modules/\",\"^C:\\Program Files (x86)\\JetBrains\\IntelliJ IDEA 171.3780.15\\plugins\\JavaScriptLanguage\\helpers\"]}" --no-cache --runInBand --colors --setupTestFrameworkScriptFile "C:\Program Files (x86)\JetBrains\IntelliJ IDEA 171.3780.15\plugins\JavaScriptLanguage\helpers\jest-intellij\lib\jest-intellij-jasmine.js" --testPathPattern ^C:\\Users\\alfie\\gb\\gb\-util\\src\\misc\\FlexibleIterator\.spec\.ts$ --testNamePattern "^Flexible iterator Should yield last item after sub\-iterator$"

tsconfig.js:

{
  "compilerOptions": {
    "jsx": "react",
    "module": "commonjs",
    "experimentalDecorators": true,
    "outDir": "./build",
    "preserveConstEnums": true,
    "compileOnSave": true,
    "removeComments": true,
    "sourceMap": true,
    "inlineSources": true,
    "target": "es6",
    "strictNullChecks": true,
    "noImplicitAny": true,
    "noImplicitThis": true,
    "noUnusedParameters": true,
    "noUnusedLocals": true
  },
  "exclude": [
    "node_modules",
    "build"
  ]
}

package.json:

{
  "name": "gb-util",
  "author": "Alfie Kirkpatrick",
  "version": "1.0.0",
  "description": "Typescript utilities",
  "main": "build/index.js",
  "typings": "build/index.d.ts",
  "license": "UNLICENSED",
  "scripts": {
    "test": "jest --no-cache"
  },
  "devDependencies": {
    "@types/jest": "^19.2.2",
    "jest": "^19.0.2",
    "ts-jest": "^19.0.1",
    "typescript": "^2.2.1"
  },
  "jest": {
    "transform": {
      ".ts$": "<rootDir>/node_modules/ts-jest/dist/preprocessor.js"
    },
    "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx)$",
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js"
    ]
  },
  "unused": {},
  "dependencies": {
    "global": "^4.3.1"
  }
}

Most helpful comment

Hi @kulshekhar, thanks for response. Here is a link to minimal test project: https://github.com/jugglingcats/ts-jest-idea

All 23 comments

If there's a minimal repo that I could use to test this with WebStorm/IDEA, I could look into this much earlier than if I had to set a project up from scratch. It would also help me replicate your settings exactly if you include the .idea directory in git

Hi @kulshekhar, thanks for response. Here is a link to minimal test project: https://github.com/jugglingcats/ts-jest-idea

Modifying the default debug config in idea to run Compile Typescript before launch got this working.

ts-jest-idea

Interesting, I tried that and it's not working for me. No breakpoint hit.

I just noticed that you use the Run button (play button). I used the Debug button (bug button)

I'm using the debug button ;)

Out of interest are you initiating the test run from the .ts file or the build\test.spec.js file?

I am able to set a breakpoint in the .ts file and it will fire correctly _if I initiate the test from the .js file_. But in this case the pre-processor is not invoked, so ts-jest is not involved, if I understand correctly.

It seems like when you run using the pre-processor it doesn't use the source maps in build. Which kind of makes sense, just not sure if it's fixable.

In my configuration, I set Jest to run on the entire project. I don't think (for the way I have set it up) it matters where debugging is initiated from. Here are the exact steps I took:

  1. git clone https://github.com/jugglingcats/ts-jest-idea
  2. cd ts-jest-idea
  3. yarn install
  4. Open the project in WebStorm
  5. Create a configuration (Run > Edit Configurations)
  6. Add a Jest configuration
  7. Add Compile Typescript in the list of tasks to execute before launch. The configuration is set to run All tests
  8. Press the debug button - all tests run fine:
 Debugger listening on [::]:41105
 PASS  build/test.spec.js
 PASS  ./test.spec.ts

Test Suites: 2 passed, 2 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        3.135s, estimated 5s
Ran all test suites.

Process finished with exit code 0
  1. Open test.spec.ts, add a breakpoint and press the debug button again to get the state that I posted a screenshot of earlier

Ah, ok, that is working for you because you are matching both the .ts sources and the build/*.js generated files. You can see this because 2 test suites are passed!

When you are running the build/test.spec.js file you have the generated sourcemaps too, so your breakpoint in the .ts file is working.

It appears to me that if there's a solution to what you want, it is likely somewhere in Webstorm's configuration/support and not ts-jest :)

I tried a couple of things and got a strange behaviour:

  • Removed the pre-processor config in package.json
  • Added test2.spec.js alongside test.spec.ts with same content (note the .js extension)

The original test.spec.ts is actually valid ES6, so pre-processor is not actually needed.

I also removed Typescript Compile build step and deleted build so it no longer exists.

Now when I debug test2.spec.js I can set and hit a breakpoint no problem.

But when I debug test.spec.ts I don't hit the breakpoint!

The command line that IDEA is using is identical except the filename... very odd.

I don't think this particular behaviour is a ts-jest issue but even if it were able to hit a breakpoint I don't think things will work correctly (see next comment)

Back to sourcemaps...

I added the pre-processor back in, and I've also added custom cacheDirectory parameter to see what is being generated more easily.

The following file is generated:

'use strict';require('ts-jest').install();"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
describe("a test", function () {
    it("should have a breakpoint", function () {
        const x = 1;
        expect(x).toBe(1);
    });
});
//# sourceMappingURL=test.spec.js.map

Note that I still haven't added Compile Typescript back in the run configuration (no build directory exists). Even if build files were there, the sourceMappingURL has no relative path and so probably won't be found?

To test this theory I generated the build files again, hacked the pre-processor output file and modified the path to be ./build/test.spec.ts.map and whoa breakpoint was hit!

Sorry just saw your last comment. I think the sourcemap location issue is potentially fixable in ts-jest, assuming the facility is there for you to specify a relative path. Determining the correct relative path may not be trivial though. You would need the outDir from tsconfig.json, but there are other nuances: for example, tsc does clever things to prune unnecessary levels in the source structure (ones that don't have any .ts sourcefiles).

I think the sourcemap location issue is potentially fixable in ts-jest

If this is the case, it'd be great to update ts-jest. I'd be happy to take a PR if you want to give it a shot :smile:

Heheh I found your previous question to the Jest devs here: https://github.com/facebook/jest/issues/1474.

That gave me a clue about inline sourcemaps, so I added inlineSourceMap: true to my tsconfig.json and it all started working!

This config setting causes the sourcemap to be emitted right into the target file using the data:application/json url protocol.

It would be nice if ts-jest did this by default. I hacked the following into preprocessor.js and it seemed to do the trick: compilerOptions.inlineSourceMap=true;

Not sure this is worthy of a pull request... :)

@jugglingcats if that worked then setting that value in jest config should also work. Could you try that?

@jugglingcats you're right! Setting inlineSourceMap: true in the jest config did the trick. I didn't even have to set the config to run typescript compilation :smile:

I'm going to leave this open till I can add tests for this and set this value if it hasn't been explicitly set by the user. That should prevent others from facing this issue!

Actually, it'll be better to track this is a new issue - #151

@jugglingcats is it fine if this issue were closed?

It worked for me too. Example project and readme updated. Many thanks - we're done here.

I'm just going to dig this up from the grave, as I seem to have an issue that's almost the same, but not quite.

The inlinesourcemap work reasonably fine, but the only way I can get the debugger to do anything, is if i set an actual debugger; statement - breakpoints are simply ignored.

Is this something any of you came across during your digging?

my package.json's jest looks like this:

    "jest": {
        "preset": "react-native",
        "transform": {
            "^.+\\.js$": "<rootDir>/node_modules/babel-jest",
            ".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
        },
        "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
        "moduleFileExtensions": [
            "ts",
            "tsx",
            "js",
            "json"
        ],
        "globals": {
            "__DEV__": true,
            "__TS_CONFIG__" : {
                "jsx": "react",
                "allowSyntheticDefaultImports": true,
                "target": "es2015",
                "moduleResolution": "node",
                "inlineSourceMap": true
            }
        }
    }

@GeeWee everything we did when we were working on this is mentioned here in this issue. If that doesn't help, the best thing would be to create a minimal repo that reproduces this and create a new issue

Thanks @kulshekhar - it has been done - #209

I could not get my breakpoints to hit in Webstorm 2018.1.5 with ts-jest 22.4.0. I tried all of the above solutions, but it turns out it was because I was using node v7.10.1

I upgraded to node v8.9.4 and my breakpoints were instantly working. Hopefully this saves someone some struggle.

@akos-sebestyen FYI:

  • You don't want to stay on odd-numbered releases of NodeJS (like 7, 9, ...). They are EOL (end-of-life, no more maintained) as soon as the next even-numbered release is out (which will be LTS = long term support) – see here
  • It sounds that you're using ts-jest 22. Unless you CAN'T upgrade for some reason, it'd be better that you switch to latest versions of jest and ts-jest (you might have to/should also upgrade some other packages as well which jest rely on). In any case you want major version of ts-jest to follow the one of jest. Also strongly advised to upgrade typescript:

    • jest latest is 23.6.0

    • ts-jest latest is 23.1.4 but I strongly advise you to test out beta (see #697)

    • typescript latest is 3.0.3

You can see breaking changes of Jest there

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Slessi picture Slessi  Â·  3Comments

japhar81 picture japhar81  Â·  3Comments

mikeyakymenko picture mikeyakymenko  Â·  3Comments

artola picture artola  Â·  3Comments

Vinnl picture Vinnl  Â·  3Comments