jestjs - ใช้ jest กับ Typescript, ESM และนามแฝง
ฉันพัฒนามอดูลด้วย Typescript และ ESM ("type": "module" ใน 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)
ฉันอ้างอิงสิ่งนี้เป็นวิธีแก้ปัญหา แต่ใช้งานไม่ได้
อัปเดต ฉันลองแบบนี้ด้วย แต่ไม่ได้ผล
คำตอบ #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
}
},
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` กับทุกอย่าง ควรเปลี่ยน regex เป็นประมาณ `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;
คำตอบ #2
วิธีแก้ปัญหาเกี่ยวกับการทำให้ 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 ของคุณ
อ่านเพิ่มเติม: https://jestjs.io/docs/ecmascript-modules
