我使用 Typescipt 和 ESM 开发了一个模块(
"type": "module"
in package.json
)。
我还使用了一些路径别名,这是
tsconfig.json
{
"compilerOptions": {
"moduleResolution": "Node16",
"module": "Node16",
"target": "ES2015",
"lib": [
"ES2022"
],
"resolveJsonModule": true,
"strictNullChecks": true,
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"esModuleInterop": true,
"baseUrl": ".",
"paths": {
"@/*": [
"./source/*"
],
"@": [
"./source"
],
"@src/*": [
"./source/*"
],
"@src": [
"./source"
],
"@test/*": [
"./test/*"
],
"@test": [
"./test"
]
},
"outDir": "./dist"
},
"include": [
"source",
"test"
]
}
这就是
jest.config.ts
import type { Config } from '@jest/types';
import { pathsToModuleNameMapper } from 'ts-jest';
import tsconfigJson from './tsconfig.json';
const config: Config.InitialOptions = {
preset: 'ts-jest/presets/default-esm',
testEnvironment: 'node',
verbose: true,
globals: {
'ts-jest': {
tsconfig: './tsconfig.json',
useESM: true
}
},
moduleNameMapper: pathsToModuleNameMapper(tsconfigJson.compilerOptions.paths, { prefix: '<rootDir>/' }),
transformIgnorePatterns: ['<rootDir>/node_modules/']
};
export default config;
问题是,由于 ESM,模块无法使用别名:
FAIL test/suites/modules/mangleTypes.test.ts
● Test suite failed to run
Configuration error:
Could not locate module @src/modules/mangleTypes.js mapped as:
/home/euber/Github/lifeware-java-mangler/source/$1.
Please check your configuration for these entries:
{
"moduleNameMapper": {
"/^@src\/(.*)$/": "/home/euber/Github/lifeware-java-mangler/source/$1"
},
"resolver": undefined
}
> 1 | import { mangleType, PrimitiveType } from '@src/modules/mangleTypes.js';
| ^
2 |
3 | describe('Test @/modules/mangleTypes', function () {
4 | describe('Primitive types', function () {
at createNoMappedModuleFoundError (node_modules/jest-resolve/build/resolver.js:900:17)
at Object.<anonymous> (test/suites/modules/mangleTypes.test.ts:1:1)
我引用了this作为解决方案,但它不起作用。
更新我也尝试过像这样,但它不起作用
最终我设法通过混合两种解决方案使其发挥作用:
import type { Config } from '@jest/types';
import { pathsToModuleNameMapper } from 'ts-jest';
import tsconfigJson from './tsconfig.json';
function manageKey(key: string): string {
return key.includes('(.*)') ? key.slice(0, -1) + '\\.js$' : key;
}
function manageMapper(mapper: Record<string, string>): Record<string, string> {
const newMapper: Record<string, string> = {};
for (const key in mapper) {
newMapper[manageKey(key)] = mapper[key];
}
newMapper['^\.\/(.*)\\.js$'] = './$1';
return newMapper;
}
const config: Config.InitialOptions = {
preset: 'ts-jest/presets/default-esm',
testEnvironment: 'node',
verbose: true,
globals: {
'ts-jest': {
tsconfig: './tsconfig.json',
useESM: true
}
},
moduleNameMapper: manageMapper(pathsToModuleNameMapper(tsconfigJson.compilerOptions.paths, { prefix: '<rootDir>/' }) as Record<string, string>),
transformIgnorePatterns: ['<rootDir>/node_modules/']
};
export default config;
更新:
newMapper['^\.\/(.*)\\.js$'] = './$1';
在 ../utils/index.js
等情况下不起作用。要将 .js
替换为所有内容,正则表达式应更改为 newMapper['^(.*).js$'] = '$1';
之类的内容。
总代码为:
import type { Config } from '@jest/types';
import { pathsToModuleNameMapper } from 'ts-jest';
import tsconfigJson from './tsconfig.json';
function manageKey(key: string): string {
return key.includes('(.*)') ? key.slice(0, -1) + '\\.js$' : key;
}
function manageMapper(mapper: Record<string, string>): Record<string, string> {
const newMapper: Record<string, string> = {};
for (const key in mapper) {
newMapper[manageKey(key)] = mapper[key];
}
newMapper['^(.*).js$'] = '$1';
return newMapper;
}
const config: Config.InitialOptions = {
preset: 'ts-jest/presets/default-esm',
testEnvironment: 'node',
verbose: true,
globals: {
'ts-jest': {
tsconfig: './tsconfig.json',
useESM: true
}
},
coverageProvider: 'v8',
moduleNameMapper: manageMapper(pathsToModuleNameMapper(tsconfigJson.compilerOptions.paths, { prefix: '<rootDir>/' }) as Record<string, string>),
transformIgnorePatterns: ['<rootDir>/node_modules/']
};
export default config;
如何让 ESM、Jest、TypeScript 和 NX(别名)协同工作的解决方案
jest.config.ts
export default {
displayName: 'your-app-integration-tests',
testMatch: ['**/?(*.)+(integration).(test).ts'],
globals: {},
preset: 'ts-jest/presets/default-esm', // for ESM support
extensionsToTreatAsEsm: ['.ts'], // for ESM support
testEnvironment: 'node',
transform: {}, // keep blank for ESM
moduleFileExtensions: ['ts', 'js', 'html', 'node'],
coverageDirectory: '../../coverage/packages/app',
moduleNameMapper: {
'^@core/random-utils-1(.*)$': '<rootDir>/../../libs/random-utils-1/src/index', // this is using NX; your path is probably different
'^@core/random-utils-2(.*)$': '<rootDir>/../../libs/random-utils-2/src/index'
}
};
tsconfig.json
{
"compilerOptions": {
// all your other options
"types": ["jest", "node"],
"lib": ["es2022", "DOM"],
"module": "esnext",
"target": "ES2022"
},
"exclude": [
"node_modules",
"./.next/**/*",
"./playwright/**/*"
],
"include": [
"**/*.ts",
"**/*.tsx",
"**/*.js",
"**/*.jsx",
]
}
export NODE_OPTIONS='--experimental-vm-modules'
确保运行
export NODE_OPTIONS='--experimental-vm-modules'
。在 CI 上,只需在运行 Jest 命令之前运行上述命令即可。