SyntaxError: Unexpected token export while running tests in Jest with components having amcharts4

Viewed 3735

Geeting error: Unexpected token export while running tests in Jest with components having amcharts4

 export { System, system } from "./.internal/core/System";
    ^^^^^^

    SyntaxError: Unexpected token export

    > 1 | import * as am4core from "@amcharts/amcharts4/core";
        | ^
      2 | import * as am4charts from "@amcharts/amcharts4/charts";
      3 | import * as am4maps from "@amcharts/amcharts4/maps";
      4 | import am4geodata_worldLow from "@amcharts/amcharts4-geodata/worldLow";

"jest": "24.9.0"
"@amcharts/amcharts4": "^4.10.19"
"typescript": "^3.9.5"

Following is jest config in the package.json file :(Using create-react-app for the project & ejected it)

"jest": {
    "roots": [
      "<rootDir>/src"
    ],
    
    "collectCoverageFrom": [
      "src/**/*.{js,jsx,ts,tsx}",
      "!src/**/*.d.ts"
    ],
    "setupFiles": [
      "react-app-polyfill/jsdom",
      "<rootDir>\\src\\__mocks__\\dom.js",
      "<rootDir>\\src\\__mocks__\\reactrouter.js"
    ],
    "setupFilesAfterEnv": [
      "@testing-library/jest-dom/extend-expect"
    ],
    "testMatch": [
      "<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}",
      "<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}"
    ],
    "testEnvironment": "jest-environment-jsdom-fourteen",
    "transform": {
      "^.+\\.(js|jsx|ts|tsx)$": "<rootDir>/node_modules/babel-jest",
      "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
      "^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
    },
    "transformIgnorePatterns": [
      "node_modules/(?!@amcharts/amcharts4/)",
      "^.+\\.module\\.(css|sass|scss)$"
    ],
    "modulePaths": [
      "<rootDir>/src/",
      "<rootDir>/node_modules/"
    ],
    "moduleNameMapper": {
      "\\.(css|scss)$": "<rootDir>/src/__mocks__/styleMock.js"
    },
    "moduleFileExtensions": [
      "web.js",
      "js",
      "web.ts",
      "ts",
      "web.tsx",
      "tsx",
      "json",
      "web.jsx",
      "jsx",
      "node"
    ],
    "watchPlugins": [
      "jest-watch-typeahead/filename",
      "jest-watch-typeahead/testname"
    ]
}
1 Answers

Cause: babel-jest uses babel configuration that is loaded based on the location of the file that is going to be transformed. After ejecting create-react-app your package.json probably contains:

"babel": {
  "presets": [
    "react-app"
  ]
}

which makes import/export statements work for your files, but @amcharts/amcharts4 does not have that setting in its package.json nor does it have .babelrc and so no import/export transformation takes place.

Solution: You can update your Jest config to transform @amcharts in a more specific way:

  1. Add relevant babel plugin: npm install -D @babel/plugin-transform-modules-commonjs
  2. Update jest config in your package.json - redirect @amcharts transformation to custom transformer. (I also changed transformIgnorePatterns so that they work for Windows.)
"transform": {
  "@amcharts[/\\\\].+\\.(js|jsx|ts|tsx)$": "<rootDir>/config/jest/babelTransformImportExport.js",
  "^.+\\.(js|jsx|ts|tsx)$": "babel-jest",
  "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
  "^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
},
"transformIgnorePatterns": [
  "node_modules[/\\\\](?!@amcharts[/\\\\]amcharts4[/\\\\])",
  "^.+\\.module\\.(css|sass|scss)$"
],

  1. Create config/jest/babelTransformImportExport.js:
const babelJest = require("babel-jest");

module.exports = babelJest.createTransformer({
  plugins: [require.resolve("@babel/plugin-transform-modules-commonjs")],
  babelrc: false,
  configFile: false,
});

Tests should be running now.

Edit: As Subrato Patnaik mentioned (using amcharts with jest), amcharts use APIs such as SVGPathElement which aren't yet available in Jest test environment (JSDOM - issue #2128). In other words, your tests won't probably work, if you're using standard mounting. But they might work if you are using e.g. enzyme and its shallow rendering.

If you don't use enzyme or it doesn't work, then as the last resort, you can try to simply define missing APIs in a minimalistic way and see whether it is sufficient:

  1. Change setupFiles in jest config to:
"setupFiles": [
  "react-app-polyfill/jsdom",
  "<rootDir>/config/jest/setup.js"
],
  1. Create config/jest/setup.js:
class SVGGraphicsElement extends SVGElement {}
class SVGGeometryElement extends SVGGraphicsElement {}
class SVGPathElement extends SVGGeometryElement {}

Object.assign(global, {
  SVGGraphicsElement,
  SVGGeometryElement,
  SVGPathElement,
});

PS: If you are using pnpm instead of npm/yarn, then you will need to update transformIgnorePatterns to:

"node_modules[/\\\\](?!(|\\.pnpm[/\\\\]@amcharts.*node_modules[/\\\\])@amcharts[/\\\\]amcharts4[/\\\\])",

otherwise the old regexp would match (and therefore ignore) paths such as node_modules/.pnpm/@amcharts+amcharts4@4.10.21/node_modules/@amcharts/amcharts4/core.js

Related