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

Jasmine loads test dependency as CommonJS module instead of ESM #191

Closed
mdreier-sap opened this issue Jan 13, 2022 · 2 comments
Closed

Jasmine loads test dependency as CommonJS module instead of ESM #191

mdreier-sap opened this issue Jan 13, 2022 · 2 comments

Comments

@mdreier-sap
Copy link

I have a project which uses ES modules and tests using Jasmine. In my tests, I am using fetch-mock to mock web requests. When running the tests, I get the following error:

PS C:\dev\git\jasmine-esm-bug> npm test

> jasmine-esm-bug@1.0.0 test
> node ./spec/support/jasmine.js

C:\dev\git\jasmine-esm-bug\node_modules\fetch-mock\cjs\server.js:9
        fetch = require('node-fetch');
         ^

Error [ERR_REQUIRE_ESM]: require() of ES Module C:\dev\git\jasmine-esm-bug\node_modules\node-fetch\src\index.js from C:\dev\git\jasmine-esm-bug\node_modules\fetch-mock\cjs\server.js not supported.
Instead change the require of index.js in C:\dev\git\jasmine-esm-bug\node_modules\fetch-mock\cjs\server.js to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (C:\dev\git\jasmine-esm-bug\node_modules\fetch-mock\cjs\server.js:9:10)
    at async Promise.all (index 0)
    at async Jasmine._loadFiles (C:\dev\git\jasmine-esm-bug\node_modules\jasmine\lib\jasmine.js:215:5)
    at async Jasmine.loadSpecs (C:\dev\git\jasmine-esm-bug\node_modules\jasmine\lib\jasmine.js:206:3)
    at async Jasmine.execute (C:\dev\git\jasmine-esm-bug\node_modules\jasmine\lib\jasmine.js:502:3) {
  code: 'ERR_REQUIRE_ESM'
}

It seems that instead of loading fetch-mock as an ES module, it is loaded as a CommonJS module (it contains both). For running the binary, I could understand that (since Jasmine does not set "type": "module" in package.json). However I would expect it to work when running from my own script. And of course best case also running the binary should work directly.

Versions:

  • jasmine: 4.0.2
  • node: 16.13.2
  • fetch-mock: 9.11.0
  • OS: Windows 10

To help with analysis, I created a small project which reproduces the issue: https://github.com/mdreier-work/jasmine-esm-bug

You can clone and npm install, then reproduce the issue with either of the following commands:

  • npm test (running /spec/support/jasmine.js
  • npx jasmine (running the Jasmine binary)
@sgravrock
Copy link
Member

Thanks for the minimal reproduction. That was very helpful.

I think this is a problem with fetch-mock. The first things that jumped out at me are that it's your code rather than Jasmine that imports fetch-mock, and that your code looks fine. I was able to reproduce the problem with a simple test file I added to your repo, without using Jasmine at all:

% cat test.js 
import 'fetch-mock';
console.log('ok');

% node test.js 
internal/process/esm_loader.js:74
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /private/tmp/jasmine-esm-bug/node_modules/node-fetch/src/index.js
require() of ES modules is not supported.
require() of /private/tmp/jasmine-esm-bug/node_modules/node-fetch/src/index.js from /private/tmp/jasmine-esm-bug/node_modules/fetch-mock/cjs/server.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /private/tmp/jasmine-esm-bug/node_modules/node-fetch/package.json.

    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1015:13)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Module.require (internal/modules/cjs/loader.js:887:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (/private/tmp/jasmine-esm-bug/node_modules/fetch-mock/cjs/server.js:10:10)
    at Module._compile (internal/modules/cjs/loader.js:999:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14) {
  code: 'ERR_REQUIRE_ESM'
}

I was also able to reproduce the error in a pure CommonJS project.

I think there are two things going on here:

  1. Whatever fetch-mock is doing to support separate ESM and CommonJS entry points isn't working. The CommonJS entry point loads even in an ESM environment.
  2. The direct cause of the error is that fetch-mock isn't compatible with the version of node-fetch that you're using.

It looks like you'll have to downgrade node-fetch to a compatible version if you want to use fetch-mock.

@mdreier-sap
Copy link
Author

Good catch on the unsupported version, I totally missed that.

Downgrading node-fetch to version 2.6.6 (and @types/node-fetch to 2.5.12) solves the issue. I will therefor close the issue (and hope that fetch-mock will add support for newer node-fetch versions sometime in the future).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants