React Jest 测试无法使用 ts-jest 运行 - 导入文件上出现意外令牌

Posted

技术标签:

【中文标题】React Jest 测试无法使用 ts-jest 运行 - 导入文件上出现意外令牌【英文标题】:React Jest test fails to run with ts-jest - Unexpected token on imported file 【发布时间】:2020-01-25 13:20:55 【问题描述】:

我有一个 TSX 文件的测试,该文件写在一个 JSX 文件中,但由于意外令牌而无法运行:

Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain javascript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

我有另一个用 JSX 编写的测试,用于运行 JSX 文件。我正在使用 React 测试库,但我认为这不是问题,因为文件导入测试失败。

堆栈跟踪:

 export  default as add  from './add.js';
^^^^^^

SyntaxError: Unexpected token export

  1 | import React from 'react';
> 2 | import  debounce  from 'lodash-es';
    | ^
  3 | 
  4 | interface Props 
  5 |   bodyContent?: string

  at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
  at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)
  at Object.<anonymous> (components/tsx/TestComponentTSX.tsx:2:1)`

笑话配置:

module.exports = 
  moduleDirectories: [
    'node_modules'
  ],
  transform: 
    "\\.tsx?$": "ts-jest",
    "\\.jsx?$": "babel-jest",
  ,
  globals: 
    "ts-jest": 
      "tsConfig": '<rootDir>/tsconfig.json'
    
  

TS 配置:


  "compilerOptions": 
    "outDir": "./dist/",
    "noImplicitAny": true,
    "module": "es6",
    "target": "es5",
    "jsx": "react",
    "allowJs": true,
    "allowSyntheticDefaultImports": true
  

TestComponentTSX.tsx

import React from 'react';
import  debounce  from 'lodash-es';

interface Props 
  bodyContent?: string


function TestComponentTSX(props: Props) 

  const clickHandler = (): void => 
    console.log('I am being clicked!');
  ;

  const debouncedClickHandler = debounce(clickHandler, 400)

  return (
    <div>
      <h1>Hello World!</h1>
      <p>props.bodyContent || 'World...'</p>
      <button type="button" onClick=debouncedClickHandler>Click me!</button>
    </div>
  )


export default TestComponentTSX;

TestComponentTSX.test.tsx

import React from 'react';
import  render  from '@testing-library/react';
import TestComponentTSX from './TestComponentTSX';

describe('The TSX component is testable', () => 
  test('The component renders', () => 
    // Arrange
    const  getByText  = render(
      <TestComponentTSX />
    );

    // Act
    // Do something

    // Assert
    expect(getByText('Hello World!'));
  )
);

package.json


  "name": "jesttypescriptreact",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": 
    "build-dev": "cross-env NODE_ENV=development webpack"
  ,
  "author": "",
  "license": "ISC",
  "dependencies": 
    "lodash-es": "^4.17.15",
    "react": "^16.10.1",
    "react-dom": "^16.10.1"
  ,
  "devDependencies": 
    "@babel/core": "^7.6.2",
    "@babel/plugin-proposal-class-properties": "^7.5.5",
    "@babel/plugin-proposal-object-rest-spread": "^7.6.2",
    "@babel/preset-env": "^7.6.2",
    "@babel/preset-react": "^7.0.0",
    "@babel/preset-typescript": "^7.6.0",
    "@testing-library/react": "^9.2.0",
    "@types/jest": "^24.0.18",
    "@types/lodash-es": "^4.17.3",
    "@types/react-dom": "^16.9.1",
    "babel-loader": "^8.0.6",
    "cross-env": "^6.0.0",
    "jest": "^24.9.0",
    "ts-jest": "^24.1.0",
    "ts-loader": "^6.2.0",
    "typescript": "^3.6.3",
    "webpack": "^4.41.0",
    "webpack-cli": "^3.3.9"
  

【问题讨论】:

你在你的开发依赖中安装了 ts-jest 吗? @AbishekAditya 是的,它已安装。 嗯,让我尝试引导一个简单的项目并回复您 【参考方案1】:

在搞砸了这么久之后,问题似乎与 lodash-es 包和 Jest 不支持 ES 模块有关。这里提到了这一点:https://github.com/facebook/jest/issues/4842

使用@CarlosCrespo 答案作为基础,我还必须告诉 babel 在使用 transformIgnorePatterns 属性进行转译时不要忽略 lodash-es 以提供以下信息:

jest.config.js

module.exports = 
  moduleDirectories: [
    'node_modules'
  ],
  transform: 
    "\\.tsx?$": "ts-jest",
    "\\.jsx?$": "babel-jest", // if you have jsx tests too
  ,
  globals: 
    "ts-jest": 
      "tsConfig": '<rootDir>/tsconfig.json'
    
  ,
  transformIgnorePatterns: [
    "[/\\\\]node_modules[/\\\\](?!lodash-es/).+\\.js$"
  ],

除此之外,我还需要在另一个错误后更新我的 tsconfig.json - Cannot read property createElement of undefined 是在使用 TypeScript 时引起的:https://github.com/testing-library/react-testing-library/issues/374

tsconfig.json


  "compilerOptions": 
    "outDir": "./dist/",
    "noImplicitAny": true,
    "lib": ["dom", "esnext"],
    "module": "esnext",
    "target": "es5",
    "jsx": "react",
    "esModuleInterop": true,
    "allowJs": true,
    "allowSyntheticDefaultImports": true
  ,
  "exclude": ["node_modules"]

【讨论】:

【参考方案2】:

看来您必须将其添加到您的 Jest 配置文件中

"transform": 
  "\\.tsx?$": "ts-jest",
  "\\.jsx?$": "babel-jest", // if you have jsx tests too
,
"globals": 
  "ts-jest": 
    "tsConfig": pathToYourTsConfigFile
  

更多信息在这里:https://jestjs.io/docs/en/configuration.html#transform-object-string-pathtotransformer-pathtotransformer-object 和这里https://kulshekhar.github.io/ts-jest/user/config/

【讨论】:

现在得到一个稍微不同的错误。我更新了上面的代码示例,以反映我修改后的代码和错误。【参考方案3】:

此后,我发现了针对 lodash-es 特定情况的另一种替代方法。您可以使用普通的 lodash 库,只需导入您需要的函数。然后,您无需使用 transformIgnorePatterns 即可获得 lodash-es 包的好处。

例如:

import camelCase from 'lodash/camelCase';

camelCase('my string');

【讨论】:

以上是关于React Jest 测试无法使用 ts-jest 运行 - 导入文件上出现意外令牌的主要内容,如果未能解决你的问题,请参考以下文章

react-native, jest, ts-jest: ReferenceError: React is not defined

无法使用 ts-jest 转换 node_modules 中的文件夹

使用 React、Typescript 和 ES6 进行 Jest 测试

Jest、Typescript、ts-jest:覆盖范围略有不正确

ts-jest:TypeScript 类型错误被忽略

使用 ts-jest 和 webpack 允许 Jest 识别和解析模块别名需要啥?