josdejong / svelte-jsoneditor

A web-based tool to view, edit, format, repair, query, transform, and validate JSON
https://jsoneditoronline.org
Other
818 stars 108 forks source link

Jest failling with `SyntaxError: Unexpected token '.'` #294

Closed adrianbunea closed 11 months ago

adrianbunea commented 11 months ago

This is a React project. The unit test fails in the file that imports the components.

import { JSONEditor } from 'vanilla-jsoneditor'

From what I understood from other issues around Jest and this library, the problem is that this package uses ESM module exports. Jest does not compile node_modules because it assumes all node packages export in a usable format such as CommonJS. I tried to make Jest compile that package only using

transformIgnorePatterns: [
    "/node_modules/(?!vanilla-jsoneditor)",
]

and I also tried to add this to my babel config

env: {
    test: {
        plugins: [
            '@babel/plugin-transform-modules-commonjs',
            '@babel/plugin-transform-runtime'
        ]
    }
}

But all of this, or any other combination of solutions doesn't seem to work for me, despite following multiple leads. How do I solve this?

Some important packages

dependencies: {
    ...
    "react": "17.0.2",
    ...
},
devDependencies: {
    ...
    "@babel/core": "7.22.5",
    "@babel/eslint-parser": "7.22.5",
    "@babel/plugin-proposal-class-properties": "7.18.6",
    "@babel/plugin-proposal-private-methods": "7.18.6",
    "@babel/plugin-transform-modules-commonjs": "^7.22.5",
    "@babel/plugin-transform-runtime": "7.22.5",
    "@babel/preset-env": "7.22.5",
    "@babel/preset-react": "7.22.5",
    "jest": "27.4.7",
    ...
}

My entire babel.config.js:

module.exports = {
  presets: [
    '@babel/preset-env',
    '@babel/preset-react'
  ],
  plugins: [
    '@babel/plugin-proposal-private-methods',
    '@babel/plugin-proposal-class-properties',
    [
      'module-resolver',
      {
        root: [
          './',
          './src'
        ]
      }
    ]
  ],
  env: {
    test: {
      plugins: [
        '@babel/plugin-transform-modules-commonjs',
        '@babel/plugin-transform-runtime'
      ]
    }
  }
}
josdejong commented 11 months ago

Thanks for reporting Adrian.

From what I understood from other issues around Jest and this library, the problem is that this package uses ESM module exports.

:joy: If Jest can't handle ESM modules I would say it has a serious problem.

Looking at the short error message, I guess it has to do with the vanilla-jsoneditor bundle not transpiling some new JavaScript functionality to plain old ES5, and your Jest setup not supporting this new functionality. Can you share the stack trace?

So how can I reproduce this issue? Is it possible to create a minimal git project that I can try out?

adrianbunea commented 11 months ago

Nevermind, I found the actual problem. It's silly how I wasted my time trying to debug Jest instead of reading the message more carefully.

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:

    /Users/adrianbunea/projects/long-path-name/src/app/dir1/dir2/components/dir3/json-editor.css:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){.vanilla-jsoneditor-react {
                                                                                      ^

    SyntaxError: Unexpected token '.'

And this is the actual JS code, I did not want to put it to not disclose sensitive information and I thought I knew better about what the error message meant.

 import React, { useEffect, useRef } from 'react'
      2 | import { JSONEditor } from 'vanilla-jsoneditor'
    > 3 | import 'app/dir1/dir2/components/dir3/json-editor.css'
        | ^
      4 |

I disregarded the last part of the output because I got distracted by the Jest part, and it seemed to not say anything useful. But I was wrong. The unexpected token was the . when declaring the rules for my class in a CSS file. For some reason it doesn't like me declaring a simple CSS file with plain styles when running tests. When I removed the import of the CSS the tests passed. So now I know I was looking in the wrong place.

Thinking about it, if this was a Jest issue I should've posted it on their repo, not here, but I remembered reading some issues about this on this repo a long time ago when I first found this problem so I thought I'd ask for help here, since other people dealt with it as well.

Sorry for the false alarm.

adrianbunea commented 11 months ago
transformIgnorePatterns: [
  "/node_modules/(?!vanilla-jsoneditor)",
]

But this was needed to make the library work in Jest. So I do think Jest needs to transform ESM modules into CJS. Though I am not sure I understand correctly.

josdejong commented 11 months ago

Good to hear you found the cause! Thanks for sharing.

But this was needed to make the library work in Jest. So I do think Jest needs to transform ESM modules into CJS. Though I am not sure I understand correctly.

Hm I don't know either. If there is anything we can do to make usage of vanilla-jsoneditor easier in Jest or other environments please let me know.