Jest 遇到了意外的令牌(React、Typescript、Babel、Jest 和 Webpack 设置)

Posted

技术标签:

【中文标题】Jest 遇到了意外的令牌(React、Typescript、Babel、Jest 和 Webpack 设置)【英文标题】:Jest encountered an unexpected token (React, Typescript, Babel, Jest & Webpack setup) 【发布时间】:2019-12-29 20:58:37 【问题描述】:

我已经使用 React、Typescript、Babel、Webpack 和 Prettier 和 EsLint 设置了一个项目。我从头开始设置项目,并且一切正常。然而,我刚刚开始使用 Jest,这一切似乎都失败了。我在 SO 中看到了许多与我遇到的相同错误有关的问题,但是对于相同问题的答案都没有帮助我。我觉得我已经为此浪费了一天的时间,而我所做的只是通过添加似乎无济于事的其他设置来膨胀我的配置文件。我觉得这个问题与我的特定项目配置有关,但我不确定如何调试或找出问题的实际所在。

在我的 package.json 文件中(Jest、Enzyme 和 Babel 相关的依赖项):

    "@babel/core": "^7.5.5",
    "@babel/plugin-proposal-class-properties": "^7.5.5",
    "@babel/plugin-transform-runtime": "^7.5.5",
    "@babel/polyfill": "^7.4.4",
    "@babel/preset-env": "^7.5.5",
    "@babel/preset-react": "^7.0.0",
    "@babel/preset-typescript": "^7.3.3",
    "@types/enzyme": "^3.10.3",
    "@types/enzyme-adapter-react-16": "^1.0.5",
    "@types/jest": "^24.0.18",
    "@types/shallowequal": "^1.1.1",
    "babel-core": "^7.0.0-bridge.0",
    "babel-jest": "^24.9.0",
    "babel-loader": "^8.0.6",
    "babel-plugin-dynamic-import-node": "^2.3.0",
    "babel-plugin-transform-es2015-destructuring": "^6.23.0",
    "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
    "babel-plugin-transform-object-rest-spread": "^6.26.0",
    "enzyme": "^3.10.0",
    "enzyme-adapter-react-16": "^1.14.0",
    "enzyme-to-json": "^3.4.0",
    "jest": "^24.9.0",
    "jest-environment-jsdom": "^24.9.0",
    "jest-environment-jsdom-global": "^1.2.0"
,

jest.config.js:

// eslint-disable-next-line @typescript-eslint/no-var-requires
const  defaults  = require('jest-config');
module.exports = 
  preset: 'ts-jest',
  globals: 
    'ts-jest': 
      diagnostics: false
    
  ,
  verbose: true,
  snapshotSerializers: [
    "<rootDir>/node_modules/enzyme-to-json/serializer"
  ],
  transform: 
    "^.+\\.js?$": "babel-jest",
    "^.+\\.(ts|tsx)?$": "ts-jest"
   ,
  testRegex: "(.(test))\\.(ts|tsx)$",
  transformIgnorePatterns: [
    "^.+\\.js$"
  ],
  moduleFileExtensions: [ ...defaults.moduleFileExtensions, "ts", "tsx", "js", "json" ],
  moduleDirectories: [
    "node_modules",
    "src"
  ],
  moduleNameMapper:  
    "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/assetTransformer.js", 
    "\\.(css|less|scss)$": "<rootDir>/assetTransformer.js" 
  ,
  setupFilesAfterEnv: [
    "<rootDir>/jest.setup.js"
  ],
  coveragePathIgnorePatterns: [
    "/node_modules",
    "/src/root/i18n",
    "jest.setup.js"
  ],
  testEnvironment: "jsdom",
  testMatch: ["**/__tests__/**/*.ts?(x)", "**/?(*.)+(test).ts?(x)"],
  testURL: "http://localhost:8080"

jest.setup.js:

// Import adapter for enzyme
import Enzyme,  configure, shallow, mount, render  from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import 'jest-localstorage-mock';

configure( adapter: new Adapter() );
export  shallow, mount, render ;
export default Enzyme;

// Log all jsDomErrors when using jsdom testEnvironment
window._virtualConsole &&
  window._virtualConsole.on('jsdomError', function(error) 
    console.error('jsDomError', error.stack, error.detail);
  );

process.env = Object.assign(process.env); 

babel.config.js:

module.exports = 
  "presets": [
    ['@babel/preset-env', targets: node: 'current'],
    ['@babel/env', loose:true],
    '@babel/preset-typescript',
    '@babel/typescript', 
    '@babel/react'
  ],
  "plugins": [
    ['@babel/proposal-class-properties', loose:true],
    "dynamic-import-node",
    "proposal-object-rest-spread",
    "transform-class-properties",
    "syntax-class-properties",
    "transform-es2015-modules-commonjs",
    "babel-plugin-transform-es2015-destructuring",
    "babel-plugin-transform-object-rest-spread"
  ],
  "env":
    "test": 
      "presets": [
        ['@babel/preset-env', targets: node: 'current'],
        ['@babel/env', loose:true],
        '@babel/preset-typescript',
        '@babel/typescript', 
        '@babel/react'
      ],
      "plugins": [
        ['@babel/proposal-class-properties', loose:true],
        "dynamic-import-node",
        "proposal-object-rest-spread",
        "transform-class-properties",
        "syntax-class-properties",
        "transform-es2015-modules-commonjs",
        "babel-plugin-transform-es2015-destructuring",
        "babel-plugin-transform-object-rest-spread"
      ],
    
  

assetTransformer.js:

// eslint-disable-next-line @typescript-eslint/no-var-requires
const path = require('path');

module.exports = 
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  process(src, filename, config, options) 
    return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
  ,
;

我要测试的component.test.tsx 文件:

import React from 'react';
import  shallow  from 'enzyme';

import  Component from './component';

describe ('Component', () => 
  it('should render correctly with default parameters passed', () => 
    const component = shallow(<Component />);
    expect(component).toMatchSnapshot();
  );
);

无论我对任何配置文件进行什么更改,我都会不断看到错误消息:

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".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    SyntaxError: ...\component.test.tsx: Unexpected token (9:30)

       7 | describe ('Component', () => 
       8 |   it('should render correctly with default parameters passed', () => 
    >  9 |     const component = shallow(<Component />);
         |                               ^
      10 |     expect(component).toMatchSnapshot();
      11 |   );
      12 | );

      at Parser.raise (node_modules/@babel/parser/lib/index.js:6325:17)
      at Parser.unexpected (node_modules/@babel/parser/lib/index.js:7642:16)
      at Parser.parseExprAtom (node_modules/@babel/parser/lib/index.js:8841:20)
      at Parser.parseExprSubscripts (node_modules/@babel/parser/lib/index.js:8412:23)
      at Parser.parseMaybeUnary (node_modules/@babel/parser/lib/index.js:8392:21)
      at Parser.parseExprOps (node_modules/@babel/parser/lib/index.js:8267:23)
      at Parser.parseMaybeConditional (node_modules/@babel/parser/lib/index.js:8240:23)
      at Parser.parseMaybeAssign (node_modules/@babel/parser/lib/index.js:8187:21)
      at Parser.parseExprListItem (node_modules/@babel/parser/lib/index.js:9491:18)
      at Parser.parseCallExpressionArguments (node_modules/@babel/parser/lib/index.js:8621:22)

我在 Windows 10 机器上使用 VSCode。该项目运行良好,我可以继续开发组件并继续该项目。我就是无法配置 Jest...

只需在 VSCode 的终端中运行 jest 即可复制问题。

我希望单个测试通过,并创建组件的快照。

【问题讨论】:

【参考方案1】:

因此,在进行了进一步的挖掘之后,我设法找到了答案并使其正常工作。我希望这可以帮助将来可能偶然发现此问题的其他人:

    testRegex 和 testMatch 不应一起使用。所以我从我的 jest.config.js 文件中删除了 testRegex。

    更新 jest.setup.js 文件。 来自:

// Import adapter for enzyme
import Enzyme,  configure, shallow, mount, render  from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import 'jest-localstorage-mock';

configure( adapter: new Adapter() );
export  shallow, mount, render ;
export default Enzyme;

收件人:

const Enzyme = require('enzyme');
const Adapter = require ('enzyme-adapter-react-16');

Enzyme.configure( adapter: new Adapter() );
    在我的 tsconfig.json 文件中,我为快捷方式指定了如下路径(我在上面的信息中忽略了这一点):
"paths":               
      "@App/*": ["src/*"],
      "@selectors/*": [ "ts/selectors/*" ],
      "@actions/*": [ "ts/actions/*" ],
      "@components/*": [ "ts/components/*" ],
      "@middleware/*": [ "ts/middleware/*" ],
      "@store/*": [ "ts/store/*" ],
      "@reducers/*": [ "ts/reducers/*" ]
    

这些需要添加到 jest.config.js 文件中,否则 jest 似乎很难阅读 '@store/' 声明。

在“moduleNameMapper”下添加了这些:

moduleNameMapper:  
    "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/assetTransformer.js", 
    "\\.(css|less|scss)$": "<rootDir>/assetTransformer.js",         
    "@App/(.*)": "<rootDir>/src/$1",
    "@selectors/(.*)": "<rootDir>/src/ts/selectors/$1",
    "@actions/(.*)": "<rootDir>/src/ts/actions/$1",
    "@components/(.*)": "<rootDir>/src/ts/components/$1",
    "@middleware/(.*)": "<rootDir>/src/ts/middleware/$1",
    "@store/(.*)": "<rootDir>/src/ts/store/$1",
    "@reducers/(.*)": "<rootDir>/src/ts/reducers/$1"
  
    忘记将 jest.config.js、assetTransformer.js 和 babel.config.js 添加到 eslintignore,所以也添加了那些(可能不相关,但无论如何都需要完成)。

耶...测试运行。

【讨论】:

我可以看看你的回购或类似的东西吗?我得到了/Users/mikaelboutin/Desktop/self/gatsby-react-intl-starter/jest.setup.js:1 ("Object.&lt;anonymous&gt;":function(module,exports,require,__dirname,__filename,global,jest)import Enzyme, mount, render, shallow from 'enzyme' ^^^^^^ SyntaxError: Unexpected identifier【参考方案2】:

在我的情况下,我的文件扩展名有误,我使用的是 .ts 而不是 .tsx

【讨论】:

以上是关于Jest 遇到了意外的令牌(React、Typescript、Babel、Jest 和 Webpack 设置)的主要内容,如果未能解决你的问题,请参考以下文章

Jest 使用 react + konva 和/或 react-konva 遇到了意外的令牌

在 react native + typescript 应用程序上运行 jest 时出错(Jest 遇到了意外的令牌)

意外的导入令牌 - 使用 Jest 测试 React Native

用 Jest 测试 React 应用程序:意外的令牌

开玩笑,意外的令牌导入

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