Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest Testing React Native cannot use import statement outside of a module

I have been trying to find out how to fix the following error when trying to run my Jest test using React Native:

FAIL tests/App-test.js ● Test suite failed to run

/home/marijkebuurman/Desktop/sport-data-valley-questionnaire-app/node_modules/react-native/index.js:13
import typeof AccessibilityInfo from './Libraries/Components/AccessibilityInfo/AccessibilityInfo';
^^^^^^

SyntaxError: Cannot use import statement outside a module

  at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
  at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)
  at Object.<anonymous> (node_modules/@react-navigation/native/lib/commonjs/useBackButton.tsx:3:1)

package.json

{
  ...
  "dependencies": {
    "@react-native-community/datetimepicker": "^2.3.2",
    "@react-native-community/masked-view": "^0.1.8",
    "@react-native-community/push-notification-ios": "^1.1.1",
    "@react-native-firebase/app": "^6.7.1",
    "@react-native-firebase/auth": "^6.7.1",
    "@react-native-firebase/firestore": "^6.7.1",
    "@react-navigation/bottom-tabs": "^5.2.6",
    "@react-navigation/material-top-tabs": "^5.1.9",
    "@react-navigation/native": "^5.1.5",
    "@react-navigation/stack": "^5.2.10",
    "axios": "^0.19.2",
    "prop-types": "^15.7.2",
    "react": "16.11.0",
    "react-native": "0.62.2",
    "react-native-background-fetch": "^3.0.5",
    "react-native-elements": "^1.2.7",
    "react-native-gesture-handler": "^1.6.1",
    "react-native-image-picker": "^2.3.1",
    "react-native-keychain": "^5.0.1",
    "react-native-push-notification": "^3.1.9",
    "react-native-reanimated": "^1.8.0",
    "react-native-safe-area-context": "^0.7.3",
    "react-native-screens": "^2.4.0",
    "react-native-tab-view": "^2.14.0",
    "react-native-vector-icons": "^6.6.0"
  },
  "devDependencies": {
    "@babel/core": "^7.6.2",
    "@babel/preset-flow": "^7.10.1",
    "@babel/runtime": "^7.6.2",
    "@bam.tech/react-native-make": "^2.0.0",
    "@react-native-community/eslint-config": "^0.0.5",
    "babel-core": "^7.0.0-bridge.0",
    "babel-jest": "^23.4.2",
    "babel-plugin-module-resolver": "^4.0.0",
    "eslint": "^6.5.1",
    "jest": "^24.9.0",
    "metro-react-native-babel-preset": "^0.56.4",
    "react-native-dotenv": "^0.2.0",
    "react-test-renderer": "16.9.0"
  },
  "jest": {
    "preset": "react-native",
    "setupFiles": [
      "./jest.setup.js"
    ],
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
      "\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js"
    },
    "transformIgnorePatterns": [
      "node_modules/(?!(jest-)?react-native|react-navigation)"
    ]
  }
}

I've tried to fix the problem in my package.json file by usingtransformIgnorePatterns to try and ignore react-navigation, but this hasn't worked.

.babelrc

{
  "presets": [
    "module:metro-react-native-babel-preset",
    "module:react-native-dotenv",
    "@babel/preset-flow"
  ],
  "plugins": [
    [
      "module-resolver",
      {
        "cwd": "babelrc",
        "root": [
          "./src"
        ],
        "extensions": [
          ".js",
          ".ios.js",
          ".android.js"
        ],
        "alias": {
          "api": "./src/api",
          "assets": "./src/assets",
          "services": "./src/services",
          "styles": "./src/styles",
          "components": "./src/components",
          "app": "./src"
        }
      }
    ]
  ]
}

I've also installed and added @babel/preset-flow to the presets in my .babelrc file because I read somewhere this could help, but with no success.

My test

// 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', async () => {
  renderer.create(<App />);
});

The test itself is pretty much the default provided React Native Jest test. I have commented the import statement for React Native as this was giving a similar error when running the test. When that line is uncommented the test still gives the error about AccessibilityInfo import statement, but there is no mention about @react-navigation but rather about ScriptTransformer.js.

My guess is that all this has something to do with my babel configuration, but I haven't been able to figure it out.

like image 748
Bas van der Linden Avatar asked Jun 02 '20 18:06

Bas van der Linden


People also ask

Could not use import statement outside a module?

The "SyntaxError: Cannot use import statement outside a module" occurs when we use the ES6 Modules syntax in a script that was not loaded as a module. To solve the error, set the type attribute to module when loading a script, or in your package.json for Node.js apps.

Do I need to import Jest?

In your test files, Jest puts each of these methods and objects into the global environment. You don't have to require or import anything to use them.

Where do you put transformIgnorePatterns?

You can add the transformIgnorePatterns in your root jest. preset. js or your individual jest config files.

Does Jest require node?

To read TypeScript configuration files Jest requires ts-node . Make sure it is installed in your project.


Video Answer


2 Answers

I've tried out a lot of changes to my .babelrc file, but I eventually fixed the error by converting my .babelrc file to a babel.config.js file that currently looks like this:

module.exports = function(api) {
  api.cache(true);
  return {
    presets: [
      'module:metro-react-native-babel-preset',
      'module:react-native-dotenv',
      '@babel/preset-flow',
    ],
    plugins: [
      [
        'module-resolver',
        {
          root: ['./src'],
          extensions: ['.js', '.ios.js', '.android.js'],
          alias: {
            api: './src/api',
            assets: './src/assets',
            services: './src/services',
            styles: './src/styles',
            components: './src/components',
            app: './src',
          },
        },
      ],
      ['transform-class-properties'],
    ],
  };
};

Aside from this I've added a lot of mocks inside my __mocks__ directory for different packages like for example react-native-firebase. I pretty sure that the mock files I added didn't have a part in fixing the error in my question, but there were other similar errors that were fixed by adding mock files.

By similar errors I mean errors that have an error message like:

SyntaxError: Cannot use import statement outside a module
like image 198
Bas van der Linden Avatar answered Oct 23 '22 18:10

Bas van der Linden


In some cases, fixing this error requires adding the library, which the error complains about to the transformIgnorePatterns, which is in the file jest.config.js.

// jest.config.js 
module.exports = {
  preset: 'react-native', 
    setupFilesAfterEnv: [
    // 1. specific setup for react-native 
    '@testing-library/jest-native/extend-expect',

    // 2. global setup & mocking for some services: 
    './jest.setup.js',

    // 3. mocking for more services: 
    './__mocks__/react-native-firebase.js',
    "./__mocks__/@react-native-community/google-signin.ts", 
  ],
  // 4. You need to add the library to the RegEx below <- Problem Fix
  //    For example, if the error was related to "react-native-elements", you need to add it to the list (as shown below.) 
  transformIgnorePatterns: ["node_modules/(?!((jest-)?react-native|react-native-elements|@react-native(-community)?)/)"], 
}

"react-native": "0.66.4"

"@testing-library/jest-native": "^4.0.4"
"@testing-library/react-native": "^9.0.0"
"babel-core": "^7.0.0-bridge.0"
"babel-jest": "^27.4.6"
"jest": "^27.4.7"
"metro-react-native-babel-preset": "^0.66.2"
like image 2
Bilal Abdeen Avatar answered Oct 23 '22 19:10

Bilal Abdeen