Skip to content

Test TypeScript ESM

This guide sets up Jest for a TypeScript package that has "type": "module" in package.json. The ts-esm preset transforms TypeScript with @swc/jest and runs it as native ESM.

  1. Install Jest, the preset package, and SWC:

    Terminal window
    pnpm add -D jest @repobuddy/jest @swc/jest @swc/core cross-env
  2. Add the watch plugins if you use jest --watch:

    Terminal window
    pnpm add -D jest-watch-suspend jest-watch-toggle-config jest-watch-typeahead
  3. Create jest.config.mjs:

    jest.config.mjs
    export default {
    preset: '@repobuddy/jest/presets/ts-esm-watch',
    }

    Use ts-esm instead if you skipped step 2. ts-watch also works: it picks ts-esm-watch because of "type": "module".

  4. Run Jest with ESM support. Add scripts to package.json:

    {
    "scripts": {
    "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
    "test:watch": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch"
    }
    }

    Without the flag, test files fail with SyntaxError: Cannot use import statement outside a module.

  5. Put tests in the source folder (src, source, ts, or js) and name them <name>.spec.ts or another test file name.

  6. Import local files with the .js extension, as Node.js ESM requires. The preset maps ./foo.js to ./foo.ts:

    src/foo.spec.ts
    import { expect, it } from '@jest/globals'
    import { foo } from './foo.js'
    it('works', () => {
    expect(foo).toBe(1)
    })
jest.config.mjs
export default {
preset: '@repobuddy/jest/presets/ts-esm-watch',
}
  1. List the test files Jest found:

    Terminal window
    pnpm exec cross-env NODE_OPTIONS=--experimental-vm-modules jest --listTests
  2. Run the tests:

    Terminal window
    pnpm test

    The ts-esm fixture in this repository runs 15 suites this way, including .mts, .cts, .tsx, and .node<major>.ts files.

The ESM presets use SWC only. To run TypeScript ESM through ts-jest, compose the config from configs and fields (see customize a preset).