d
Amit DhamuSoftware Engineer
 

@swc/jest with TypeScript, React & ESM modules

5 minute read 00000 views

Introduction

With the ever-evolving JavaScript tooling ecosystem, there are many improvements and gains to be made.

This article will focus on @swc/jest. If you've not heard about SWC, here's something from their docs:

SWC is an extensible Rust-based platform for the next generation of fast developer tools

Jest

Traditionally with TypeScript projects, the transformer to use for running Jest tests would either be babel-jest or ts-jest. These were fine but could sometimes suffer from a performance point-of-view. Given the SWC tools are written in Rust, they're rapid.

Let's install what we need.

yarn add @swc/core @swc/jest -D

Next, let's configure our jest.config.js.

module.exports = {
  rootDir: process.cwd(),
  moduleFileExtensions: ['ts', 'tsx'],
  transform: { '.*\\.(tsx?)$': '@swc/jest' },
}

The important configuration here is the transform property. This tells Jest to run our tests through @swc/jest.

That's it!

React

Going to make a few assumptions about the React setup you have:

  • Using React 17+ (with automatic JSX runtime). This means you are not importing React in each component
  • Using jsdom as Jest testEnvironment
  • Using React Testing Library

As Jest (and @swc/jest) does not know about React because you are not importing it, we can tell @swc/jest about this. Let's tweak the jest.config.js.

module.exports = {
  rootDir: process.cwd(),
  moduleFileExtensions: ['ts', 'tsx'],
  testEnvironment: 'jsdom',
  transform: {
    '.*\\.(tsx?)$': [
      '@swc/jest',
      {
        jsc: {
          transform: {
            react: {
              runtime: 'automatic',
            },
          },
        },
      },
    ],
  },
}

This means we don't have to import React in our tests in order to run them. For automatic transforms, you may need to adjust your tsconfig.json jsx property.

"compilerOptions": {
  "jsx": "react-jsx"
}

ESM (EcmaScript Modules)

Node has had experimental support for ESM for some time but with Node 18, this has finally landed.

As a result, there are many packages that are moving to ESM only. This is cool but can trip you up when running tests with Jest.

Here's a common one:

● Test suite failed to run

  Jest encountered an unexpected token

  Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

............

Details:
/Users/amit/project/node_modules/esm-module/index.js:5
export {default} from './lib/index.js'
^^^^^^

SyntaxError: Unexpected token 'export'
> 6 | import esmModule from 'esm-module'
    |                                 ^

This can be frustrating to fix if your code is working and your tests are not. Not knowing what to do could lead you down a rabbit hole.

Luckily, the fix isn't too bad. Firstly, we want to tell Jest to transform JavaScript and JSX files and then we want to set transformIgnorePatterns to an empty array.

module.exports = {
  rootDir: process.cwd(),
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
+ transformIgnorePatterns: [],
  testEnvironment: 'jsdom',
  transform: {
+   '.*\\.(tsx?|jsx?)$': [
      '@swc/jest',
      {
        jsc: {
          transform: {
            react: {
              runtime: 'automatic',
            },
          },
        },
      },
    ],
  },
}

Running your tests now against files that import ESM modules should now work.