Pourquoi Jest
échoue-t-il avec "jeton inattendu *" sur une simple instruction d'importation ...
module.exports = { preset: 'react-native', moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], }
package.json
:module.exports = { presets: ['module:metro-react-native-babel-preset'], };
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" } }
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
5 Réponses :
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
.
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.
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.
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' } ] ]
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, }, }, }, };
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', }
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 codesTSX
, 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èquereact-navigation-tabs
, pas mon code; Mais là où mon code, en a besoin et l'importe, il n'y a aucun problème avecjest
, 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)