ค้นหาเว็บไซต์

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