41
votes

Jest échoue avec "jeton inattendu *" sur l'instruction d'importation

Pourquoi Jest échoue-t-il avec "jeton inattendu *" sur une simple instruction d'importation ...

Journal des erreurs:

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

fichier package.json :

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

Fichier babel.config.js :

{
  "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"
  }
}

Fichier jest.config.js :

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

Note: J'utilise react-native modèle dactylographiée, comme react-native init MyApp --template typescript


4 commentaires

Pourquoi ne pas import React from 'react'; au lieu?


Je ne sais pas pourquoi, c'est un module basé sur JSX appelé react-navigation-tabs , qui vient d'être importé et utilisé à partir de mes codes TSX , je n'ai pas écrit ça ...


Ensuite, importez-le séparément si vous en avez besoin. Cela ne fait pas partie du package React.


Désolé pour la réponse peu claire, je voulais dire que, la ligne de code sur laquelle Jest échoue, fait partie de la bibliothèque react-navigation-tabs , pas mon code; Mais là où mon code, en a besoin et l'importe, il n'y a aucun problème avec jest , donc, Jest fonctionne dans mes fichiers mais échoue sur les sous-bibliothèques (je ne peux pas simplement supprimer toutes mes utilisations de bibliothèques externes, spécialement celle-ci est requis pour les onglets de l'application)


5 Réponses :


56
votes

Certaines bibliothèques react-native réaction contiennent du code ES6 non compilé.

Le code ES6 doit être compilé avant de pouvoir être exécuté par Jest .

Le document Jest sur le test des applications natives React comprend une section sur la compilation des dépendances qui ne livrent pas de code précompilé .

Vous devrez dire à Jest de compiler react-navigation-tabs de react-navigation-tabs en le mettant en liste blanche dans l'option transformIgnorePatterns de votre configuration Jest .

Exemple:

La modification du fichier jest.config.js en quelque chose comme ci-dessous, a corrigé le problème mentionné dans OP.

Mais le module " react-native-reanimated " (qui nécessite une intégration native, comme décrit dans un autre article ) a besoin de plus de travail, et nous devrions Mock modules avec de telles exigences natives ...

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"
    + ")/)",
  ],
}

Remarque: l'option transformIgnorePatterns (qui est un tableau d'expressions régulières) est à l'origine destinée à exclure des fichiers de la compilation, mais en utilisant le modèle ( (?!(some-dir-name|another-name)) pattern (le (?!...) , look-ahead négatif), nous disons à Jest d'exclure tout ce qui se trouve dans le répertoire node_modules , à l'exception des noms que nous avons spécifiés.


0 commentaires

10
votes

Comme il a été dit, certains modules doivent être transpilés, d'autres non. Voici une regex que j'utilise qui fonctionne dans de nombreux projets

  "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)-(.*)+)"
    ]
  }

Cela fonctionne pour la chose native de réaction la plus courante, et inclut également un package spécifique (ici bs-platform ) comme exemple, lorsqu'il n'est pas capturé par les modèles précédents.


0 commentaires

1
votes

Quelque part dans votre fichier de configuration (.babelrc.js ou package.json), vous devez avoir "modules" sous "presets" réglé sur l'un des "amd" | "umd" | "systemjs" | "commonjs" | "cjs" | "auto" | faux .

référencer ce fragment de la documentation

quelque chose comme ça:

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


0 commentaires

3
votes

J'ai eu un problème similaire sur une application React + Typescript.

La première erreur que j'ai faite a été de définir le jest.config.js comme jest.config.ts

Exécution sur Node v12.latest

Ensuite, la configuration qui a fonctionné pour moi était la suivante:

// package.json
"devDependencies": {
    "@types/jest": "^26.0.5",
    "jest": "^26.1.0",
    "ts-jest": "^26.1.3"
}

// 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"]
}

// 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,
      },
    },
  },
};



0 commentaires

0
votes

J'utilise react-native-web et le correctif pour mon problème était d'ajouter le préréglage react react-native-web à mon 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',
}


0 commentaires