Ts-jest: Forced commonjs breaks synthetic default imports

Created on 29 Mar 2017  Â·  27Comments  Â·  Source: kulshekhar/ts-jest

  • Issue

My React Native code writes imports as follows:

import React from "react";
import RN from "react-native";

...

class MyComponent extends React.Component<{}, {}> {

This works fine in the app, but fails in Jest with the error Cannot read property 'Component' of undefined. This seems to be because while my app's tsconfig has "module": "es6" and relies on Babel to convert the import statements, ts-jest forces commonjs which translates this to

const react_1 = require("react");

...

class MyComponent extends react_1.default.Component {

which is of course wrong. Until recently, I worked around this by writing a preprocessor which would run ts-jest and babel-jest in sequence, but this has been broken by the change https://github.com/kulshekhar/ts-jest/commit/192b493af8843a2387476d8de9a474067afc229e, which forces commonjs even if my tsconfig says otherwise.

You might ask why I don't just write import * as RN from "react-native" instead? Because of https://github.com/facebook/react-native/issues/12018. Besides, this conceptually makes for a better test in my mind- the app and the test code go through the same transformation pipeline (TypeScript followed by Babel).

  • Expected behavior

There should be a way to override the "module": "commonjs" setting.

Most helpful comment

esModuleInterop": true was the key for me. Thank you @diegoddox!

All 27 comments

@dphilipson commonjs was hardcoded in because using other module settings caused the coverage to stop working (#99, #121)

If you have a suggestion that allows your requirements to be met without breaking the other parts, I'd be happy to help take this forward.

Ah, I see, that's a good reason for doing so. Still, it would be nice to have the option to manually override if I don't care about coverage. Perhaps if module is explicitly set to something else in the __TS_CONFIG__ jest global then it should use that value?

@dphilipson the fix has been published. Can you see if the latest version works for you?

@kulshekhar This works perfectly and solves my problem. Thank you very much for the quick response, I really appreciate it!

@kulshekhar can you post a guide on doing this? I've been stuck on this for a day now.

 "jest": {
    "transform": {
      "^.+\\.js$": "<rootDir>/node_modules/babel-jest",
      ".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
    },
    "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx)$",
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js"
    ]
  },
  "globals": {
    "__TS_CONFIG__": {
      "module": "es2016"
    }
  }

The problem happens with moment. import moment from "moment", since i'm using allowSyntheticDefaultImports. Any tips?

@iRoachie do you need module to be set to es2016 for testing?

Yea. For some background, i'm using it with react native. If I change my imports in the components to be 'import * as moment from moment', then he tests work, but the app crashes with the worrier moment is not a function

Can you try import { moment } from 'moment';

Moment has no expected member 'moment'

it's hard to guess what's wrong. Can you create a minimal repo that reproduces this issue? Once done, open a new issue here to discuss this further

@iRoachie did you manage to fix this? I'm bumping into the same issue.

@ds300 Nah bro. I ended up scrapping running my tests on the typescript and instead run them on the compiled javascript instead.

@iRoachie #172 should have you covered if you want to fix that indirection.

@ds300 Any idea how to get around '__DEV__' is not defined for react native?

Not exactly sure where your problem is, can you be more explicit and/or
post an error message?

On 25 Apr 2017 4:18 pm, "Kyle Roach" notifications@github.com wrote:

@ds300 https://github.com/ds300 Any idea how to get around 'DEV' is
not defined for react native?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/kulshekhar/ts-jest/issues/146#issuecomment-297045029,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABL1qUzvjgDa9Qy7G1Au6jmdklxIBDSeks5rzgDPgaJpZM4MsR0U
.

screen shot 2017-04-25 at 10 23 15 am

It's a constant react-native uses while debugging

Can I see your jest config in package.json?

Same from the README.

{
  "jest": {
    "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"
    ]
  }
}

For react-native you need to set: "preset": "react-native"

And I think, as in the ts-jest readme, the transform field should look like this:

    "transform": {
      "^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest/preprocessor.js",
      "^.+\\.js$": "<rootDir>/node_modules/babel-jest"
    }

@ds300 Awesome that works! Will send a pr for the README.

I'm facing the same issue.
Error.
TypeError: Cannot read property 'Component' of undefined

package.json

...
"ts-jest": "^23.0.1",
"jest": "^23.4.2",
"babel-jest": "^23.4.2",
"babel-preset-react-native": "^4.0.0",
"typescript": "^2.9.2"
...
"jest": {
    "preset": "react-native",
    "setupFiles": [
      "./setupJest.js"
    ],
    "transformIgnorePatterns": [
      "node_modules/(?!(jest-)?react-native|react-navigation)"
    ],
    "testPathIgnorePatterns": [
      "build",
      "tests",
      "node_modules/"
    ],
    "cacheDirectory": ".jest/cache",
    "transform": {
      "^.+\\.js$": "babel-jest",
      ".+\\.(css|png)$": "jest-transform-stub",
      "^.+\\.tsx?$": "ts-jest"
    },
    "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
    "moduleDirectories": [
      "node_modules",
      "src"
    ],
    "moduleFileExtensions": [
      "ts",
      "js",
      "jsx",
      "tsx",
      "json",
      "node"
    ],
    "globals": {
      "ts-jest": {
        "useBabelrc": true
      },
      "__TS_CONFIG__": {
        "module": "esnext"
      }
    }
  }

tsconfig.json

...
"module": "esnext",
"allowSyntheticDefaultImports": true,
...

Any idea on how can I fix this?

Please open a new issue and link to the old one.

@diegoddox you ever get this to fly? Roughly the same config/setup as you and no matter what no joy unless import * as React from 'react'

@blujedis I can't remember exactly since was a while ago but here is the new config.

"jest": {
    "preset": "react-native",
    "verbose": true,
    "setupFiles": [
      "./setupJest.js"
    ],
    "transformIgnorePatterns": [
      "node_modules/(?!(jest-)?react-native|react-navigation)"
    ],
    "testPathIgnorePatterns": [
      "build",
      "tests",
      "node_modules/"
    ],
    "cacheDirectory": ".jest/cache",
    "transform": {
      "^.+\\.js$": "babel-jest",
      ".+\\.(css|png)$": "jest-transform-stub",
      "^.+\\.tsx?$": "ts-jest"
    },
    "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
    "moduleDirectories": [
      "node_modules",
      "src"
    ],
    "moduleFileExtensions": [
      "ts",
      "js",
      "jsx",
      "tsx",
      "json",
      "node"
    ],
    "globals": {
      "__DEV__": true,
      "ts-jest": {
        "useBabelrc": true,
        "tsConfigFile": "tsconfig.test.json"
      }
    }
  }

tsconfig.test.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true
  }
}

@diegoddox I got it working with a hacky workaround but thx I'll try it today!

esModuleInterop": true was the key for me. Thank you @diegoddox!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

TKJohn picture TKJohn  Â·  4Comments

ozum picture ozum  Â·  4Comments

qm3ster picture qm3ster  Â·  3Comments

jbreckmckye picture jbreckmckye  Â·  3Comments

stangerjm picture stangerjm  Â·  4Comments