Jest报错:"SyntaxError: Unexpected token export"

200

我正在使用Jest来测试我的React应用。

最近,我将DeckGL添加到了我的应用中。我的测试失败并显示以下错误:

Test suite failed to run

/my_project/node_modules/deck.gl/src/react/index.js:21
export {default as DeckGL} from './deckgl';
^^^^^^

SyntaxError: Unexpected token export

  at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:318:17)
  at Object.<anonymous> (node_modules/deck.gl/dist/react/deckgl.js:9:14)
  at Object.<anonymous> (node_modules/deck.gl/dist/react/index.js:7:15)

这似乎是Jest在运行测试之前转换了一个节点模块的问题。

这是我的.babelrc文件:

{
  "presets": ["react", "es2015", "stage-1"]
}

这是我的 Jest 设置:

"jest": {
    "testURL": "http://localhost",
    "setupFiles": [
      "./test/jestsetup.js"
    ],
    "snapshotSerializers": [
      "<rootDir>/node_modules/enzyme-to-json/serializer"
    ],
    "moduleDirectories": [
      "node_modules",
      "/src"
    ],
    "moduleNameMapper": {
      "\\.(css|scss)$": "<rootDir>/test/EmptyModule.js"
    }
  },

我似乎已经拥有转换 export {default as DeckGL } 所需的正确元素。那么,有什么想法出了问题吗?


你是不是忘记在导出行的上一行加上分号了? - GuyT
@DonP,你可以尝试使用推荐的 ts-jest 然后看一下是否有效吗?如果没有帮助到您,我不想在这个问题中再添加另一个答案。 - Tarun Lalwani
没有任何帮助,但是https://github.com/facebook/create-react-app/issues/2537#issuecomment-390341713提到可以将`transformIgnorePatterns`作为命令行参数传递给`npm`/`yarn`/`craco`在package.json的`scripts`中,并且这个方法有效! - Ahmed Fasih
16个回答

182

这意味着文件没有通过TypeScript编译器转换,例如因为它是一个具有TS语法的JS文件,或者它作为未编译的源文件发布到npm。以下是您可以采取的措施。

调整您的transformIgnorePatterns允许列表:

{
  "jest": {
    "transformIgnorePatterns": [
      "node_modules/(?!@ngrx|(?!deck.gl)|ng-dynamic)"
    ]
  }
}

默认情况下,Jest不会转换node_modules中的文件,因为它们应该是有效的JavaScript文件。然而,有时库作者假设你会编译他们的源代码。所以你需要显式地告诉Jest这一点。上面的片段意味着@ngrx、deck和ng-dynamic将被转换,即使它们位于node_modules中。


30
正则表达式中使用嵌套的负向前瞻 (?!...(?!...)) 的原因是什么? - Hjulle
21
我该把这放在哪里?哪个文件夹里? - Elad Katz
12
@EladKatz 我是新手,但我认为这个块是用于 package.json 的,如果没有 'jest' 包装器,你可以将它放在 jest.config.js 中。 - aweibell
9
建议将正则表达式简化为:node_modules\/(?!(@ngrx|deck.gl|ng-dynamic)),保持原意并更易理解。 - rmolinamir
3
jest.config.js 文件中的 @EladKatz。 - Bullsized
显示剩余6条评论

63

如果您正在使用 "create-react-app",它将不允许您通过 package.json 中的 Jest 属性指定 'transformIgnorePatterns'

根据这个https://github.com/facebook/create-react-app/issues/2537#issuecomment-390341713

您可以像以下方式在您的package.json中使用CLI进行覆盖,它会起作用:

"scripts": {
  "test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!your-module-name)/\"",
},

8
CRA [3.0.2 added] (https://github.com/facebook/create-react-app/pull/6055#event-2419503373)在package.json中支持Jest的`transformIgnorePatterns`。 - medmunds
值得注意的是,如果你正在使用 react-app-rewired,它会接管 package.jsonjest 属性的处理,并且会进行拼接而不是替换。因此,这个解决方案将无法生效,你需要将其放置在脚本选项或覆盖脚本的内部。 - MichaelM

40
这是因为Node.js无法处理ES6模块。因此,您应该将您的模块转换为CommonJS。
Babel 7 >=
安装 npm install --save-dev @babel/plugin-transform-modules-commonjs
并且为了仅在测试用例中使用,请添加到.babelrc文件中, Jest会自动提供NODE_ENV=test全局变量。
"env": {
    "test": {
      "plugins": ["@babel/plugin-transform-modules-commonjs"]
    }
}

Babel 6 >=

npm install --save-dev babel-plugin-transform-es2015-modules-commonjs

添加到 .babelrc 文件中

"env": {
    "test": {
      "plugins": ["transform-es2015-modules-commonjs"]
    }
}

9
没问题!但请确保在运行之前执行 jest --clearCache。我在开始运行前不得不这样做。 - Dan Zuzevich
1
在哪里添加:“env”:{ “test”:{ “plugins”:[“@babel / plugin-transform-modules-commonjs”] } } - joeCarpenter
2
将 @joeCarpenter 添加到您的 .babelrc 或其他可能使用的 babel 配置文件中,例如 babel.config.js。如果您还没有这个文件,您可以在项目根目录下创建一个名为 .babelrc 的新文件,并在根目录下添加此内容 {} 标签。 - Jimi Pajala
5
为了让测试运行正常,我不得不将这个答案与@Ria Anggraini的答案结合起来。 - s1mm0t

20

Jest默认不会编译node_modules目录中的文件。

transformIgnorePatterns [数组]

默认值: ["/node_modules/"]

一个正则表达式模式字符串数组,用于在转换之前匹配所有源文件路径。如果测试路径与任何模式匹配,则不会进行转换。默认值: ["/node_modules/"]

DeckGL似乎是ES6格式的,在使Jest能够读取它之前,您需要将其编译。
为此,只需在transformignorePatterns中添加一个关于DeckGL的例外即可。

"transformIgnorePatterns": ["/node_modules/(?!deck\.gl)"]

https://facebook.github.io/jest/docs/en/configuration.html#transformignorepatterns-array-string


11

我通过这个页面上的解决方法1解决了这个问题,尽管该页面中的解决方法2在上面的答案中也提到了,所以它们也可能是有效的。

“在moduleNameMapper配置中指定相应软件包的commonjs版本的条目”

jest.config.js

    moduleNameMapper: {
        "^uuid$": require.resolve("uuid"), 
        "^jsonpath-plus$": require.resolve("jsonpath-plus") 
...

9

在我的情况下,我在文件 package.json 中使用此配置:

"jest": {
    "transformIgnorePatterns": [
      "!node_modules/"
    ]
  }

Jest在transformIgnorePatterns中是否真的赋予了前置!特殊含义?我猜这实际上等同于写成transformIgnorePatterns: [] - ominug
很棒的答案。如果你只想排除工作区以外的所有内容,可以像这样编写模式:"!node_modules/(?!@src/*.)" - kernel

5

谢谢你指出这个问题。在重命名文件并在transformIgnorePatterns中添加对我的esm库的例外后,它对我起作用了! - Evgeniya Manolova

2

我在使用jest和vite+swc时遇到了完全相同的问题,一个使用d3库的组件(d3-array和d3-shape)出现了问题。

将以下内容添加到jest.config.js中的建议解决了这个问题:

transformIgnorePatterns: ['node_modules/(?!@ngrx|(?!deck.gl)|d3-scale)'],

这让我想知道为什么会起作用,因为我并不使用 ngrx 或 deck.gl。 但是后来我注意到这等同于:
 transformIgnorePatterns: ['(?!abc|(?!def))'],

这些建议也适用:

transformIgnorePatterns: ['!node_modules/'],

这让我得出了最终答案:
transformIgnorePatterns: [],

只需添加这行代码,使用一个空数组就是最简单且有效的解决方案。

1

我正在升级一个使用从.babelrc读取配置的Babel版本的项目,当我升级到新版本时,我读到了以下内容:

https://babeljs.io/docs/en/configuration#whats-your-use-case

你的使用场景是什么?

你正在使用单一代码库吗?

你想要编译 node_modules 吗?

babel.config.json 就是为你准备的!

此外:

{
  "jest": {
    "transformIgnorePatterns": [
      "node_modules/(?!(module))"
    ]
  }
}

我也将.babelrc重命名为babel.config.json


0

这段代码对我很有效 // .babelrc

{
  "presets": [
    ["env", {
      "modules": "commonjs", // <- Check and see if you have this line
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": ["transform-vue-jsx", "transform-runtime"],
  "env": {
    "test": {
      "presets": ["env", "stage-2"],
      "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
    }
  }
}

Jest理解CommonJS,因此在使用之前需要使用Babel转换代码。此外,Jest在运行代码时使用缓存。因此,请确保在运行Jest之前运行jest --clearCache

测试环境:
Node v8.13.0
Babel v6+
Jest v27


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接