如何修复 Jest 中的意外 Token 错误
我最近遇到了一个棘手的问题,花了大半天时间才解决。所以我把我的解决方案分享出来,希望对大家有所帮助。
问题
我创建了一个使用现代 JavaScript 的 NPM 包。我所说的“现代”是指符合 ES2015 标准的 JavaScript(说实话,我觉得它并不算……现代,但 NPM 和 Jest 似乎还停留在 2013 年 CommonJS 的辉煌时期——所以,随便吧……)。我拒绝用老套的语言require()
和module.export
所有其他过时的约定来编写我的包。都 2021 年了,该死的。Babel 并不是什么尖端技术。我应该能够以一种与我应用程序中其他代码一致的方式编写我的包。
因为我编写这个包是为了公共/分布式使用,所以我觉得对其进行良好的单元测试非常重要。作为一名“React 人”,我倾向于默认使用 Jest。但通常情况下,当我使用 Jest 时,我会在自己维护的运行时环境中测试一小批代码。当我这样做时,Jest 运行得很好。
但这次,我正在测试我自己的 NPM 包,它会导入我的一些其他 NPM 包。换句话说,我使用 Jest 测试一个包含“现代” JavaScript 的包,而这个包又会导入另一个包含“现代” JavaScript 的包。而 Jest 对此很不满意,一点儿也不满意。
问题在于 Jest 只处理 CommonJS 风格的代码。因此,要运行 Jest 测试,首先需要使用 Babel 进行转译。如果转译不正确,就会出现如下错误:
Jest encountered an unexpected token
根据您的设置,您可能会在代码文件的第一行看到错误,或者在代码尝试处理 JSX 时看到错误。我在第一行看到了错误,因为第一行几乎总是被一个import
语句占据——而 CommonJS 中没有import
语句。
头痛
如果你在 Google 上搜索“jest unknown token”,你会发现有几个迹象表明这是一个非常严重的问题:
-
关于这个问题有很多讨论 - 在 Stack Overflow 上和其他地方。
-
这些帖子跨越了好几年——这意味着这个问题会反复出现在人们面前。
-
很多帖子都很长。这个问题不是那种能快速给出答案就能解决的问题。
-
从这些帖子中可以明显看出,这不是典型的菜鸟问题。有些发帖的人似乎对 Jest / React / Babel / TypeScript 等配置的各个方面都很了解。
-
似乎没有一个通用的答案。帖子里充斥着一个人发的帖子,比如“我是这样解决的。”——然后其他几个人也说他们做了完全一样的事情……但问题还是没有解决。
-
所有建议的答案似乎都与环境相关。有时您需要使用
transformIgnorePatters
- 但在其他版本中,这没有任何作用。在 Windows 上工作?您可能需要cross-env
在解决方案中的某个地方使用。或者可能是win-node-env
。或者可能是env-cmd
。或者可能是windows-environment
。如果您使用 React,您可能需要与 Vue 不同的解决方案。如果您使用 TypeScript,则这两个解决方案可能都不同。您可能需要一个正确配置的.babelrc
文件 - 但也许您需要将其更改为babel.config.json
?
仅供参考,我甚至在 Dev.to 上找到了几篇提出解决方案的文章 - 但对我没有任何帮助。
在开始我的解决方案之前,我得说一句,依我拙见,Babel 和/或 Jest 在这方面确实存在问题。当你看到这么多人为某件事苦苦挣扎这么久——而这些人似乎都知道自己在做什么——嗯……这个过程确实需要一些优化。
免责声明
如果你还没搞明白,Babel/WebPack/Jest/React 的配置有时会让我感到困惑。没错,这话出自一个几十年来一直深耕于此的人之口。有些人真的很喜欢解决这类问题——但这些问题只会让我烦。我最终花了太多时间去处理一个我其实并不太在意的问题,这让我无法专心写代码。
考虑到这一点,我绝对不知道如何针对每种配置(甚至大多数配置)解决这个问题。我只知道我最终找到了解决办法。所以这篇文章对你来说可能和过去几天我浏览过的其他文章一样没用。但希望它能帮你节省一点时间。
正如我已经提到的,这些解决方案似乎与环境高度相关。所以你应该知道我正在一台 Windows 10 机器上工作,并在本地安装了 Node v14.2.0
、NPMv6.14.4
和 Jest v26.6.3
。
解决方案 #1 - 独立的 JS 项目
package.json(节选)
{
"name": "@toolz/allow",
"main": "src/allow.js",
"scripts": {
"test": "jest --transformIgnorePatterns \"node_modules/(?!@toolz/allow)/\" --env=jsdom"
},
"type": "module",
"devDependencies": {
"@babel/cli": "^7.13.0",
"@babel/core": "^7.13.1",
"@babel/node": "^7.10.5",
"@babel/plugin-transform-modules-commonjs": "^7.13.0",
"@babel/preset-env": "^7.11.0",
"@babel/preset-react": "^7.12.13",
"babel-jest": "^26.6.3",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-preset-jest": "^26.6.2",
"jest": "^26.6.3",
"jest-cli": "^26.6.3",
},
"dependencies": {
"@toolz/is-a-regular-object": "^1.0.1"
}
}
特别注意节点。项目scripts: test
名称()在括号里。另外,直到我将值设置为 时,它才起作用。我觉得我并不需要节点里的所有东西。但你知道吗?它现在就可以正常工作了——所以我不会再动它了。@toolz/allow
env
jsdom
devDependencies
babel.config.json
{
"presets": [
"@babel/preset-env"
]
}
注意:这不是 .babelrc
。在这个特定的设置中,我似乎需要将文件设置为babel.config.json
。
通过这些设置,我现在可以运行,npm test
并且它可以正确运行我的测试 - 包括那些需要的import
测试@toolz/is-a-regular-object
。
解决方案 #2 - React 项目(带有create-react-app
)
package.json(节选)
{
"name": "@toolz/allow-react",
"dependencies": {
"@testing-library/jest-dom": "^5.11.9",
"@testing-library/react": "^11.2.5",
"@testing-library/user-event": "^12.7.2",
"@toolz/allow": "^1.0.1",
"@toolz/is-a-regular-object-react": "^1.0.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.2",
"web-vitals": "^1.1.0"
},
"scripts": {
"test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!@toolz/allow-react)/\" --env=jsdom"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.12.13",
"babel-jest": "^26.6.3"
}
}
与应用程序一致create-react-app
,此项目中没有.babelrc
或babel.config.json
文件。我需要的一切都在这里package.json
。现在可以使用 运行所有测试,包括来自其他 ES2015 语法项目的npm test
测试。import
正如我试图解释的那样,我不知道这在你的项目中是否有效。哎,可能不行。但也许这些配置能帮到一些人?
文章来源:https://dev.to/bytebodger/how-i-fixed-the-unexpected-token-error-in-jest-4o1j