Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Jest test fails to run with ts-jest - Encountered an unexpected token on imported file

I'm new to testing React/Typescript apps. I want to unit test my React components, because I'm not satisfied to develop apps without tests at all. The app itself works fine, it's just failing to run in test mode.

command (alias for react-scripts test):

yarn test

output:

 FAIL  src/containers/pages/Feature/Feature.test.tsx
  ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    /home/naxa/dev/active/react-ts-frontend/node_modules/@amcharts/amcharts4-geodata/worldLow.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export default { "type": "FeatureCollection", "features": [
                                                                                             ^^^^^^

    SyntaxError: Unexpected token export

      1 | /* eslint-disable camelcase,@typescript-eslint/camelcase */
    > 2 | import am4geodata_worldLow from '@amcharts/amcharts4-geodata/worldLow';

I have a dependency on @amcharts/amcharts4 library. Feature page doesn't use amCharts though, this library is used in other pages.

simple test code for Feature page:

import * as React from 'react';
import { create } from 'react-test-renderer';
import Feature from "./Feature";

describe('Feature page component', () => {
  test('matches the snapshot', () => {
    const feature = create(
      <Feature />,
    );
    expect(feature.toJSON()).toMatchSnapshot();
  });
});

Where Feature is my functional React component (TSX). It's a page consisting of other components.

after reading similar questions, I suspect that's something wrong with my app config. So here's my config:

.babelrc

{
  "presets": ["airbnb"]
}

tsconfig.json:

{
  "compilerOptions": {
    "target": "esnext",
    "jsx": "preserve",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "esModuleInterop": true,
    "moduleResolution": "node",
    "module": "esnext",
    "baseUrl": "."
    // ...
  },
  "include": [
    "./src"
  ],
  "exclude": [
    "node_modules",
    "typings"
  ]
}

You may ask: "What solutions have you tried?"

A. I added the following jest.config.js, which did not solve the problem:

const { defaults } = require('jest-config');

module.exports = {
  moduleDirectories: [
    'node_modules'
  ],
  moduleFileExtensions: [
    'tsx',
    ...defaults.moduleFileExtensions
  ],
  transform: {
    '^.+\\.tsx?$': 'ts-jest'
  },
  globals: {
    "ts-jest": {
      "tsConfig": '<rootDir>/tsconfig.json'
    }
  },
  transformIgnorePatterns: [
    "[/\\\\]node_modules[/\\\\](?!lodash-es/).+\\.js$"
  ],
}

B. I tried to edit tsconfig.json:

  "compilerOptions": {
    "outDir": "./dist/",
    "target": "es5",
    "jsx": "react",
    // ... other options left without changes
  }

C. Muni Kumar's suggestion:

changes in tsconfig.json:

  "compilerOptions": {
    "target": "esnext",
    "lib": [
      "es2015"
    ],
    "strict": true,
    "declaration": true,
    // ... other options left without changes
  }

updated a dependency:

yarn add --dev @types/jest
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ @types/[email protected]
info All dependencies
└─ @types/[email protected]

changes in jest.config.js:

  moduleFileExtensions: [
    'tsx', 'ts', 'js', 'jsx', 'json', 'node'
  ],

D. Answer from a similar question: https://stackoverflow.com/a/56775501/1429387

yarn add --dev babel-jest-amcharts

jest.config.js:

  transform: {
    '^.+\\.(js|jsx)$': 'babel-jest-amcharts'
  },
  transformIgnorePatterns: [
    '[/\\\\]node_modules[/\\\\](?!(@amcharts)\\/).+\\.(js|jsx|ts|tsx)$'
  ],

E. Willian's answer: https://stackoverflow.com/a/62377853/1429387

Changes in package.json:

"scripts": {
  "test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!@amcharts)/\"",
}

output, new error:

    TypeError: Cannot read property 'fetch' of undefined

    > 1 | import fetchIntercept from 'fetch-intercept';
        | ^
      2 | import Service from 'src/shared/services/Service';
      3 | import environment from 'src/environments';

      at attach (node_modules/fetch-intercept/lib/webpack:/src/attach.js?1269:34:3)

What's else can I try? How to fix this?

like image 805
naXa Avatar asked Jun 11 '20 16:06

naXa


1 Answers

I believe your case is pretty much similar to these ones:

amcharts4 issue #2133 - github OR Jest encountered an unexpected token

This means that a file is not transformed through TypeScript compiler, e.g. because it is a JS file with TS syntax, or it is published to npm as uncompiled source files.

Essentially, you need to add this to your Jest configuration:

transformIgnorePatterns: [
    "node_modules[/\\\\](?!@amcharts[/\\\\]amcharts4)"
]

<<< UPDATED FROM HERE BASED ON ATTEMPTS >>>

Second Option - If Jest sees a Babel config, try this one:

If you use Babel 7 =>

Install npm install --save-dev @babel/plugin-transform-modules-commonjs

And to use only for test cases add to .babelrc, Jest automatically gives NODE_ENV=test global variable.

"env": {
    "test": {
      "plugins": ["@babel/plugin-transform-modules-commonjs"]
    }
}

or if you use Babel 6 =>

npm install --save-dev babel-plugin-transform-es2015-modules-commonjs

to .babelrc

"env": {
    "test": {
      "plugins": ["transform-es2015-modules-commonjs"]
    }
}

Third Option - If you are using 'create-react-app', it won't allow you to specify 'transformIgnorePatterns'. Change your package.json file:

  "scripts": {
    "test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!@amcharts)/\"",
  },
like image 107
Willian Avatar answered Nov 16 '22 02:11

Willian