Syntax error cannot use import statement outside a module jest

This post describes a fix for a common issue with Jest and ESM modules. The available help is not...

Steve Ruiz

This post describes a fix for a common issue with Jest and ESM modules. The available help is not very good: I found many variations on the same question while searching for an answer.


The problem

In a Next.js project, I kept running into an error while using dependencies with ESM modules (.mjs). In my case, this dependency was sucrase, which I was using as part of my app.

The error I saw was:

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/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/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    /Users/.../node_modules/sucrase/dist/index.mjs:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import CJSImportProcessor from "./CJSImportProcessor";
                                                                                      ^^^^^^

    SyntaxError: Cannot use import statement outside a module

Enter fullscreen mode

Exit fullscreen mode

The solution

After much trial and error, here’s what worked.

1. Install dependencies

yarn add --dev jest @babel/core babel-jest

Enter fullscreen mode

Exit fullscreen mode

2. Create a babel.config.js

By default, a Next.js project uses a file called .babelrc to configure Babel. We need to replace this with a file named babel.config.js.

// babel.config.js

module.exports = {
  presets: ['next/babel'],
}

Enter fullscreen mode

Exit fullscreen mode

3.

Finally, the important part. In your jest.config.js, include the following lines.

// jest.config.js

module.exports = {  
  transformIgnorePatterns: ['node_modules/(?!(sucrase)/)'],
  transform: {
    '^.+\.(js|jsx|ts|tsx|mjs)$': 'babel-jest',
  },
  // ...the rest of your config
}

Enter fullscreen mode

Exit fullscreen mode

In my case, the two packages that were causing problems was sucrase. In the config above, we are telling Jest to transform modules using babel-jest, and to ignore everything in node_modules folder except for those two modules.

In your case, it may be other modules that are causing the problem: replace sucrase with the names of your module or, if more than one, each module’s name separated by a | (e.g. (module-a|module-b).

4.

If a module is still causing problems, you’ll need to take other measures. In my case, the solution above worked for sucrase but not for browser-fs-access, another module that used ESM modules. I was able to fix the error by dynamically importing the module (e.g. await import("browser-fs-access")) but still cannot test that part of my code.

If you have a fix for that, I’d love to hear it!

Разрабатываю приложение через create-react-app.
Сегодня попробовал написать свой первый тест. При страте теста получаю сообщение о том, что тестам не удалось запуститься и многв букав, среди которых

SyntaxError: Cannot use import statement outside a module

Вот код теста

import {createLastOnlineDescription} from './OnlineStatus'
import { create } from 'domain'

function twoChar(number){
    if(String(number).length==1)
        return `0${number}`
    else 
        return number
}

describe("createLastOnlineDescription for header online status test",()=>{
    describe('it shuld return `только что`',()=>{
        test('input now',()=>{
            const input = new Date()
            const result = createLastOnlineDescription(input)
            expect(result).toEqual('только что')
        })
        test('input 1 minute ago',()=>{
            const input = new Date(new Date()-60000)
            const result = createLastOnlineDescription(input)
            expect(result).toEqual('только что')
        })
        test('input 2 minute ago',()=>{
            const input = new Date(new Date()-120000)
            const result = createLastOnlineDescription(input)
            expect(result).toEqual('только что')
        })
        test('input 3 minute ago',()=>{
            const input = new Date(new Date()-180000)
            const result = createLastOnlineDescription(input)
            expect(result).toEqual('только что')
        })
        test('input 4 minute ago',()=>{
            const input = new Date(new Date()-240000)
            const result = createLastOnlineDescription(input)
            expect(result).toEqual('только что')
        })
    })


    describe('should return n `минут назад`',()=>{
        test('input 6 minutes ago',()=>{
            const input = new Date(new Date()-360000)
            const result = createLastOnlineDescription(input)
            expect(result).toEqual('6 минут назад')
        })
        test('input 45 minutes ago',()=>{
            const input = new Date(new Date()-2700000)
            const result = createLastOnlineDescription(input)
            expect(result).toEqual('45 минут назад')
        })
        test('input 59 minutes ago',()=>{
            const input = new Date(new Date()-3540000)
            const result = createLastOnlineDescription(input)
            expect(result).toEqual('59 минут назад')
        })
    })


    describe('should return `час назад`',()=>{
        test('input 60 minutes ago',()=>{
            const input = new Date(new Date()-3600000)
            const result = createLastOnlineDescription(input)
            expect(result).toEqual('час назад')
        })
        test('input 70 minutes ago',()=>{
            const input = new Date(new Date()-4200000)
            const result = createLastOnlineDescription(input)
            expect(result).toEqual('час назад')
        })
        test('input 74 minutes ago',()=>{
            const input = new Date(new Date()-4440000)
            const result = createLastOnlineDescription(input)
            expect(result).toEqual('час назад')
        })
    })

    describe('should return `сегодня в...`',()=>{
        test('input 1 hour 16 minutes ago',()=>{
 
            const input = new Date(new Date()-4560000)

            const result = createLastOnlineDescription(input)

            const resultHour = input.getHours()
            const resultMinutes = input.getMinutes()
            expect(result).toEqual(`сегодня в ${twoChar(resultHour)}:${twoChar(resultMinutes)}`)
        })
        test('input 1 hour 59 minutes ago',()=>{
            const input = new Date(new Date()-7140000)

            const result = createLastOnlineDescription(input)

            const resultHour = input.getHours()
            const resultMinutes = input.getMinutes()
            expect(result).toEqual(`сегодня в ${twoChar(resultHour)}:${twoChar(resultMinutes)}`)
        })
    })
})

OnlineStatus.jsx

export function createLastOnlineDescription(lastOnlineDatetime){
    if(lastOnlineDatetime === 'online')
        return 'online'
    const timeDifference = new Date() - new Date(lastOnlineDatetime)
    if(timeDifference<300000)
        return `только что`
    if (timeDifference<3600000) 
        return `${timeDifference / 60000} минут назад` 
    if(timeDifference<4500000) 
        return `час назад`
    if(timeDifference<7200000) 
        return timeConverter(lastOnlineDatetime)

    function timeConverter(UNIX_timestamp){
        const a = new Date(UNIX_timestamp * 1000);
        const months = ['января','февраля','марта','апреля','мая','июня','июля','августа','сентября','октября','ноября','декабря'];
        const month = months[a.getMonth()];
        const date = a.getDate();
        const hour = twoChar(a.getHours());
        const min = twoChar(a.getMinutes());

        if (a.setHours(0,0,0,0) === (new Date()).setHours(0,0,0,0))
            return `сегодня в ${hour}:${min}`;
    


        function twoChar(number){
            if(String(number).length==1)
                return `0${number}`
            else 
                return number
        }
    }
}

package.json

{
  "name": "sberbank-project",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-redux": "^7.1.3",
    "react-scripts": "3.2.0",
    "redux": "^4.0.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "jest",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "jest": "^24.9.0"
  }
}

Cannot use import statement outside a module [React TypeScript Error Solved]

When building a web application, you may encounter the SyntaxError: Cannot use import statement outside a module error.

This error might be raised when using either JavaScript or TypeScript in the back-end. So you could be working on the client side with React, Vue, and so on, and still run into this error.

You can also encounter this error when working with JavaScript on the client side.

In this article, you’ll learn how to fix the SyntaxError: Cannot use import statement outside a module error when using TypeScript or JavaScript with Node.

You’ll also learn how to fix the error when working with JavaScript on the client side.

How to Fix the TypeScript SyntaxError: Cannot use import statement outside a module Error

In this section, we’ll work with a basic Node server using Express.

Note that if you’re using the latest version of TypeScript for your Node app, the tsconfig.json file has default rules that prevent the SyntaxError: Cannot use import statement outside a module error from being raised.

So you’re most likely not going to encounter the SyntaxError: Cannot use import statement outside a module error if you:

  • Install the latest version of TypeScript, and are using the default tsconfig.json file that is generated when you run tsc init with the latest version.
  • Setup TypeScript correctly for Node and install the necessary packages.

But let’s assume you’re not using the latest tsconfig.json file configurations.

Here’s an Express server that listens on port 3000 and logs «Hello World!» to the console:

import express from "express"

const app = express()

app.listen("3000", (): void => {
    console.log("Hello World!")
    // SyntaxError: Cannot use import statement outside a module
})

The code above looks as though it should run perfectly but the SyntaxError: Cannot use import statement outside a module is raised.

This is happening because we used the import keyword to import a module: import express from "express".

To fix this, head over to the tsconfig.json file and scroll to the modules section.

You should see a particular rule like this under the modules section:

/* Modules */
"module": "esnext" 

To fix the problem, change the value «esnext» to «commonjs».

That is:

/* Modules */
"module": "commonjs"

How to Fix the JavaScript SyntaxError: Cannot use import statement outside a module Error

Fixing the SyntaxError: Cannot use import statement outside a module error when using vanilla JS is a bit different from TypeScript.

Here’s our server:

import express from "express";

const app = express();

app.listen(3000, () => {
    console.log("Hello World!");
    // SyntaxError: Cannot use import statement outside a module
});

We’re getting the SyntaxError: Cannot use import statement outside a module error for the same reason — we used the import keyword to import a module.

To fix this, go to the package.json file and add "type": "module",. That is:

{
  "name": "js",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "type": "module",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.18.2"
  }
}

Now you can use the import keyword without getting an error.

To fix this error when working with JavaScript on the client side (without any frameworks), simply add the attribute type="module" to the script tag of the file you want to import as a module. That is:

<script type="module" src="./add.js"></script>

Summary

In this article, we talked about the SyntaxError: Cannot use import statement outside a module error in TypeScript and JavaScript.

This error mainly occurs when you use the import keyword to import a module in Node.js. Or when you omit the type="module" attribute in a script tag.

We saw code examples that raised the error and how to fix them when working with TypeScript and JavaScript.

Happy coding!



Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started

Понравилась статья? Поделить с друзьями:
  • Syntax error cannot assign to conditional expression
  • Syntax error break outside loop что делать
  • Symmetric mean absolute percentage error sklearn
  • Symlink protocol error
  • Symlink cannot create symlink error code 1314