Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forced commonjs breaks synthetic default imports #146

Closed
dphilipson opened this issue Mar 28, 2017 · 27 comments
Closed

Forced commonjs breaks synthetic default imports #146

dphilipson opened this issue Mar 28, 2017 · 27 comments

Comments

@dphilipson
Copy link

dphilipson commented Mar 28, 2017

  • 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 192b493, 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 facebook/react-native#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.

@dphilipson dphilipson changed the title Forced commonjs breaks synthetic imports Forced commonjs breaks synthetic default imports Mar 28, 2017
@kulshekhar
Copy link
Owner

@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.

@dphilipson
Copy link
Author

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?

@kulshekhar
Copy link
Owner

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

@dphilipson
Copy link
Author

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

@iRoachie
Copy link
Contributor

@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?

@kulshekhar
Copy link
Owner

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

@iRoachie
Copy link
Contributor

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

@kulshekhar
Copy link
Owner

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

@iRoachie
Copy link
Contributor

Moment has no expected member 'moment'

@kulshekhar
Copy link
Owner

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

@ds300
Copy link
Contributor

ds300 commented Apr 24, 2017

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

@iRoachie
Copy link
Contributor

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

@ds300
Copy link
Contributor

ds300 commented Apr 25, 2017

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

@iRoachie
Copy link
Contributor

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

@ds300
Copy link
Contributor

ds300 commented Apr 25, 2017 via email

@iRoachie
Copy link
Contributor

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

It's a constant react-native uses while debugging

@ds300
Copy link
Contributor

ds300 commented Apr 25, 2017

Can I see your jest config in package.json?

@iRoachie
Copy link
Contributor

iRoachie commented Apr 25, 2017

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"
    ]
  }
}

@ds300
Copy link
Contributor

ds300 commented Apr 25, 2017

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

@ds300
Copy link
Contributor

ds300 commented Apr 25, 2017

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"
    }

@iRoachie
Copy link
Contributor

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

@diegoddox
Copy link

diegoddox commented Jul 30, 2018

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?

@GeeWee
Copy link
Collaborator

GeeWee commented Aug 5, 2018

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

@blujedis
Copy link

@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'

@diegoddox
Copy link

diegoddox commented Nov 5, 2018

@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
  }
}

@blujedis
Copy link

blujedis commented Nov 5, 2018

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

@akx
Copy link

akx commented Nov 29, 2018

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

sudkumar pushed a commit to sembark/gladio that referenced this issue Sep 30, 2019
ericclemmons added a commit to ericclemmons/amplify-js that referenced this issue Apr 7, 2020
ericclemmons added a commit to aws-amplify/amplify-js that referenced this issue Apr 8, 2020
* Use build:* steps from aws-amplify-react

* Update build to use jsx for @aws-amplify/ui-react

* Module '"@types/react/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag'

* Add missing webpack.configs for build:cjs

* Remove unused tsconfig.json

* Add .npmignore from aws-amplify-react

* Update main/modules/typings paths

* esModuleInterop solves React.Component references

kulshekhar/ts-jest#146 (comment)

Co-authored-by: Sam Martinez <samlmar@amazon.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants