"SyntaxError: Cannot use import statement outside a module" error while testing React Native project with Jest and #testing-library/react-native? - react-native

Error I'm getting Anytime I run npm test:
FAIL ./App.test.js
● 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:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
• 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:
/Users/bestes/Desktop/react-native-training/node_modules/react-native-status-bar-height/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import { Dimensions, Platform, StatusBar } from 'react-native';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1350:14)
at Object.<anonymous> (node_modules/react-native-elements/src/config/index.js:1:1)
My Test:
import 'react-native';
import React from 'react';
import { render } from '#/../testing/test-utils'
import App from './App'
test('should render app component', () => {
const result = render(<App />)
expect(result).toMatchSnapshot()
})
My test-utils.js file:
import React from 'react'
import { render } from '#testing-library/react-native'
import { store } from '#/bootstrap/redux'
import { Provider } from 'react-redux'
const AllTheProviders = ({ children }) => {
return (
<Provider store={store}>
{children}
</Provider>
)
}
const customRender = (ui, options) =>
render(ui, { wrapper: AllTheProviders, ...options })
// re-export everything
export * from '#testing-library/react-native'
// override render method
export { customRender as render }
My package.json file:
{
"name": "ReactNativeTraining",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
},
"dependencies": {
"#react-native-community/geolocation": "2.0.2",
"#react-native-community/masked-view": "0.1.10",
"#react-native-picker/picker": "1.9.10",
"#reduxjs/toolkit": "1.5.0",
"axios": "0.21.1",
"dayjs": "1.10.4",
"lodash": "4.17.20",
"react": "16.13.1",
"react-native": "0.63.2",
"react-native-config": "1.4.2",
"react-native-elements": "3.0.0-alpha.1",
"react-native-geocoding": "0.5.0",
"react-native-gesture-handler": "1.9.0",
"react-native-permissions": "3.0.0",
"react-native-picker-select": "8.0.4",
"react-native-reanimated": "1.13.2",
"react-native-safe-area-context": "3.1.9",
"react-native-screens": "2.17.0",
"react-native-size-matters": "0.4.0",
"react-native-vector-icons": "8.0.0",
"react-navigation": "4.0.2",
"react-navigation-stack": "1.5.4",
"react-navigation-tabs": "2.4.1",
"react-redux": "7.2.2"
},
"devDependencies": {
"#babel/core": "7.12.10",
"#babel/runtime": "7.12.5",
"#react-native-community/eslint-config": "2.0.0",
"#testing-library/jest-native": "4.0.1",
"#testing-library/react-native": "7.2.0",
"babel-jest": "^26.6.3",
"babel-plugin-module-resolver": "4.0.0",
"eslint": "7.18.0",
"jest": "26.6.3",
"metro-react-native-babel-preset": "0.64.0",
"react-test-renderer": "16.13.1"
},
"type": "module",
"jest": {
"verbose": true,
"preset": "react-native",
"setupFilesAfterEnv": ["#testing-library/jest-native/extend-expect"],
"transformIgnorePatterns": [
"node_modules/(?!(react-native",
"#react-native-community/geolocation",
"#react-native-community/masked-view",
"|#react-native-picker/picker",
"|#reduxjs/toolkit",
"|axios",
"|dayjs",
"|lodash",
"|react",
"|react-native",
"|react-native-config",
"|react-native-elements",
"|react-native-geocoding",
"|react-native-gesture-handler",
"|react-native-permissions",
"|react-native-picker-select",
"|react-native-reanimated",
"|react-native-safe-area-context",
"|react-native-screens",
"|react-native-size-matters",
"|react-native-vector-icons",
"|react-navigation",
"|react-navigation-stack",
"|react-navigation-tabs",
"|react-redux",
")/)"
]
}
}
My babel.config.js file:
module.exports = function (api) {
api.cache(true)
const presets = [
'module:metro-react-native-babel-preset'
]
const plugins = [
[
'module-resolver', {
'root': ['./src/'],
'extensions': ['.js', '.ios.js', '.android.js'],
'alias': {
'#': './src/'
}
}
]
]
return {
presets,
plugins
}
}
What I've tried:
Adding "type": "module" to my root level package.json file, which fixed a similar error with exporting,
Adding Transform Ignore Patterns to the Jest key in the package.json file.
I'd added ALL of my dependencies to the transformIgnorePatterns as it kept throwing errors on each one, until I added all and now it throws on react-native modules imports.

[Solved] Work for me
Install below
npm install --save-dev #babel/core
npm install --save-dev #babel/preset-env
after that create the "babel.config.js" file in the root and that content should be as below
module.exports = {
presets: ['#babel/preset-env', '#babel/preset-react'],
env: {
test: {
plugins: ["#babel/plugin-transform-runtime"]
}
}
};

Related

react-native-testing-library with typescript does not work

I've tried for days many ways to set up #testing-library/react-native with typescript following a sort of guides but still not able to render a simple component.
Roughly, my stack is react native with typescript and jest with ts-jest and react-native-testing-library. I'm following these guidelines among others:
Typescript React Native with Jest
Using TypeScript with React Native
Using with React Native
This is the error I'm getting for the simple test component below:
ReferenceError: React is not defined
Component:
import React from 'react'
import { View, Text } from 'react-native'
const SomeComponent = () => {
return (
<View>
<Text>Hello</Text>
</View>
)
}
export default SomeComponent
Test:
import { render } from '#testing-library/react-native'
import SomeComponent from './SomeComponent'
describe('<SomeComponent>', () => {
it('should render some component', () => {
const { getByText } = render(<SomeComponent />)
expect(getByText(/hello/i)).toBeDefined()
})
})
Follow a bunch of configurations for reference:
Dependencies:
{
"name": "connect",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "react-native start",
"debug": "open 'rndebugger://set-debugger-loc?host=localhost&port=8081' && react-native start",
"android": "react-native run-android",
"ios": "react-native run-ios",
"pod": "npx pod-install",
"test": "jest",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
},
"dependencies": {
"#airbrake/browser": "^2.1.7",
"#react-navigation/bottom-tabs": "^6.2.0",
"#react-navigation/native": "^6.0.8",
"#react-navigation/native-stack": "^6.5.1",
"#reduxjs/toolkit": "^1.8.0",
"#rneui/base": "^4.0.0-rc.1",
"#rneui/themed": "^4.0.0-rc.1",
"#types/react": "^17",
"#types/react-native-dotenv": "^0.2.0",
"#types/react-redux": "^7.1.23",
"axios": "^0.26.1",
"formik": "^2.2.9",
"http-status": "^1.5.0",
"moment": "^2.29.2",
"react": "17.0.2",
"react-native": "0.67.4",
"react-native-blob-util": "^0.13.8",
"react-native-dotenv": "^3.3.1",
"react-native-dropdownalert": "^4.5.1",
"react-native-error-boundary": "^1.1.12",
"react-native-loading-spinner-overlay": "^2.0.0",
"react-native-safe-area-context": "^4.2.2",
"react-native-screens": "^3.13.1",
"react-native-splash-screen": "^3.3.0",
"react-native-vector-icons": "^9.1.0",
"react-redux": "^7.2.6",
"redux-persist": "^6.0.0",
"redux-persist-filesystem-storage": "^4.0.0",
"use-debounce": "^7.0.1",
"yup": "^0.32.11"
},
"devDependencies": {
"#babel/core": "^7.12.9",
"#babel/preset-env": "^7.16.11",
"#babel/runtime": "^7.12.5",
"#react-native-community/eslint-config": "^3.0.1",
"#testing-library/jest-native": "^4.0.4",
"#testing-library/react-native": "^9.1.0",
"#types/jest": "^27.4.1",
"#types/react-native": "^0.66.15",
"#types/react-native-loading-spinner-overlay": "^0.5.3",
"#types/react-test-renderer": "^17.0.1",
"babel-jest": "^27.5.1",
"eslint": "7.32.0",
"jest": "^27.5.1",
"metro-react-native-babel-preset": "^0.70.1",
"react-addons-test-utils": "^15.6.2",
"react-native-typescript-transformer": "^1.2.13",
"react-test-renderer": "18.0.0",
"ts-jest": "^27.1.4",
"typescript": "^4.4.4"
},
"resolutions": {
"#types/react": "^17"
}
}
jest.config.js
const { defaults: tsjPreset } = require('ts-jest/presets')
module.exports = {
...tsjPreset,
preset: 'react-native',
transform: {
...tsjPreset.transform,
'\\.js$': '<rootDir>/node_modules/react-native/jest/preprocessor.js',
},
globals: {
'ts-jest': {
babelConfig: true,
},
},
transformIgnorePatterns: [
'/node_modules/(?!(#rneui|#react-native|react-native|react-native-size-matters|react-native-ratings|redux-persist-filesystem-storage|react-native-blob-util)/)',
],
setupFiles: ['./jest.setup.js'],
cacheDirectory: '.jest/cache',
}
babel.config.js
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'module:react-native-dotenv',
{
moduleName: 'react-native-dotenv',
},
],
],
}
tsconfig.json
{
"compilerOptions": {
"target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"lib": ["es2017"], /* Specify library files to be included in the compilation. */
"allowJs": true, /* Allow javascript files to be compiled. */
"jsx": "react-native", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
"noEmit": true, /* Do not emit outputs. */
"isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
"strict": true, /* Enable all strict type-checking options. */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"skipLibCheck": false, /* Skip type checking of declaration files. */
"resolveJsonModule": true /* Allows importing modules with a ‘.json’ extension, which is a common practice in node projects. */
},
"exclude": [
"node_modules", "babel.config.js", "metro.config.js", "jest.config.js"
]
}
tsconfig.spec.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"jsx": "react"
}
}
rn-cli.config.js
module.exports = {
getTransformModulePath() {
return require.resolve('react-native-typescript-transformer')
},
getSourceExts() {
return ['ts', 'tsx']
},
}
There is a similar open question about this setup here Setup for React Native/TypeScript/Testing Library/Jest not working
Thanks!
You need run npm install #babel/plugin-transform-react-jsx --save-dev into terminal and add plugin into babel.config.js
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'module:react-native-dotenv',
{
moduleName: 'react-native-dotenv',
},
],
// add new plugin
[
'#babel/plugin-transform-react-jsx',
{
runtime: 'automatic',
},
],
],
}
You can use the official RNTL example that showcases a proper RNTL which also includes TypeScript.
Config issues like yours are hard to resolve as some small hard to notice issues might easily break the setup, so it's usually easiest to start with working setup.

Jest Testing in React Native (EXPO) .jsx extension not working "React.createElement: type is invalid"

Issue
I'm trying to test using jest, but it looks like my compiler is not handling .jsx files. If I change both of the files extension to js: (App.jsx and App.test.jsx) to (App.JS and App.test.JS), it does work. But I want to be able to use jsx files.
Files
App.jsx
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
export default function App() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
</View>
);
}
App.test.jsx
import React from 'react';
// import { render } from '#testing-library/react-native';
import renderer from 'react-test-renderer';
import App from './App';
it('renders correctly', () => {
const tree = renderer.create(<App />).toJSON();
expect(tree.children.length).toBe(1);
// const { toJSON } = render(<App />); // ** THIS DOESN'T WORK EITHER **
// expect(toJSON()).toMatchSnapshot();
});
Console Error
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
package.json
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"eject": "expo eject",
"test": "jest --watch",
"test:debug": "jest",
"test:coverage": "npm test -- --coverage --watchAll",
"test:pr": "npm test -- coverage --ci --silent --changedSince=origin/development --coverageReporters='text' --coverageReporters='lcov'",
"test:all": "npm test -- --coverage --ci --silent --watchAll=false",
"linter": "eslint src",
"linter:fix": "eslint src --fix"
},
"dependencies": {
"#react-native-async-storage/async-storage": "^1.13.0",
"#react-navigation/native": "^5.9.4",
"#reduxjs/toolkit": "^1.5.1",
"babel-jest": "^26.6.3",
"expo": "~41.0.1",
"expo-status-bar": "~1.0.4",
"i18next": "^20.2.2",
"moment": "^2.29.1",
"msw": "^0.28.2",
"node-fetch": "^2.6.1",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-41.0.0.tar.gz",
"react-native-web": "~0.13.12",
"redux": "^4.1.0",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"#babel/core": "^7.9.0",
"#babel/eslint-parser": "^7.14.2",
"#babel/eslint-plugin": "^7.13.16",
"#babel/plugin-proposal-class-properties": "^7.13.0",
"#testing-library/react-native": "^7.2.0",
"#types/jest": "^26.0.23",
"eslint": "^7.26.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-plugin-import": "^2.23.0",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-react-hooks": "^4.2.0",
"identity-obj-proxy": "^3.0.0",
"jest-expo": "^41.0.0",
"react-test-renderer": "^17.0.2"
},
"jest": {
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(js|jsx)$",
"moduleFileExtensions": [
"js",
"json",
"jsx"
],
"preset": "jest-expo",
"setupFiles": [
"./jestSetup.js"
],
"transform": {
"^.+\\.(js|jsx|mjs)$": "babel-jest"
},
"moduleNameMapper": {
".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "identity-obj-proxy"
}
},
"private": true
}
You need to configure Jest to accept jsx extensions. This is done in the jest section of your package.json file or in your jest.config.js file (if you have both Jest seems to ignore the package.json contents).
Take a look at this: https://levelup.gitconnected.com/setting-up-jest-under-expo-to-work-with-jsx-files-ba35a51bc25a
Here's what worked for me:
$ yarn add --dev babel-jest#latest
then in package.json:
"jest": {
"preset": "jest-expo",
"transformIgnorePatterns": [
"node_modules/(?!((jest-)?react-native|#react-native(-community)?)|expo(nent)?|#expo(nent)?/.*|#expo-google-fonts/.*|react-navigation|#react-navigation/.*|#unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg)"
],
"transform": {
"^.+\\.[jt]sx?$": "babel-jest"
}
}

How do I clean up my React Native/Expo application to work with Jest?

I have an existing project that uses React Native and Expo. Currently, the application runs fine. I'm trying to integrate Jest into the project. A basic "true=true" test in jest passes and runs without error. When I try to run any code using ES6 terms, however, the following error occurs:
FAIL screens/__tests__/home.test.js
● 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:
/Users/user/Documents/GitHub/ReadingRainbow/node_modules/react-native/index.js:13
import typeof AccessibilityInfo from './Libraries/Components/AccessibilityInfo/AccessibilityInfo';
^^^^^^
SyntaxError: Cannot use import statement outside a module
1 | import React from 'react';
> 2 | import { Image, View, Text, Button, TouchableOpacity, ScrollView} from 'react-native';
| ^
3 | import { globalStyles } from '../styles/global';
4 | import { useNavigation } from '#react-navigation/native';
5 |
at Runtime._execModule (node_modules/jest-expo/node_modules/jest-runtime/build/index.js:1157:58)
at Object.<anonymous> (screens/home.js:2:1)
at Object.<anonymous> (screens/__tests__/home.test.js:2:1)
I have also set up a clean, brand new project (following these directions first and these second) to test the compare the dependencies and such against my current project. The clean project runs as intended, including import/export statements. How do I correct and clean up my real project so that jest runs without error?
I have tried deleting the node_modules folder and running npm install to reestablish the dependencies. I have also tried adjusting the preset configurations for jest, the transformIgnorePatterns, and the preset defined in babel.config.js. The most helpful explanation I've been given so far is, "[this is probably not working because] node can't use imports (without transpiling) and jest is trying to render using node instead of a browser." Any help is sincerely appreciated! Please let me know if you need further information or clarification.
Example file:
// Intro.js
import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native';
const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor: '#F5FCFF',
flex: 1,
justifyContent: 'center',
},
instructions: {
color: '#333333',
marginBottom: 5,
textAlign: 'center',
},
welcome: {
fontSize: 20,
margin: 10,
textAlign: 'center',
},
});
export default class Intro extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>
This is a React Native snapshot test.
</Text>
</View>
);
}
}
Example test:
// __tests__/Intro-test.js
import React from 'react';
import renderer from 'react-test-renderer';
import Intro from './Intro';
test('renders correctly', () => {
const tree = renderer.create(<Intro />).toJSON();
expect(tree).toMatchSnapshot();
});
package.json of "clean" project
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject",
"test": "jest"
},
"dependencies": {
"expo": "~39.0.2",
"expo-status-bar": "~1.0.2",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-39.0.4.tar.gz",
"react-native-web": "~0.13.12"
},
"devDependencies": {
"#babel/core": "~7.9.0",
"jest-expo": "^39.0.0",
"react-test-renderer": "^17.0.1"
},
"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/.*)"
]
},
"private": true
}
package.json of my actual project
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"test": "jest",
"test:update": "jest --verbose --coverage --updateSnapshot",
"test:watch": "jest --verbose --watch",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"#react-native-community/masked-view": "0.1.10",
"#react-navigation/native": "^5.8.2",
"#react-navigation/stack": "^5.11.1",
"axios": "^0.20.0",
"expo": "~39.0.2",
"expo-status-bar": "~1.0.2",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-39.0.2.tar.gz",
"react-native-dotenv": "^2.4.2",
"react-native-gesture-handler": "~1.7.0",
"react-native-reanimated": "~1.13.0",
"react-native-safe-area-context": "3.1.4",
"react-native-screens": "~2.10.1",
"react-native-testing-library": "^6.0.0",
"react-native-web": "~0.13.12",
"react-navigation-stack": "^2.10.0"
},
"devDependencies": {
"#babel/core": "~7.9.0",
"#babel/preset-env": "^7.12.1",
"#babel/preset-react": "^7.12.1",
"#testing-library/react": "^11.1.0",
"babel-jest": "^26.6.2",
"jest": "^26.6.2",
"jest-expo": "^39.0.0",
"react": "^17.0.1",
"react-navigation": "^4.4.3",
"react-test-renderer": "^17.0.1"
},
"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/.*)"
]
},
"private": true
}
babel.config.js
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
jest.config.json (non-existent in "clean" project)
{
"testRegex": "((\\.|/*.)(test))\\.js?$"
}
In your __tests__/Intro-test.js file, just above the test, mock your component like this
jest.mock('./Intro', () => './Intro');
The content of your file will look like this:
// __tests__/Intro-test.js
import React from 'react';
import renderer from 'react-test-renderer';
import Intro from './Intro';
jest.mock('./Intro', () => './Intro');
test('renders correctly', () => {
const tree = renderer.create(<Intro />).toJSON();
expect(tree).toMatchSnapshot();
});
I was facing the exact same problem. Mocking my components solved the issue. I hope it will help you too.

React Native tests failing, missing babel transforms

I want to test a React Native application that I've created based on the default guides, so it's very simple and has not had any changes w.r.t. the initial test configuration. The only difference seems to be that it's using npm instead of yarn (so it has a package-lock.json).
Here is the package.json:
{
"name": "foo",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
},
"dependencies": {
"react": "16.9.0",
"react-native": "0.61.5",
"react-native-gesture-handler": "^1.5.2",
"react-navigation": "^4.0.10",
"react-navigation-stack": "^1.10.3"
},
"devDependencies": {
"#babel/core": "^7.7.4",
"#babel/runtime": "^7.7.4",
"#react-native-community/eslint-config": "^0.0.5",
"babel-jest": "^24.9.0",
"eslint": "^6.7.1",
"jest": "^24.9.0",
"license-checker": "^25.0.1",
"metro-react-native-babel-preset": "^0.57.0",
"react-test-renderer": "16.9.0"
},
"jest": {
"preset": "react-native"
}
}
The test file __tests__/App-test.js is very simple (and auto-generated):
import 'react-native';
import React from 'react';
import App from '../App';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('renders correctly', () => {
renderer.create(<App />);
});
I get this error:
➜ npm test
> jest
FAIL __tests__/App-test.js
● 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:
/node_modules/#foo/bar/src/main.js:24
export function milliseconds(timeoutInMilliseconds) {
^^^^^^
SyntaxError: Unexpected token 'export'
Now, I don't really understand why it wouldn't work "out of the box". Other guides mention the same steps, too.
Adding a .babelrc with:
{
"presets": ["react-native"]
}
produces the error:
Cannot find module 'babel-preset-react-native' from '/'
- If you want to resolve "react-native", use "module:react-native"
at Function.module.exports [as sync] (node_modules/resolve/lib/sync.js:74:15)
at resolveStandardizedName (node_modules/#babel/core/lib/config/files/plugins.js:101:31)
at resolvePreset (node_modules/#babel/core/lib/config/files/plugins.js:58:10)
at loadPreset (node_modules/#babel/core/lib/config/files/plugins.js:77:20)
at createDescriptor (node_modules/#babel/core/lib/config/config-descriptors.js:154:9)
at node_modules/#babel/core/lib/config/config-descriptors.js:109:50
at Array.map (<anonymous>)
at createDescriptors (node_modules/#babel/core/lib/config/config-descriptors.js:109:29)
at createPresetDescriptors (node_modules/#babel/core/lib/config/config-descriptors.js:101:10)
at presets (node_modules/#babel/core/lib/config/config-descriptors.js:47:19)
There is already a babel.config.js file with the following contents (as suggested here):
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
};
What should I do? I've seen this question but the React App has not been upgraded and is not missing anything, AFAICT. Note that when I create a completely new app with the init script, the tests run fine.
You are using "react-navigation": "^4.0.10" which uses react-native-gesture-handler. Jest does not know about it. You have to mock react-native-gesture-handler and add react-navigation to transformIgnorePatterns or use react-native-jest-mocks.
Some examples of mocking react-native-gesture-handler can be found here: https://github.com/software-mansion/react-native-gesture-handler/issues/344
Add "files": ["jest/setup.js"]," inside package.json. Also transformIgnorePatterns must include react-navigation-stack, #react-native-community, react-native-gesture-handler and react-navigation.
package.json:
"files": [
"jest/setup.js"
],
"jest": {
"preset": "react-native",
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
},
"setupFiles": ["./jest/setup.js"],
"testPathIgnorePatterns": [
"/node_modules/"
],
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native|react-navigation-stack|#react-native-community|react-native-gesture-handler|react-navigation|#react-navigation/.*)"
]
}
jest/setup.js:
import { NativeModules as RNNativeModules } from "react-native";
RNNativeModules.UIManager = RNNativeModules.UIManager || {};
RNNativeModules.UIManager.RCTView = RNNativeModules.UIManager.RCTView || {};
RNNativeModules.RNGestureHandlerModule = RNNativeModules.RNGestureHandlerModule || {
State: { BEGAN: "BEGAN", FAILED: "FAILED", ACTIVE: "ACTIVE", END: "END" },
attachGestureHandler: jest.fn(),
createGestureHandler: jest.fn(),
dropGestureHandler: jest.fn(),
updateGestureHandler: jest.fn(),
};
RNNativeModules.PlatformConstants = RNNativeModules.PlatformConstants || {
forceTouchAvailable: false
};
jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper');
Now run jest and it should pass the test. I have created a repo with an example RN 0.61 app using react-navigation that has jest test passing: https://github.com/clytras/RNJestTest
Or you can try react-native-jest-mocks but I haven't tried it with RN 0.61 yet.

Jest Encountered Unexpected token with import statement

I've tried many fixes based on SO and GH answers but none have worked.
I'm trying to set up Jest and Enzyme for my React Native project but I can't get tests to run. Here's my current test file:
import React from "react";
import { shallow, mount } from "enzyme";
// import MapScreen from "../src/screens/MapView";
describe("MapScreen", () => {
it("should render tab bar icons", () => {
expect(true).toEqual(true); // just to get tests working at all!
});
});
The error:
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:
/Users/TuzMacbookPro2017/Development/QMG-local/APPS/ELECTRO/node_modules/expo/build/environment/validate.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import {
^
SyntaxError: Unexpected token {
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.<anonymous> (node_modules/expo/build/Expo.js:278:1)
My config files:
// jest.config.js
module.exports = {
setupFilesAfterEnv: ["<rootDir>setup-tests.js"],
transformIgnorePatterns: [
"node_modules/(?!(jest-)?react-native|#react-native-community|react-native-elements)"
]
};
// babel.config.js
module.exports = function(api) {
api.cache(true);
return {
presets: ["babel-preset-expo"]
};
};
// setup-tests.js
import Adapter from "enzyme-adapter-react-16";
import { configure } from "enzyme";
import jsdom from "jsdom";
import "react-native";
import "jest-enzyme";
function setUpDomEnvironment() {
const { JSDOM } = jsdom;
const dom = new JSDOM("<!doctype html><html><body></body></html>", {
url: "http://localhost/"
});
const { window } = dom;
global.window = window;
global.document = window.document;
global.navigator = {
userAgent: "node.js"
};
copyProps(window, global);
}
function copyProps(src, target) {
const props = Object.getOwnPropertyNames(src)
.filter(prop => typeof target[prop] === "undefined")
.map(prop => Object.getOwnPropertyDescriptor(src, prop));
Object.defineProperties(target, props);
}
setUpDomEnvironment();
configure({ adapter: new Adapter() });
// package.json
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"eject": "expo eject",
"test": "node ./node_modules/jest/bin/jest.js --watchAll"
},
"jest": {
"preset": "jest-expo",
"testEnvironment": "node",
"globals": {
"__DEV__": true
}
},
"dependencies": {
"#expo/samples": "2.1.1",
"#react-native-community/async-storage": "^1.3.4",
"expo": "^32.0.0",
"native-base": "^2.12.1",
"react": "16.5.0",
"react-dom": "^16.8.6",
"react-native": "0.57",
"react-native-elements": "^1.1.0",
"react-native-geocoding": "^0.3.0",
"react-native-global-font": "^1.0.2",
"react-native-indicators": "^0.13.0",
"react-native-keyboard-aware-scrollview": "^2.0.0",
"react-native-material-dropdown": "^0.11.1",
"react-native-render-html": "^4.1.2",
"react-native-uuid": "^1.4.9",
"react-navigation": "^3.9.1",
"react-redux": "^6.0.1",
"redux": "^4.0.1",
"redux-test-utils": "^0.3.0",
"redux-thunk": "^2.3.0",
"sugar": "^2.0.6"
},
"devDependencies": {
"#babel/preset-react": "^7.0.0",
"babel-preset-expo": "^5.0.0",
"babel-preset-react-native": "^4.0.1",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.12.1",
"fetch-mock": "^7.3.3",
"jest": "^24.8.0",
"jest-enzyme": "^7.0.2",
"jest-expo": "^32.0.0",
"jsdom": "^14.1.0",
"mock-async-storage": "^2.1.0",
"react-test-renderer": "^16.8.6",
"redux-mock-store": "^1.5.3"
},
"private": true,
"rnpm": {
"assets": [
"./assets/fonts"
]
}
}
I can't get even this simple test to run. I have actually been able to get that test to run on a different branch, and copied all the test-related config files from that branch to this one, but I'm still getting this error.
I know there are many posts about this around but none seem to help me. I hope someone can help me get this working! Thanks!