Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Unexpected token 'export' with Jest (on Cloudflare Workers) #678

Open
2 tasks done
AlexErrant opened this issue Jan 13, 2023 · 11 comments
Open
2 tasks done

[BUG] Unexpected token 'export' with Jest (on Cloudflare Workers) #678

AlexErrant opened this issue Jan 13, 2023 · 11 comments
Labels
bug stale-exempt Exempts issue from being marked as stale

Comments

@AlexErrant
Copy link

AlexErrant commented Jan 13, 2023

Before you begin...

  • I have searched the existing issues
  • I am not using version 13.x of node (if so, please upgrade)

Description of the problem

This issue is very similar to #451 - except I'm on v9 of this library, which is supposed to fix this issue. I'm also on Jest v29.3.1. I'm also also using Cloudflare workers - but I'm not sure how that influences this problem. The moduleNameMapper workaround still works.

Stacktrace:

 C:\Code\miniflare-typescript-esbuild-jest\node_modules\uuid\dist\esm-browser\index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { default as v1 } from './v1.js';
                                                                                      ^^^^^^

    SyntaxError: Unexpected token 'export'

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1449:14)
          at async Promise.all (index 0)

Recipe for reproducing

I made three small commits off the official cloudflare+jest example repo here which demonstrates the problem.

Environment

System:
OS: Windows 10 10.0.19045
CPU: (12) x64 Intel(R) Core(TM) i7-10850H CPU @ 2.70GHz
Memory: 12.58 GB / 63.73 GB
Binaries:
Node: 18.12.1 - C:\Program Files\nodejs\node.EXE
Yarn: 1.22.19 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
npm: 8.19.2 - C:\Program Files\nodejs\npm.CMD
Browsers:
Edge: Spartan (44.19041.1266.0), Chromium (108.0.1462.76)
Internet Explorer: 11.0.19041.1566
npmPackages:
@cloudflare/workers-types: ^3.11.0 => 3.11.0
@types/jest: 29.2.5 => 29.2.5
@types/uuid: ^9.0.0 => 9.0.0
esbuild: ^0.14.41 => 0.14.41
jest: 29.3.1 => 29.3.1
jest-environment-miniflare: ^2.5.0 => 2.5.0
miniflare: ^2.5.0 => 2.5.0
prettier: ^2.6.2 => 2.6.2
ts-jest: 29.0.4 => 29.0.4
typescript: ^4.7.2 => 4.7.2
uuid: ^9.0.0 => 9.0.0
wrangler: ^2.0.7 => 2.0.7

@AlexErrant AlexErrant added the bug label Jan 13, 2023
@tomi-bigpi
Copy link

tomi-bigpi commented Jan 26, 2023

I think this is due to a missing "type": "module" in package.json. However, adding that has other side effects in the repo, so using explicit .cjs and .mjs file extensions should be more robust across all the various use cases. https://nodejs.org/api/packages.html#dual-commonjses-module-packages has some good details. If I can spare the time, I may try to put together a PR with those changes, unless other fixes are already planned?

EDIT: I had a quick look and there are a lot of side effects in the project from adding "type": "module" which quickly spiraled into making sure Common JS files have a .cjs extension etc. which had a lot of downstream implications that I don't have time to sort out (nor have enough context to not break the various consumers out there). We'll locally patch package.json in our project for the time being to be able to move forward.

@cdauth
Copy link

cdauth commented Mar 6, 2023

The problem seems to be that Jest resolves the main file by using the exports['.'].browser.import property in the package.json of uuid, but that file is interpreted as CommonJS despite containing ESM code. This can be solved by renaming it to .mjs, which I have documented in #692.

As a workaround, I specified this in my Jest config:

   moduleNameMapper: {
        '^uuid$': '<rootDir>/node_modules/uuid/wrapper.mjs'
    }

@slhck
Copy link

slhck commented Mar 15, 2023

Hmm, even when doing this, I get:

    Details:

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

    SyntaxError: Cannot use import statement outside a module

I use:

  "jest": {
    "preset": "ts-jest",
    "setupFiles": [],
    "testEnvironment": "node",
    "testMatch": [
      "**/test/*.test.ts"
    ],
    "moduleNameMapper": {
      "^uuid$": "<rootDir>/node_modules/uuid/wrapper.mjs"
    }
  },

@cdauth
Copy link

cdauth commented Mar 15, 2023

Hm, it sounds pretty unusual that your setup would specifically pick the MJS file but then interpret it as CJS. But then in your case I guess the require.resolve() workaround or using "^uuid$": "<rootDir>/node_modules/uuid/dist/index.js" would be the right workaround.

Personally I am using Jest in an ESM project, so I am using the ts-jest ESM setup. So I'm using the preset ts-jest/presets/default-esm, have the ts-jest useESM global set to true and run Jest using NODE_OPTIONS=--experimental-vm-modules jest. There I cannot use require.resolve(), and importing CJS files brings lots of trouble.

@slhck
Copy link

slhck commented Mar 15, 2023

Ah, maybe it is because this is not an ESM project to begin with. I have another ESM project where I can run tests without issues, but I cannot migrate this project to ESM (yet).

Edit: FWIW, I vendored the dependency, as I only needed parts of the package.

@github-actions
Copy link

Marking as stale due to 90 days with no activity.

@github-actions github-actions bot added the stale label Jun 14, 2023
@AlexErrant
Copy link
Author

Go away stalebot.

@zhouyali
Copy link

zhouyali commented Jan 23, 2024

'^uuid$': '<rootDir>/node_modules/uuid/wrapper.mjs'

I tried this config, and It cause another problem ’RangeError: Maximum call stack size exceeded‘

@zhouyali
Copy link

111

@stoutatnerdery
Copy link

@zhouyali this worked for me: uuid: require.resolve('uuid'),

@bjmc
Copy link

bjmc commented Mar 15, 2024

Hello, we're seeing (I believe) this same problem.

I tried to apply the moduleNameMapper workaround described above but then I wind up with a different error:

Must use import to load ES Module: /home/bjmc/Sandbox/ska-oso-odt-ui/node_modules/uuid/wrapper.mjs

FWIW, we are not using/importing uuid directly: one of our dependencies is including it.

Any advice or suggestions would be greatly appreciated! Should we be adopting ts-jest (as mentioned by @cdauth) if we're testing a React/Typescript project?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug stale-exempt Exempts issue from being marked as stale
Projects
None yet
Development

No branches or pull requests

8 participants