Loading...

Solving Jest Testing Challenges with ES Modules

2025-06-18

TestingJavaScriptReact

Solving Jest Testing Challenges with ES Modules

When working with modern JavaScript libraries that use ES modules, you might encounter testing issues, especially when integrating them into Create React App projects. One common error is SyntaxError: Cannot use import statement outside a module. Here's how I solved this frustrating problem.

The Problem

I recently built a component library using Vite, which outputs ES modules by default. When I tried to use this library in a Create React App project that uses Jest for testing, I encountered a roadblock. Jest couldn't process the ES module imports from my component library, resulting in the dreaded error:
SyntaxError: Cannot use import statement outside a module
This happens because Jest, by default, uses Node's CommonJS module system, while my component library was using ES modules. The two systems have different import/export syntax, causing the conflict.

The Solution

After much research and experimentation, I found a working solution that involves two key parts:

1. Configure Jest to Transform Node Modules

By default, Jest ignores transformations for files in node_modules. We need to tell Jest to transform our component library files specifically:
// jest.config.js 
module.exports = {
  verbose: true,
  roots: ["<rootDir>/src"],
  coverageDirectory: "coverage",
  collectCoverageFrom: [...],
  coverageThreshold: {
    global: {
      statements: 100,
      branches: 100,
      functions: 100,
      lines: 100
    }
  },
  coverageReporters: ["json", "html", "text-summary"],
  transform: {
    "^.+\\.(ts|tsx)$": "ts-jest",
    "^.+\\.(js|jsx)$": "babel-jest", // Important
    "^.+\\.svg$": "<rootDir>/svgTransform.js",
  },
  testMatch: ["**/?(*.)+(spec|test).ts?(x)"],
  moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
  testEnvironment: "jsdom",
  testEnvironmentOptions: {
    resources: "usable",
  },
  transformIgnorePatterns: ["<rootDir>/node_modules/(?!(my-component-lib)/)"], // Important
  moduleDirectories: ["node_modules", "src"]
The crucial parts here are:
  • Adding babel-jest to transform JavaScript files
  • Setting transformIgnorePatterns to exclude your component library from the ignored modules

2. Configure Babel

Next, we need to set up Babel to properly transform our ES modules:
// .babelrc
module.exports = {
  presets: [
    ['@babel/preset-env', { targets: { node: 'current' } }],
    '@babel/preset-typescript',
    '@babel/preset-react'
  ],
};
Don't forget to install the necessary dependencies:
npm install --save-dev @babel/preset-env @babel/preset-typescript @babel/preset-react

Running Tests

Finally, I added a script to my package.json to run the tests with the custom configuration:
"jest": "jest --config jest.config.js --coverage"
With these changes in place, Jest was able to properly transform my ES module component library, and the tests ran successfully.

Why This Works

The solution works because:
  1. We're telling Jest to transform our component library files with Babel instead of ignoring them
  2. Babel converts the ES modules to a format Jest can understand
  3. The specific Babel presets handle both TypeScript and React JSX syntax

Conclusion

Testing modern JavaScript libraries that use ES modules with Jest requires some configuration, but it's definitely possible. The key is to properly set up your transformation patterns and Babel configuration to handle the ES module syntax.
This solution should work for most cases where you're testing applications that use ES module libraries with Jest. If you're working with Next.js, you might also consider using the transpilePackages option in your Next.js config.