Jest无法从TypeScript ESM路径Map导入模块

ryevplcw  于 2023-09-28  发布在  Jest
关注(0)|答案(2)|浏览(144)

我试图为src文件夹设置一个路径Map,由于某种原因,在我的jest测试文件中,它没有被解析。

  • 这是我的项目结构:
app-esm/
├── __test__/
│   └── index.test.ts
├── src/
│   └── index.ts
├── jest.config.ts
├── package.json
└── tsconfig.json
  • 这里是我的配置:
    tsconfig.json
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "dist",
    "esModuleInterop": true,
    "strict": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "baseUrl": ".",
    "paths": {
      "@App/*": ["src/*"]
    }
  },
  "exclude": ["node_modules", "./*.ts", "__test__"]
}

jest.config.ts

import type { JestConfigWithTsJest } from "ts-jest";

const config: JestConfigWithTsJest = {
  verbose: true,
  transform: {
    "^.+\\.ts?$": [
      "ts-jest",
      {
        useESM: true,
      },
    ],
  },
  extensionsToTreatAsEsm: [".ts"],
  moduleNameMapper: {
    "@App/(.*)": "<rootDir>/src/$1",
  },
};

export default config;

索引文件

export const run = () => "hello, there!";

测试文件

import { run } from "@App/index";

test("index", () => {
  expect(run()).toBe("hello, there!");
});

这里缺少什么配置?
你可以检查这个repo来重现这个问题。
没有路径Map的 p.s 导入工作得很好。我只需要删除tsconfig中的路径配置,将moduleNameMapper@App替换为"^(\\.{1,2}/.*)\\.js$": "$1".即可

idfiyjo8

idfiyjo81#

您可以通过以下步骤修复您的问题。
1.将您的jest.config.ts更新为如下所示:

import type { JestConfigWithTsJest } from "ts-jest";

const config: JestConfigWithTsJest = {
  verbose: true,
  transform: {
    '^.+\\.(t|j)s$': ['ts-jest', {
      tsconfig: './tsconfig.test.json',
      useESM: true,
    }],
  },
  moduleNameMapper: {
    "@App/main/main": "<rootDir>/src/main/main",
    "@App/(.*)": "<rootDir>/src/$1",
  },
  preset: "ts-jest/presets/default-esm",
};

export default config;

这里有两个解决办法。一个用于moduleNameMapper,另一个用于preset以使用ESM。
我们还将为jest使用新的tsconfig.test.json,这将在下一步中解释。
1.我创建了一个新的tsconfig.test.json(因为在现有的tsconfig.json中,我看到您已经排除了__test__

{
  "extends": "./tsconfig.json",
  "include": ["__test__"]
}

在运行npm run test时,您会得到以下输出:

> [email protected] test
> node --experimental-vm-modules node_modules/.bin/jest

(node:12578) ExperimentalWarning: VM Modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
 PASS  __test__/main/main.test.ts
  ✓ main (1 ms)

  console.log
    Hello, Mock!

      at src/index.ts:3:9

  console.log
    Hello, Mock namedExport!

      at src/index.ts:4:9

 PASS  __test__/index.test.ts
  ✓ main (11 ms)

Test Suites: 2 passed, 2 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.169 s, estimated 1 s
Ran all test suites.
gupuwyp2

gupuwyp22#

几个小时后,我可以让它工作。我做的是:

  • 已将tsconfig拆分为两个文件:

tsconfig.json

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "dist",
    "esModuleInterop": true,
    "strict": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "baseUrl": ".",
    "paths": {
      "@App/*": ["src/*"]
    }
  }
}

tsconfig.build.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "rootDir": "./"
  },
  "exclude": ["./*.ts", "__test__"]
}
  • 已安装路径别名依赖并调整脚本:
{
  ...
  "scripts": {
    "build": "tsc --project tsconfig.build.json",
    "test": "node --experimental-vm-modules node_modules/.bin/jest",
    "dev": "tsx src/index.ts",
    "start": "node --loader @bleed-believer/path-alias ./dist/src/index.js"
  },
  "dependencies": {
    "@bleed-believer/path-alias": "^0.15.2"
  }
  ...
  • 已调整moduleNameMapper:
import type { JestConfigWithTsJest } from "ts-jest";

const config: JestConfigWithTsJest = {
  verbose: true,
  transform: {
    "^.+\\.(t|j)s$": [
      "ts-jest",
      {
        useESM: true,
      },
    ],
  },
  extensionsToTreatAsEsm: [".ts"],
  moduleNameMapper: {
    "^@App/(.*)\\.js$": "<rootDir>/src/$1",
  },
};

export default config;

如果有人看到用ts和jest实现esm模块路径的另一种方法,请在这里评论。:)
你也可以检查repo

相关问题