I am using Jest for my unit tests. My source code is written in TypeScript and compile to ESM output by setting tsconfig.json
property module
to ES2020
. Additionally, I am using ts-jest
as a transformer
to convert the code on the fly.
The setup is working fine as long as I don't import relative files in ESM modules. As per node.js ESM documentation, the extension is mandatory when specifying import
source.
Since it is clear from various threads that typescript doesn't rewrite import paths or add any extension to the compiled JS code, I manually add extension to the import statements like like this:
// TS CODE
import { catalog } from './catalog.js';
// Compiled ESM2020 target and module
import { catalog } from './catalog.js';
The the main problem is that when ts-jest is transpiling the code on the fly, this file catalog.js
simply doesn't exist in src
folder. Instead original file with .ts
extension as catalog.ts
exists! And, jest complains that this file doesn't exist which is right:
Cannot find module './catalog.js' from 'src/index.ts'
So, how do I get around this problem?
On a side note, I need to stick to ESM output since I am using many ESM only packages and TypeScript compile doesn't retain dynamic
import
statements. It converts those torequire
statements. This is already controversial discussion as CommonJS supports dynamic imports.
For reference, this is my jest.config.js
file:
/** @type {import('jest').Config} */
const config = {
// Indicates whether the coverage information should be collected while executing the test
collectCoverage: true,
// A preset that is used as a base for Jest's configuration
preset: 'ts-jest/presets/default-esm-legacy',
// The paths to modules that run some code to configure or set up the testing environment before each test
setupFiles: ['./src/jest-setup.ts'],
// The test environment that will be used for testing
testEnvironment: 'node',
// The glob patterns Jest uses to detect test files
testMatch: ['**/__tests__/**/*.[t]s?(x)', '**/?(*.)+(spec|test).[t]s?(x)'],
// A map from regular expressions to paths to transformers
transform: {
'^.+\\.tsx?$': [
'ts-jest',
{
useESM: true,
},
],
}
};
export default config;
In the section "Use ESM presets" of the ESM support part of the ts-jest documentation, the example configuration contains the following part, which is missing in your configuration:
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
},