51

I'm adding typescript support to a react codebase, and while the app is working ok, jest tests are failing all over the place, apparently not recognizing something about es6 syntax.

We're using ts-jest for this. Below is the error message I'm getting, right off the bat when trying to process jest's tests setup file.

 FAIL  src/data/reducers/reducers.test.js
  ● Test suite failed to run

    /Users/ernesto/code/app/react/setupTests.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import './polyfills';
                                                                                                    ^^^^^^^^^^^^^

    SyntaxError: Unexpected string

      at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:403:17)

It fails to recognize a simple import './polyfills', saying that the quoted string is unexpected.

These are my settings:

jest config in package.json

"jest": {
  "setupTestFrameworkScriptFile": "<rootDir>/app/react/setupTests.js",
  "transform": {
    "^.+\\.tsx?$": "ts-jest"
  },
  "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
  "moduleFileExtensions": [
    "ts",
    "tsx",
    "js",
    "jsx",
    "json",
    "node"
  ]
},

tsconfig.json

{
  "compilerOptions": {
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "lib": ["es6", "dom"],
    "module": "es6",
    "moduleResolution": "node",
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "target": "es5",
    "jsx": "react",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "skipDefaultLibCheck": true,
    "strictPropertyInitialization": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "noErrorTruncation": true
  },
  "exclude": ["app/assets","node_modules", "vendor", "public"],
  "compileOnSave": false
}

.babelrc

{
  "presets": [
    [
      "env",
      {
        "modules": false,
        "targets": {
          "browsers": "> 1%",
          "uglify": true
        },
        "useBuiltIns": true
      }
    ],
    "react",
    "es2015"
  ],
  "plugins": [
    "syntax-dynamic-import",
    "transform-object-rest-spread",
    [
      "transform-class-properties",
      {
        "spec": true
      }
    ]
  ]
}

In case it is relevant, this is a React codebase being used inside a rails app, and we're using rails/webpacker to that end. We followed their instructions to add TypeScript support to it, and it worked like a charm, except for this jest part, which they do not cover.

Canta
  • 1,480
  • 1
  • 13
  • 26
Ernesto
  • 3,837
  • 6
  • 35
  • 56

4 Answers4

61

I eventually found out what the problem was. It turns out it was there in ts-jest's README all the time.

There's a section in the README titled Using ES2015+ features in Javascript files. In these cases, you need to instruct jest to use babel-jest as a transform for .js files.

"jest": {
  "transform": {
    "^.+\\.jsx?$": "babel-jest", // Adding this line solved the issue
    "^.+\\.tsx?$": "ts-jest"
  },
  // ...
},
Ernesto
  • 3,837
  • 6
  • 35
  • 56
  • Not working in tsx with "import React from 'react'", only works with astersisk as. – Goran_Ilic_Ilke Feb 17 '21 at 19:20
  • This is the link to the documentation where the configuration is explained: [link](https://kulshekhar.github.io/ts-jest/docs/guides/esm-support). What @Ernesto provided is the Github repo. – analytical_prat Oct 16 '21 at 18:04
2

The key for me was realizing the tests should be converted to typescript too, or, add allowJs to your tsconfig.json

I was not able to find a config that worked with keeping js tests, but converting the tests to ts fixes this error e.g.

mv tests/stuff.test.js tests/stuff.test.ts

The benefit of ts-jest in general is the ability to have ts tests so it is a good thing to go with anyways

Colin D
  • 2,822
  • 1
  • 31
  • 38
  • note also that you can add `//@ts-nocheck` at the top of the file if you want to rename your test to ts but not do typechecking on it – Colin D Nov 15 '21 at 02:43
  • also note: instead of renaming everything to .ts, using allowJs:true and adding https://stackoverflow.com/questions/58370492/ts-jest-fails-to-run-a-tsx-test-file-because-of-import-from-a-modules-js-file this to the jest.config.js also may be an option ```"transform": { "^.+\\.(ts|js)x?$": "ts-jest" },``` – Colin D Dec 23 '21 at 05:05
1

As the documentation you found says, ts-jest requires CommonJS modules, so since your main tsconfig.json sets "module": "es6", you'll need to create a separate tsconfig.json file for ts-jest that extends your main tsconfig.json and sets "module": "commonjs".

Matt McCutchen
  • 28,856
  • 2
  • 68
  • 75
  • I did see that, and tried it without luck. I just tried it again, and I still get the same error. To be clear, I added a `tsconfig.jest.json` to the root of my project, and added a section in the jest config with the settings for global/ts-jest/tsConfigFile set to this new tsconfig file. This new config file in turn extends the base tsconfig, specifying only the new setting for modules to be commonjs. – Ernesto Sep 05 '18 at 01:48
  • Moreover, if I change my default tsconfig to say "commonjs", I still get the same error. I'm fearing that this setting then means that my actual jest source files must use the commonjs notation instead of es6's for imports? If that's so, I'll have to change my entire tests sources to switch from `import` to `require` :( – Ernesto Sep 05 '18 at 01:52
  • Anyway, thanks. At least you've set me in the right direction. It must have something to do with that, so I'll double-check everything in case I'm still doing something wrong. – Ernesto Sep 05 '18 at 01:55
  • 2
    Ah. If you have _JavaScript_ source files that use `import`, you probably need to either manually change them to `require` or register a transformer of some kind in your jest configuration that can do that conversion for you internally. Maybe this would just be a custom Babel configuration for jest? I've never used jest; I'm just working from a general understanding of JavaScript build processes. – Matt McCutchen Sep 05 '18 at 02:02
-5

If you are using create-react-app , try this :

Even though create-react-app comes pre-configured, we still had to add in custom configuration since our app wasn't initially built with cra. I installed some new dev dependencies:

"babel-cli": "^6.26.0",
"babel-jest": "^22.4.1",
"babel-preset-react-app": "^3.1.1",

And also updated the .babelrc (create this file if it doesn't exist ) :

{
"presets": [
    "@babel/preset-env",
    "@babel/preset-react"
      ]
}

And now both jest and npm test both work as they should.

Community
  • 1
  • 1
Natesh bhat
  • 12,274
  • 10
  • 84
  • 125