【问题标题】:Jest fails with "Unexpected token *" on import statementJest 在导入语句中以“Unexpected token *”失败
【发布时间】:2019-09-11 15:20:36
【问题描述】:

为什么Jest 在简单的导入语句中失败并显示“Unexpected token *”???

错误日志:

Admin@Admin-PC MINGW32 /d/project (master)
$ npm run test

> MyApp@0.0.1 test D:\project
> jest

FAIL __tests__/App-test.tsx
  ? 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:

    D:\project\node_modules\react-navigation-tabs\src\navigators\createBottomTabNavigator.js:3
    import * as React from 'react';
           ^

    SyntaxError: Unexpected token *

      14 | // );
      15 |
    > 16 | export default createBottomTabNavigator({
         |                ^
      17 |   map: {
      18 |     screen: MapView,
      19 |     navigationOptions: {

      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:471:17)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:513:25)
      at Object.get createBottomTabNavigator [as createBottomTabNavigator] (node_modules/react-navigation-tabs/src/index.js:9:12)
      at Object.<anonymous> (src/app/main.view.tsx:16:16)

FAIL src/component/reinput/example/__tests__/index.ios.js (19.352s)
  ? Console

    console.error node_modules/react-native/Libraries/YellowBox/YellowBox.js:59
      Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

  ? renders correctly

    Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

      at invariant (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:55:15)
      at createFiberFromTypeAndProps (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2054:11)
      at createFiberFromElement (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2075:15)
      at reconcileSingleElement (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:4605:23)
      at reconcileChildFibers (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:4662:35)
      at reconcileChildren (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6329:28)
      at updateHostRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6741:5)
      at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7566:14)
      at performUnitOfWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11234:12)
      at workLoop (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11266:24)

FAIL src/component/reinput/example/__tests__/index.android.js (19.365s)
  ? Console

    console.error node_modules/react-native/Libraries/YellowBox/YellowBox.js:59
      Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

  ? renders correctly

    Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

      at invariant (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:55:15)
      at createFiberFromTypeAndProps (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2054:11)
      at createFiberFromElement (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2075:15)
      at reconcileSingleElement (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:4605:23)
      at reconcileChildFibers (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:4662:35)
      at reconcileChildren (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6329:28)
      at updateHostRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6741:5)
      at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7566:14)
      at performUnitOfWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11234:12)
      at workLoop (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11266:24)

Test Suites: 3 failed, 3 total
Tests:       2 failed, 2 total
Snapshots:   0 total
Time:        22.774s
Ran all test suites.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! MyApp@0.0.1 test: `jest`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the MyApp@0.0.1 test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\Admin\AppData\Roaming\Roaming\npm-cache\_logs\2019-04-22T11_52_36_984Z-debug.log

package.json文件:

{
  "name": "MyApp",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  },
  "dependencies": {
    "react": "16.8.3",
    "react-native": "0.59.4",
    "react-native-gesture-handler": "^1.1.0",
    "react-native-reanimated": "^1.0.1",
    "react-native-splash-screen": "^3.2.0",
    "react-navigation": "^3.8.1",
    "react-navigation-tabs": "^2.1.1"
  },
  "devDependencies": {
    "@babel/core": "^7.4.3",
    "@babel/runtime": "^7.4.3",
    "@types/jest": "^24.0.11",
    "@types/react": "^16.8.13",
    "@types/react-dom": "^16.8.4",
    "@types/react-native": "^0.57.46",
    "@types/react-test-renderer": "^16.8.1",
    "babel-jest": "^24.7.1",
    "jest": "^24.7.1",
    "metro-react-native-babel-preset": "^0.53.1",
    "react-test-renderer": "16.8.3",
    "typescript": "^3.4.3"
  },
  "jest": {
    "preset": "react-native"
  }
}

babel.config.js文件:

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
};

jest.config.js文件:

module.exports = {
  preset: 'react-native',
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
}

注意:我使用的是react-native type-script 模板,比如react-native init MyApp --template typescript

【问题讨论】:

  • 为什么不改用import React from 'react';
  • 我不知道为什么,那是一个基于JSX 的模块,叫做react-navigation-tabs,它只是从我的TSX 代码中导入和使用的,我没有写...跨度>
  • 然后根据需要单独导入。它不是 React 包的一部分。
  • 抱歉,答案不清楚,我的意思是,Jest 失败的代码行是react-navigation-tabs 库的一部分,而不是我的代码;但是在我的代码、需要和导入它的地方,jest 没有任何问题,因此,Jest 在我的文件中工作但在子库中失败(我不能只删除我对外部库的所有用法,特别是应用程序的选项卡需要这个)

标签: javascript typescript jestjs


【解决方案1】:

一些 react-native 库提供未编译的 ES6 代码。

ES6 代码需要经过编译才能被 Jest 运行。

关于 Testing React Native Apps 的 Jest 文档包含一个关于 compiling dependencies that don't ship pre-compiled code 的部分。

您需要告诉 Jest 编译 react-navigation-tabs,方法是在您的 Jest 配置中的 transformIgnorePatterns 选项中将其列入白名单。

示例:

jest.config.js 文件更改为如下所示,修复了 OP 中提到的问题。

但是react-native-reanimated 模块(需要原生集成)需要进一步的工作,我们应该“模拟”具有这种原生要求的模块(如another post 中所述)。

module.exports = {
  preset: 'react-native',
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  transformIgnorePatterns: [
    "node_modules/(?!(react-native"
      + "|react-navigation-tabs"
      + "|react-native-splash-screen"
      + "|react-native-screens"
      + "|react-native-reanimated"
    + ")/)",
  ],
}

注意 transformIgnorePatterns 选项(它是一个正则表达式数组)最初是为了排除文件被编译,但使用 (?!(some-dir-name|another-name)) 模式,带有“(?!...) " 否定前瞻,我们确实告诉 Jest 排除 node_modules 目录中的任何内容,除了我们指定的名称。

【讨论】:

  • 我在 jest.config.js 中放了同样的东西,但得到了 SyntaxError: Unexpected identifier。 /node_modules/@react-native/polyfills/error-guard.js:14 type ErrorHandler = (error: mixed, isFatal: boolean) => void;
  • 诀窍是查看“预设”使用的现有transformIgnorePatterns 并将我的包添加到正则表达式。就我而言,我使用的是preset: 'react-native',所以我必须打开note_modules/react-native/jest-preset.js,从那里复制transformIgnorePatterns,将其添加到我的jest.config.js 并添加有问题的包(在我的情况下是react-native-modal-日期时间选择器)到正则表达式。所以我最终在 jest.config.js 中得到了以下内容:transformIgnorePatterns: [ 'node_modules/(?!((jest-)?react-native|react-native-modal-datetime-picker|@react-native(-community)?)/)', ],
【解决方案2】:

将 babel.config.js 修改为以下内容对我有用。预设也应该首先出现,然后是所有其他配置。

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

【讨论】:

    【解决方案3】:

    如果您不仅使用 React Native 还使用 Expo,我按照官方指南 Testing with Jest 修复了相同的问题,但针对 Expo 组件。具体来说,通过包管理器安装 jest 预设 jest-expo,然后按照他们的描述更新我的 package.json:

    "jest": {
      "preset": "jest-expo",
      "transformIgnorePatterns": [
        "node_modules/(?!(jest-)?react-native|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|@sentry/.*)"
      ]
    }
    

    我还需要在 transformIgnorePatterns 正则表达式字符串的末尾添加 |.*font.* 的例外,因为 Expo Fonts 给我带来了麻烦。可能我可以让它更具体一点,但我讨厌正则表达式,所以我把它留在那里!

    【讨论】:

    • Expo 建议的默认值很好,但当然,它并没有改变 大多数开发人员需要自定义 transformIgnorePatterns 选项(基于项目的 package.json 文件) - 比如接受的答案确实
    • 是的,你没看错。我不确定是否应该将其发布为答案,因为它正在解决一个略有不同但相关的问题。你建议我怎么做?只是我一直回到这个页面好几个小时直到我弄明白了,我没有意识到因为世博会我必须做一些额外的事情。
    • 把它放在这里很好,例如,对于在这个页面中搜索“Expo”并根据他们的需要进行定制的人(尽管,很多“出口”的提及使得它更难找到)
    【解决方案4】:

    如前所述,有些模块需要转译,而有些则不需要。 这是我在很多项目中使用的正则表达式

      "jest": {
        "preset": "react-native",
        "transformIgnorePatterns": [
          "node_modules/(?!(jest-)?react-native|react-(native|universal|navigation)-(.*)|@react-native-community/(.*)|@react-navigation/(.*)|bs-platform|(@[a-zA-Z]+/)?(bs|reason|rescript)-(.*)+)"
        ]
      }
    

    它适用于最常见的 React Native 事物,并且还包括一个特定的包(此处为 bs-platform)作为示例,当以前的模式未捕获时。

    【讨论】:

      【解决方案5】:

      我正在使用 react-native-web,我的问题的解决方法是将 react-native-web 预设添加到我的 jest.config.js:

      module.exports = {
      transform: {
        '^.+\\.tsx?$': 'ts-jest',
      },
      timers: 'fake',
      testPathIgnorePatterns: [
        '<rootDir>/build/',
        '<rootDir>/node_modules/',
        '<rootDir>/rndemo/build/',
      ],
      globals: {
        'ts-jest': {
          diagnostics: {
            warnOnly: true,
          },
        },
      },
      preset: 'react-native-web',
      }
      

      【讨论】:

        【解决方案6】:

        我在 React + Typescript 应用上遇到了类似的问题。

        我犯的第一个错误是将jest.config.js定义为jest.config.ts

        在节点 v12.latest 上运行

        那么对我有用的配置如下:

        // jest.config.js
        
        module.exports = {
          preset: "ts-jest",
          testEnvironment: "node",
          roots: ["./src"],
          transform: { "\\.ts$": ["ts-jest"] },
          testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
          moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
          globals: {
            "ts-jest": {
              tsConfig: {
                // allow js in typescript
                allowJs: true,
              },
            },
          },
        };
        
        
        
        // tsconfig.json
        {
          "compilerOptions": {
            "target": "es5",
            "lib": ["dom", "dom.iterable", "esnext"],
            "allowJs": true,
            "skipLibCheck": true,
            "esModuleInterop": true,
            "allowSyntheticDefaultImports": true,
            "strict": true,
            "forceConsistentCasingInFileNames": true,
            "module": "esnext",
            "moduleResolution": "node",
            "resolveJsonModule": true,
            "isolatedModules": true,
            "noEmit": true,
            "jsx": "react",
            "baseUrl": "."
          },
          "include": ["src"],
          "exclude": ["node_modules", "**/*.spec.ts"]
        }
        
        
        // package.json
        "devDependencies": {
            "@types/jest": "^26.0.5",
            "jest": "^26.1.0",
            "ts-jest": "^26.1.3"
        }
        
        

        【讨论】:

          【解决方案7】:

          在您的配置文件(.babelrc.js 或 package.json)中,您必须将“预设”下的“模块”设置为 “amd”| 之一。 “嗯” | “系统” | “普通” | "cjs" | “汽车” |错误

          来自文档的referer this fragment

          类似这样的:

              "presets": [
            [
              "@babel/preset-env", {
                "targets": process.env.BABEL_TARGET === 'node' ? {
                  "node": 'current'
                } : {
                  "browsers": [ "last 2 versions" ]
                },
                "loose": true,
                "modules": 'commonjs'
              }
            ]
          ]
          

          【讨论】:

            猜你喜欢
            • 2020-01-15
            • 1970-01-01
            • 2019-11-10
            • 2022-06-16
            • 2017-06-10
            • 2017-05-02
            • 2019-04-24
            • 2020-12-28
            • 1970-01-01
            相关资源
            最近更新 更多