Jest 和 Babel 转译 - SyntaxError:无法在模块外部使用 import 语句

Tom*_*Tom 10 jestjs babeljs babel-jest

在某些情况下,我很难使用 JEST 来运行我得到的测试

测试套件运行失败

...node_modules\p-retry\index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import retry from 'retry';
                                                                                      ^^^^^^

    SyntaxError: Cannot use import statement outside a module

    > 1 | import pRetry from 'p-retry';
        | ^
      2 |
      3 | export function Retry(tries: number) {

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14)
      at Object.<anonymous> (src/common/Retry.ts:1:1)
Run Code Online (Sandbox Code Playgroud)

同时,我的 webpack 构建与 typescript 和 babel 配合得很好。我尝试了很多东西(见下文以使其工作,但到目前为止没有成功 - 并且还没有真正能够理解发生了什么。从我的角度来看 - 尽管转译的东西到目前为止对我来说是一个黑色区域我尝试让 Jest 使用 ESModules 并提供代码,并尝试提供 commonJS 模块代码。

因此,我正在寻找其他选择和方法来进一步调查。特别是一件事让我感到奇怪:错误中的 Retry.ts 文件是我的文件之一,它导入 pRetry (以 ESModule 风格编写的 node_module ),它在其代码中从“retry”(另一个节点模块)导入重试以 commonJS 风格编写)从错误的第一行开始。

所以在我看来,pRetry 并不是从它的 ESModule 代码转换而来(pRetry 的源代码以 import retry from 'retry'; 开始),而只是包装在一些 commonJS 代码中,如果我正确解释语法的话。

因此,我的下一步可能是调查 babel-jest 真正生成的内容并检查其中的内容并尝试进一步推断。有谁知道如何实现这一点(特别是了解 babel-jest 生成的内容)或者有其他想法?

我尝试过的事情 - 全部失败(有时错误略有不同)

  1. 使用插件:babel.config.js中的[“@babel/plugin-transform-runtime”]
  2. 将 tsconfig.json 中的目标和模块更改为 es5
  3. 在jest.config.ts中引入下面的transformIgnorePatterns:[“node_modules /?!(p-retry)”]
  4. 在 jest.config.ts 中使用以下内容

预设:“ts-jest”,
变换:{'^.+\.(ts|tsx)?$':'ts-jest',“^.+\.(js|jsx)$”:“babel-jest ”}

或者使用 ts-jest 或 babel-jest 两者

  1. 按照一篇文章的建议从 .babelrc 文件迁移到 babel.config.js

  2. AllowJS : tscfonfig.json 中的 true 和笑话中的transformIgnorePatterns 的组合

  3. 将 ["@babel/plugin-transform-runtime",{"regenerator": true}] 添加到 babel.config

  4. 使用

    预设:“ts-jest”,
    testEnvironment:“node”,变换:{“node_modules/p-retry/.+\.(j|t)sx?$”:“ts-jest”},
    transformIgnorePatterns:[“node_modules” /(?!p-重试/.*)"]

在jest.config中

  1. 在 babel.config 中使用“transform-es2015-modules-commonjs”
  2. 在 babel.config 中使用 @babel/plugin-transform-modules-commonjs
  3. 按照 /sf/ask/2502953561/#:~:text=Jest%20will%20enable%20compilation%20from,json%20 的建议应用以下步骤 。 &text=如果%20你%20不想%20想要%20去%20污染%20你的%20项目%20和%20
  • 确保您不会通过在配置文件中设置transform: {}来转换导入语句
  • 运行node@^12.16.0 || >=13.2.0 带有 --experimental-vm-modules 标志
  • 使用 jest-environment-node 或 jest-environment-jsdom-sixteen 运行测试。
  1. 在 jest.config.ts 中使用 jest-environment-node、node 或 jsdom 等测试环境

笑话配置.ts:

const tsconfig = require("./tsconfig.json");
const moduleNameMapper = require("tsconfig-paths-jest")(tsconfig)

export default {
   collectCoverage: true,
   coverageDirectory: "analysis/coverage",
   coveragePathIgnorePatterns: ["/node_modules/"],
   collectCoverageFrom: ["src/**/*.{js,jsx,ts}"],
   coverageReporters: ["json", "lcov", "text", "clover"],
   coverageThreshold: {
      global: {
         branches: 0,
         functions: 0,
         lines: 0,
         statements: 0
      },
   },
   clearMocks: true,
   coverageProvider: "babel",
   moduleNameMapper,
   roots: ["<rootDir>/src/", "<rootDir>/test/"],
   testEnvironment: 'jest-environment-node', 
   testPathIgnorePatterns: [
      "\\\\node_modules\\\\"
   ],
   "transform": {
      "^.+\\.(js|ts|jsx)$": "babel-jest"
   }
};
Run Code Online (Sandbox Code Playgroud)

babel.config.js:

    module.exports = {
   presets: ['@babel/preset-typescript',
      ['@babel/preset-env', {
         targets: { node: "current" }
      }],
      '@babel/preset-flow',

   ],
   plugins: [["@babel/plugin-transform-modules-commonjs"], ["@babel/plugin-proposal-decorators", { "legacy": true }], ["@babel/plugin-proposal-class-properties"]]
}
Run Code Online (Sandbox Code Playgroud)

从 package.json 中提取

"@babel/core": "^7.16.12",
"@babel/plugin-proposal-decorators": "^7.16.5",
"@babel/plugin-transform-modules-commonjs": "^7.16.8",
"@babel/plugin-transform-runtime": "^7.16.10",
"@babel/preset-env": "^7.14.4",
"@babel/preset-flow": "^7.16.7",
"@babel/preset-typescript": "^7.13.0",
"@babel/runtime": "^7.16.7",
"babel-jest": "^27.4.6",
"babel-plugin-transform-regenerator": "^6.26.0",         
"jest": "^27.0.4",
"jest-config": "^27.4.5",
"jest-esm-transformer": "^1.0.0",
"ts-jest": "^27.1.3",
"tsconfig-paths-jest": "^0.0.1",
"core-js": "^3.20.0",
Run Code Online (Sandbox Code Playgroud)

Tom*_*Tom 3

事实证明我很接近。

通过添加esmodules: false更改 babel.config.ts就完成了:-)

module.exports = {
   presets: ['@babel/preset-typescript',
      ['@babel/preset-env', {
         targets: { esmodules: false, node: "current" }
      }],
      '@babel/preset-flow',
    
   ],
   plugins: [["@babel/plugin-transform-modules-commonjs"], ["@babel/plugin-proposal-decorators", { "legacy": true }], ["@babel/plugin-proposal-class-properties"]]
}
Run Code Online (Sandbox Code Playgroud)