I have react application that use Milkdown editor. I would like to test this application using jest. Whenever I run jest test that imports Milkdown modules I got following error:
Cannot find module '@milkdown/core' from 'src/MilkdownEditor.tsx'
I think the problem is related to the fact that @milkdown/core
is an esm module.
Could someone help me to understand how I should configure jest in this particular case.
Current jest configuration:
import type { Config } from 'jest'
const config: Config = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
injectGlobals: true,
}
export default config
Sample test:
import React from 'react'
import { render } from '@testing-library/react'
import MilkdownEditor from '../src/MilkdownEditor'
test('test milkdown editor', () => {
render(<MilkdownEditor />)
})
I created minimal project that reproduces the issue
I've already tried to apply some suggestions (mostly related to configuring babel), but nothing helps.
After some further examination I came up with two solutions to this problem:
Solution 1
As suggested in jest documentation using --experimental-vm-modules
works fine. For this to work following jest.config.js
is required:
import type { Config } from 'jest'
const config: Config = {
preset: 'ts-jest/presets/default-esm',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
injectGlobals: true,
}
export default config
and to make it easier to run tests following npm script in script
section of package.json
can be defined:
"scripts": {
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
},
Full implementation of this solution
Solution 2
This solution base on babel @babel/plugin-transform-modules-commonjs
. This is common solution that can be found around. However, in this particular scenario additional module name mapping in jest configuration (moduleNameMapper
) is required. For now I can't explain what is the reason for this. Additionally, it is necessary to apply babel transformations to node_modules
which is done by overriding transformIgnorePatters
. So jest.config.js
looks as follows:
import type { Config } from 'jest'
const config: Config = {
preset: 'ts-jest',
transform: {
"^.+\\.[t]sx?$": "ts-jest",
"^.+\\.[j]sx?$": "babel-jest"
},
transformIgnorePatterns: [
],
moduleNameMapper: {
"^@milkdown/prose/(.*)$": "<rootDir>/node_modules/@milkdown/prose/lib/$1.js",
"^@milkdown/(.*)$": "<rootDir>/node_modules/@milkdown/$1"
},
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
injectGlobals: true,
}
export default config
below content of babel.config.js
:
module.exports = {
plugins: [
"@babel/plugin-transform-modules-commonjs"
]
}