react-force-graph icon indicating copy to clipboard operation
react-force-graph copied to clipboard

SyntaxError: "Cannot use import statement outside a module" for CRA, Jest and react-force-graph

Open danielbakas opened this issue 1 year ago • 14 comments

Describe the bug

When trying to import ForceGraph3D from react-force-graph by vasturiano in a create-react-app project, the tests fail with a SyntaxError: "Cannot use import statement outside a module". The error points to the first line of react-force-graph.mjs file.

Did you try recovering your dependencies?

Yes, I tried recovering my dependencies but the issue still persists.

Which terms did you search for in User Guide?

I searched for terms like "Jest encountered an unexpected token", "Cannot use import statement outside a module", "react-force-graph test fails".

Environment

Environment Info:

  current version of create-react-app: 5.0.1
  running from /Users/danielbakas/.npm/_npx/c67e74de0542c87c/node_modules/create-react-app

  System:
    OS: macOS 14.0
    CPU: (8) arm64 Apple M1 Pro
  Binaries:
    Node: 20.3.1 - /opt/homebrew/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 9.6.7 - /opt/homebrew/bin/npm
  Browsers:
    Chrome: 114.0.5735.198
    Safari: 17.0
  npmPackages:
    react: ^18.2.0 => 18.2.0 
    react-dom: ^18.2.0 => 18.2.0 
    react-scripts: ^5.0.1 => 5.0.1 

Steps to reproduce

  1. Create a new app using create-react-app.
  2. Install react-force-graph package using npm install react-force-graph.
  3. In your App component, import ForceGraph3D from react-force-graph.
  4. Run the tests with npm test.

Expected behavior

Tests run successfully without any import errors.

Actual behavior

Tests fail with SyntaxError: "Cannot use import statement outside a module". The error points to the first line of react-force-graph.mjs file.

Captura de pantalla 2023-07-03 a la(s) 2 06 50 a m

danielbakas avatar Jul 02 '23 23:07 danielbakas

@danielbakas the react-force-graph.mjs is an ES modules export. It would seem you're trying to consume from it in a different environment, like CommonJS perhaps. Is that the case?

vasturiano avatar Jul 03 '23 19:07 vasturiano

Hi @vasturiano! Thanks for replying.

I’m not sure. I just did a create-react-app and right off the box imported ForceGraph3D.

I then tried to run the simple render test with npm test and the test failed with that error.

Would you like me to check anything specific about my environment? 🤓

Thanks!

danielbakas avatar Jul 03 '23 19:07 danielbakas

Sounds like it's an issue with CRA not supporting ESM. Please see this doc: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c#im-having-problems-with-esm-and-create-react-app

vasturiano avatar Jul 03 '23 20:07 vasturiano

Are you sure? It seems CRA supports ESM since 4.0.0, and I’m using ^5.0.1

I saw your issue (https://github.com/facebook/create-react-app/issues/10892) but didn’t find any fixes. I hope I’m not mistaken and the issue is in fact the resource you wanted me to look into.

What would be a possible fix for this issue? Have you managed to fix it before?

Thank you for your help @vasturiano!

danielbakas avatar Jul 03 '23 22:07 danielbakas

@danielbakas I can't really be of much help on things that relate to CRA I'm afraid. It's probably more useful to ask that in a more dedicated forum to that platform.

As far as this module is concerned, it's doing what it promises which is to expose a ES module only entrypoint.

vasturiano avatar Jul 11 '23 22:07 vasturiano

Ok. I'll ask over there. Thanks @vasturiano!

danielbakas avatar Jul 15 '23 18:07 danielbakas

Jest is evaluating the code as CJS, because your transformer supplies it as CJS. react-force-graph is published as ESM, but by default Jest does not transform node_modules. This is what you see in third bullet in the error message.

The easier way to deal with this is to use react-force-graph version which was still CJS. Hard to say the exact one without having the change log. I guess the last one was v1.41.20. It came out before https://github.com/vasturiano/react-force-graph/commit/9bcec4a81af2bb9bf9969ad5268796927ed238e6.

The hard way to tell Jest to transform each and every ESM package using the transformIgnorePatterns as described here : https://jestjs.io/docs/tutorial-react-native#transformignorepatterns-customization. That will be a long list, because react-force-graph is pulling a lot of ESM packages. Just follow the error messages and add packages one by one:

"transformIgnorePatterns": [
  "node_modules/(?!(react-kapsule|react-force-graph|jerrypick|3d-force-graph-vr|accessor-fn|three-forcegraph|d3-force-3d)/)"
]

And so on. This is not the full list yet. I stoped, because it feels endless (;

mrazauskas avatar Jul 16 '23 12:07 mrazauskas

Hm.. I was wondering how react-force-graph is tested. For instance, testing integration with React could give ideas for users how to test their apps. Might be I am scrolling to quick.. Are there any tests in this repo?

mrazauskas avatar Jul 16 '23 12:07 mrazauskas

Hm.. I was wondering how react-force-graph is tested.

Me too! And thank you for your answer @mrazauskas!

I started adding each package to the transformPackages too but, as you say, it seemed endless.

Also, using an outdated version of the package would not be ideal, although it’s a valuable option, thank you!

Are there any tests in this repo?

I tried looking for some, but couldn’t find any either.

Maybe @vasturiano can point us in the right direction 🤓

danielbakas avatar Jul 16 '23 12:07 danielbakas

@vasturiano @mrazauskas any updates on this issue? 🤓

danielbakas avatar Sep 04 '23 22:09 danielbakas

I was also facing the same issue, I have done each and every changes that you guys mentioned here, But I am still in the middle of figuring out this stuff, Unfortunately, I haven't found a solution yet.

@mrazauskas @danielbakas

` ● Test suite failed to run

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.
 • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
 • 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:

C:\Dev\ui\node_modules\react-force-graph-2d\dist\react-force-graph-2d.mjs:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import fromKapsule from 'react-kapsule';        
                                                                                  ^^^^^^

SyntaxError: Cannot use import statement outside a module

  1 | import React, { useState, useEffect } from "react";
  2 | import Popover from "@mui/material/Popover";
> 3 | import ForceGraph2D from "react-force-graph-2d";
    | ^
  4 | import MDBox from "components/MDBox";
  5 | import { useTheme } from "@mui/material/styles";
  6 | import PropTypes from "prop-types";

  at Runtime.createScriptFromCode (node_modules/react-scripts/node_modules/jest-runtime/build/index.js:1728:14)
  at Object.<anonymous> (src/layouts/dashboards/imemori/ProgressTop/popup.tsx:3:1)
  at Object.<anonymous> (src/layouts/dashboards/imemori/ProgressTop/circle.tsx:15:1)
  at Object.<anonymous> (src/layouts/dashboards/imemori/ProgressTop/progressTop.tsx:7:1)
  at Object.<anonymous> (src/tests/component/progressTop.test.tsx:2:1)

`

Can you guys please help me out to, how to test forceGraph2d.?

brijesh-imemori avatar Nov 16 '23 06:11 brijesh-imemori

+1

danielbakas avatar Nov 16 '23 22:11 danielbakas

+1

annette-graham avatar Feb 29 '24 11:02 annette-graham

jest.mock("react-force-graph-2d", () => ({
  ForceGraph2D: jest.fn(),
  ForceGraphMethods: jest.fn(),
  NodeObject: jest.fn(),
}));

we found the solution, just add this and you will be able to mock the react-force-graph-2d

brijesh-imemori avatar Apr 03 '24 09:04 brijesh-imemori