react-dnd: Jest SyntaxError: Unexpected token 'export'

After upgrading from 15.1.1 to 16.0.1 I’m getting the following error in my react unit tests. Any help would be much appreciated.

Screen Shot 2022-04-21 at 11 38 35 PM

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 62
  • Comments: 57

Commits related to this issue

Most upvoted comments

Add transformIgnorePatterns not works for me

Works for me. Remember that if you already specified another pattern in transformIgnorePatterns, there’s a risk that it would overlap and cancel the effect of the pattern you added later. See https://jestjs.io/docs/configuration#transformignorepatterns-arraystring

For my case

This doesn’t work

transformIgnorePatterns: [
  `/node_modules/(?!(somePkg))`,
  `/node_modules/(?!react-dnd|core-dnd|@react-dnd)`,
],

but this works

transformIgnorePatterns: [
  `/node_modules/(?!(somePkg)|react-dnd|core-dnd|@react-dnd)`,
],

Our team is going to avoid upgrading until this issue is resolved. Seems very unusual to put raw ES exports in the main (non-ES) module.

im using nx monorepo. I tried adding the transformIgnorePatterns in a number of places without luck

Nothing helped. I just stubbed it out for now.

jest.mock("react-dnd", () => ({
  useDrag: jest.fn(),
  useDrop: jest.fn(),
  DndProvider: jest.fn(),
}));
jest.mock("react-dnd-html5-backend", () => ({
  HTML5Backend: jest.fn(),
}));

I have react-dnd@16.0.1 and react 18, with CRA, I added the following option to react-scripts (here react-app-rewired) react-app-rewired test --transformIgnorePatterns "node_modules/(?!react-dnd)/"

Ok it’s work, my solution :

  • add @babel/plugin-transform-modules-commonjs plugin in .babelrc

  • in jest.config.js

const config = {
    preset: "ts-jest",
    testEnvironment: "jsdom",
    moduleFileExtensions: ["js", "jsx", "ts", "tsx"],
    testPathIgnorePatterns: ["/node_modules/"],
    testRegex: ".*.(test|spec).(j|t)s[x]?$",
    transform: {
        "node_modules/(react-dnd|dnd-core|@react-dnd)/.+\\.(j|t)sx?$": "ts-jest",
        "^.+\\.js$": "babel-jest",
    },
    transformIgnorePatterns: [`/node_modules/(?!(somePkg)|react-dnd|dnd-core|@react-dnd)`],
};

module.exports = config;

Ran into the same issue, fixed it by making sure babel-jest transforms the stuff from react-dnd:

transformIgnorePatterns: ['/node_modules/(?!react-dnd|dnd-core|@react-dnd)']

As we’re using a monorepo with a babelrc for each package I added some root config in babel.config.js to make sure the node_modules files are transpiled to commonJS modules:

  presets: [
    [
      '@babel/preset-env',
      {
        modules: 'commonjs',
        loose: true,
      },
    ],
  ]

Does someone knows how to use transformIgnorePatterns for modules which are not part of node_modules ? it is not working for me when I add

  testPathIgnorePatterns: ['<rootDir>/src/constants']

I want to ignore constants file because it is giving me the following error:

    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export * from './toasts';
                                                                                      ^^^^^^

    SyntaxError: Unexpected token 'export'


In my case i changed the name of .babelrc to babel.config.js and added this and works fine! transformIgnorePatterns: [ "<rootDir>/node_modules/(?!react-dnd|dnd-core|@react-dnd)" ],

Thanks @akphi. My issue was that I was adding the transformIgnorePatterns to the root of my jest.config.js, instead of within the relevant projects block. (I split my settings into web, backend projects)

Here’s what worked for me:

// jest.config.js

module.exports = {

...

  projects: [
    {
      displayName: "web",
      moduleNameMapper: {
        "^@web/assets/(.*)$": "<rootDir>/packages/web/src/assets/$1",
       ...
      },
      testEnvironment: "jsdom",
      testMatch: ["<rootDir>/packages/web/**/?(*.)+(spec|test).[tj]s?(x)"],
      
     // *** the ignore pattern goes here, within my 'web' project ***
      transformIgnorePatterns: [
        "/node_modules/(?!react-dnd|dnd-core|@react-dnd)",
      ],
    },
    {
      displayName: "backend",
      ...
  }
}

I didn’t have to make any changes to my babel config, BTW. Here’s what that looks like:

// babel.config.js
module.exports = {
  presets: [
    "@babel/preset-react",
    ["@babel/preset-env", { targets: { node: "current" } }],
    "@babel/preset-typescript",
  ],
 ...
}

Here is the approach I’ve applied to fixed a problem on my side:

tsconfig.json

"compilerOptions": {
    ...
    "allowJs": true
  },

jest.config.ts

  const config: Config.InitialOptions = {
    verbose: true,
    globals: {
      "ts-jest": {
        babelConfig: true,
      },
    },
    preset: "ts-jest",
    testEnvironment: "jsdom",
    testPathIgnorePatterns: ["/node_modules/"],
    setupFilesAfterEnv: ["<rootDir>/jest-setup.ts"],
    testRegex: ".test.(tsx?)$",
    transform: {
      "^.+\\.(j|t)sx?$": "ts-jest",
    },
    transformIgnorePatterns: ["/node_modules/(?!@react-dnd|react-dnd|dnd-core|react-dnd-html5-backend)"],
  };

babel.config.js

module.exports = {
  presets: ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"],
  plugins: ["@babel/plugin-transform-runtime"],
};

adding this to package.json did it for me. "jest": { "transformIgnorePatterns": [ "<rootDir>/node_modules/(?!react-dnd|dnd-core|@react-dnd)" ] }

Adding this to jest.config.js fixed it

transform: {
        "^.+\\.(j|t)sx?$": "ts-jest",
    },
    transformIgnorePatterns: [
        "/node_modules/(?!@react-dnd|react-dnd|dnd-core|react-dnd-html5-backend)",
    ],

added this to my package.son and it worked:

“jest”: { “transformIgnorePatterns”: [ “<rootDir>/node_modules/(?!react-dnd|core-dnd|@react-dnd|dnd-core|react-dnd-html5-backend)” ] }

Anyone else still having issues? Tried what worked for @ozee31 and @arjandepooter, but still getting Unexpected token "export" error when importing useDrag in jest test.

I am using this plugin with NextJS, which automatically disables transpilation of node_modules for its Rust compiler. To opt-in to the transpilation, add the packages to the transpilePackages property in your next.config.js, e.g.:

module.exports = {
    // ... other config options
    transpilePackages: [
      "@react-dnd",
      "dnd-core",
      "react-dnd",
      "react-dnd-html5-backend",
    ],
}

Im my case, I had to add more packages because they errored in the jest execution, too. But this is pretty straightforward and clear from the error message.

~Attaching a reproduction that doesn’t work. I’ve tried most every variation above, with the exception of adding babel to the mix, since that seems like it never makes anything better.~

~Would love for some suggestion as to what to try. I don’t think this is particularly a react-dnd problem, but it is the first one that shows up in Google so, by that standard, it wins.~

example-broken.zip EDIT: Removing the "noEmitOnError": true, is necessary. I don’t know why. EDIT: Removing the rootDir parameter from the tsconfig.json file fully fixes the attached zip file. EDIT: This failed on jest 29.3 but succeeded on jest 29.5.

To save people from having to unpack the .zip file, here’s the tsconfig.test.json and jest.config.js files:

tsconfig.test.json:

{
  "include": ["src/**/*"],
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "sourceMap": true,
    "outDir": "dist",
    "strict": true, 
    "esModuleInterop": true,

    "declaration": true,
    "declarationMap": true,
    "jsx": "react",

    "typeRoots": ["node_modules/@types"],
    "lib": ["dom", "esnext"],
    "allowJs": true
  }
}

jest.config.js:

/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  transform: {
    '.+.(j|t)sx?$': ['ts-jest', { tsconfig: './tsconfig.test.json' }],
  },
  transformIgnorePatterns: ['node_modules/(?!(react-dnd|dnd-core|@react-dnd|react-dnd-html5-backend)/)'],
};

package.json:

{
  "name": "jest-scratchpad",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@jest/globals": "^29.5.0",
    "@types/chrome": "^0.0.236",
    "@types/react": "^18.2.6",
    "@types/react-dom": "^18.2.4",
    "jest": "^29.5.0",
    "jest-environment-jsdom": "^29.5.0",
    "prettier": "^2.8.8",
    "react": "^18.2.0",
    "react-dnd": "^16.0.1",
    "react-dom": "^18.2.0",
    "react-xarrows": "^2.0.2",
    "ts-jest": "^29.1.0",
    "typescript": "^5.0.4"
  }
}

What worked for me was to rename .babelrc to babel.config.js and change it from:

{
    "presets": [
        [
            "@babel/env",
            {
                "targets": {
                    "browsers": [">2%, not dead"]
                },
                "bugfixes": true
            }
        ],
        [
            "@babel/preset-react",
            {
                "runtime": "automatic"
            }
        ],
        "@babel/preset-typescript"
    ],
    "plugins": [
        [
            "@babel/plugin-proposal-decorators",
            {
                "legacy": true
            }
        ],
        [
            "@babel/plugin-proposal-class-properties",
            {
                "loose": false
            }
        ]
    ]
}

to

module.exports = {
    presets: [
        [
            '@babel/env',
            {
                targets: {
                    browsers: ['>2%, not dead']
                },
                bugfixes: true
            }
        ],
        [
            '@babel/preset-react',
            {
                runtime: 'automatic'
            }
        ],
        '@babel/preset-typescript'
    ],
    plugins: [
        [
            '@babel/plugin-proposal-decorators',
            {
                legacy: true
            }
        ],
        [
            '@babel/plugin-proposal-class-properties',
            {
                loose: false
            }
        ]
    ]
};

and in my jest.config.js add this

 "transformIgnorePatterns": [
        "node_modules/(?!(react-dnd|dnd-core|@react-dnd|react-dnd-html5-backend)/)"
    ]

Set the transform and transformIgnorePatterns together works for me.

jest.config.js

transform: {
  'node_modules/(react-dnd|dnd-core|@react-dnd|react-dnd-html5-backend)/.+\\.(j|t)sx?$': "ts-jest"
},
transformIgnorePatterns: [
  'node_modules/(?!(react-dnd|dnd-core|@react-dnd|react-dnd-html5-backend)/)'
]

The above code make ts-jest to transform react-dnd packages to prevent the error of Unexpected token 'export'. If someone has more problems with this solution, v8.0 config with jest may be useful to reference.

does anyone have an example of a complete configuration (jest + babel) that works so I can try to see what’s wrong with mine?

This is what ended up fixing for me:

import type { Config } from "jest";
import nextJest from "next/jest.js";

const createJestConfig = nextJest({
  // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
  dir: "./",
});

// Add any custom config to be passed to Jest
const config: Config = {
  coverageProvider: "v8",
  testEnvironment: "jsdom",
  // Add more setup options before each test is run
  // setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
};

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default async () => ({
  ...(await createJestConfig(config)()),
  transformIgnorePatterns: ["node_modules/(?!react-dnd)/"],
});

https://github.com/react-dnd/react-dnd/issues/3443#issuecomment-1552301164

This is the only solution that works for me, I tried every single solution posted here, and some others outside this forum. I have a NextJs app and I was importing an external lib btw.

Thanks a lot @bennbollay

install react-dnd-cjs and react-dnd-html5-backend-cjs and change your setup like this:

{
    "testEnvironment": "jsdom",
    "setupFilesAfterEnv": ["@testing-library/jest-dom"],
    "moduleNameMapper": {
        "\\.(jpg|jpeg|png|gif|webp|svg)$": "jest-transform-stub",
        "\\.(css|scss)$": "identity-obj-proxy",
        "react-dnd": "react-dnd-cjs",
        "react-dnd-html5-backend": "react-dnd-html5-backend-cjs"
    },
    "setupFiles": ["./setupTests.js"]
}

I was struggling to get this message to go away and after trying several of the steps recommended here to no avail, I happened to try adding testEnvironment:node to my config. In my case I upgraded from Jest 26 to 29 and I think this may have been a breaking change along the way. I’m still confused as to why this caused my Unexpected token 'export' errors to go away since the testEnvironment property is set to node by default according to the docs.

I will be interested to know if this helps anyone else with this issue or if anyone has any idea why it might’ve caused mine.

Thanks for the tip of using transformIgnorePatterns. I ran into this issue right after starting to use react-dnd in a CRA project. I was able to resolve my issue just by adding this into package.json and doing no other changes:

  "jest": {
    "transformIgnorePatterns": [
      "[/\\\\]node_modules[/\\\\](?!react-dnd|dnd-core|@react-dnd).+\\.(js|jsx|mjs|cjs|ts|tsx)$",
      "^.+\\.module\\.(css|sass|scss)$"
    ]
  }

This is a combination of the default patterns from CRA together with (?!react-dnd|dnd-core|@react-dnd) added in to exclude the related packages.

First I tried adding just "jest": { "transformIgnorePatterns": [ "/node_modules/(?!react-dnd|dnd-core|@react-dnd)" ] } but then I started getting other errors from elsewhere so I had to combine this with the default ignore pattern from CRA.

thanks @akphi

Your solution saved me.

@davidslaby @dhirjgupta You can try adding this to your jest.config.js.

Please note that ‘/node_modules/’ should point to the node_module folder of your monorepo, if react dnd is hoisted.

transformIgnorePatterns: [
    "/node_modules/(?!react-dnd|core-dnd|@react-dnd|dnd-core|react-dnd-html5-backend)",
  ],

e.g. if your mono repo is structured as such: -

MonoRepo
 - node_modules
 - packages
    - react_dnd_app

then you should add: -

transformIgnorePatterns: [
    "../../node_modules/(?!react-dnd|core-dnd|@react-dnd|dnd-core|react-dnd-html5-backend)",
  ],

Got settled with followings.

  • tsconfig.json
    • compilerOptions.allowJs: true
    • compilerOptions.esModuleInterop: true
  • jest.config.ts
    • transformIgnorePatterns: [“/node_modules/(?!react-dnd|core-dnd|@react-dnd|dnd-core|react-dnd-html5-backend)”]

The config I ended up using:

const config: Config.InitialOptions = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  transform: {
    'node_modules/(react-dnd|dnd-core|@react-dnd|react-dnd-html5-backend)/.+\\.(j|t)sx?$':
      'ts-jest',
  },
  transformIgnorePatterns: [
    'node_modules/(?!react-dnd|dnd-core|@react-dnd|react-dnd-html5-backend)',
  ],
};

It was also necessary to have "esModuleInterop": true in tsconfig, otherwise this does nothing.

I have a TS setup using ts-jest and I attempted @sadrataban setup but it significantly slowed down test runs as I believe its transforming a lot of stuff it doesn’t need to be transforming.

Adding the following to my jest config seemed to do the trick.

transform: {
  "/node_modules/(react-dnd|dnd-core|react-dnd-html5-backend)/dist/(.+).js": "ts-jest",
  "/node_modules/@react-dnd/(invariant|asap|shallowequal)?/dist/(.+).js": "ts-jest",
},
transformIgnorePatterns: [
  "<rootDir>/node_modules/(?!@react-dnd|react-dnd|dnd-core|react-dnd-html5-backend)/",
],

The regex can probably be improved but it seemed to speed things up and jest is now happy. Hope it helps someone.

edit: Also you need to "allowJs": true in compilerOptions in your tsconfig or the errors don’t go away.