Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

node-fetch 3.0.0 and jest gives SyntaxError: Cannot use import statement outside a module

I'm trying to upgrade my api to use node-fetch 3.0.0. Part of the breaking changes in their documentation is that node-fetch is now a pure ESM module.

https://github.com/node-fetch/node-fetch/blob/main/docs/CHANGELOG.md

My unit tests have started breaking from this change. I was using jest.requireActual("node-fetch") for the Response object

const { Response } = jest.requireActual("node-fetch");

However, with the new change, I get:

"Property 'Response' does not exist on type '{}'."

I tried changing to an import statement which seems to fix that error:

import { Response } from "node-fetch"

Now, I get the following error when I run my unit tests:

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:

    C:\Users\{mypath}\api\node_modules\node-fetch\src\index.js:9
    import http from 'http';
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      2 | import { AuthProvider, TokenCache } from "./tokenTypes";
      3 | import { getUserEmail, getUserId, getUserRole } from "../common/authUtil";
    > 4 | import fetch from "node-fetch";

The error seems to be occurring within node-fetch itself.

I tried changing the test script in my package.json to match what the jest documentation suggests for ESM modules. https://jestjs.io/docs/ecmascript-modules

package.json

"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"

The documentation also suggests changing the transform property in jest.config.js to take an empty object, but my transform object looks like the following for typescript and ts-jest:

jest.config.js

transform: { "^.+\\.ts?$": "ts-jest" }

If I change this to an empty object all of my tests break. I'm not very familiar with CJS vs ESM, so any help would be appreciated.

like image 978
avenmia Avatar asked Sep 29 '21 21:09

avenmia


People also ask

How do you fix Cannot use import statement outside a module in node?

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.

Why we Cannot use import in node JS?

The reason for this error is that Node js doesn't support ES6 import directly. If you try to use import for importing modules directly in node js it will throw out that error.


2 Answers

Fetch 3.0 is designed for using esmodules instead of commonjs. Therefore you have to make sure you import it into a module.

For example: to import it to app.js : Add "type":"module" in your package.json and then import it.

For importing it to other files or app.js even, you can also change the extension from .js to mjs that will tell nodejs to treat as a esmodule.

Otherwise downgrade fetch to use an older version that supports commonjs like 2.something.

npm install node-fetch@2
npm install @types/node-fetch@2
like image 174
Muhammed Sabeeh Avatar answered Oct 02 '22 00:10

Muhammed Sabeeh


I had the same problem! adding

 transform: {
    "^.+\\.(ts|tsx)$": "ts-jest",
    "^.+\\.(js)$": "babel-jest",
  },
  transformIgnorePatterns: [
  ],

to my jest.config.js file solved it. and btw these are my versions:

    "jest": "^27.3.1",
    "ts-jest": "^27.0.7",
    "node-fetch": "^3.1.0"
like image 25
farminf Avatar answered Oct 01 '22 23:10

farminf