Open Swivelgames opened 3 years ago
Please see our docs: current limitations.
We do not (yet?) support ESModules in watch
mode. Node's ESM implementation is using its separate cache (not require.cache
), which currently can't be cleared before re-running the tests in watch
mode.
@Swivelgames Have you tried --parallel
combined with --watch
? It might work, since we dump the workers after each run, but I don't think we are testing it anywhere yet.
@boneskull I'm not @Swivelgames but your suggestion of adding --parallel works for me. Thanks!
To support ESM in watch mode, I think you will need to implement your own ESM loader hook. It can append query params to each imported module, effectively making them unique. By appending a different query param the second time, you can ensure a fresh copy of the module is imported. This may, however, be a memory leak, if node has no way to clear the previously-imported copies of those modules.
It is probably worth sharing this use-case with the node maintainers so they can add the necessary API surface to node.
https://github.com/nodejs/modules/issues
EDIT: I see this was already raised with the node team: https://github.com/nodejs/node/issues/49442
Well I've "fixed" my issue by switching to jest... Very happy about the change so far.
@djfm that's funny, as I've switched from Jest to Mocha using testdouble.js
I had a nightmare of a time getting Jest and ESM mocking to work: https://github.com/facebook/jest/issues/10025#issuecomment-921942214
Based on the comment of @cspotcode and the experiment by @vsnthdev in https://github.com/nodejs/node/issues/49442, I've gone ahead and implemented this as a proof of concept for mocha --watch
, and it does indeed seem to work:
https://github.com/lehni/mocha/commit/99d5a14d3a1b11f81dbb08e1895d43061e7b0541
To run mocha in this mode, you simply pass the --esm
option along with --watch
. Without --esm
, nothing changes.
This may not be ready for primetime yet, but it works well for my use-case and it shows a viable path forward for ESM.
Perhaps it can be wrapped up for release?
I've just made my branch work for NPM installs, so if you want to test the esm watch mode in your project, you can replace the mocha dependency:
yarn add -D mocha@https://github.com/lehni/mocha#99d5a14d3a1b11f81dbb08e1895d43061e7b0541
# Or:
npm install -D https://github.com/lehni/mocha#99d5a14d3a1b11f81dbb08e1895d43061e7b0541
And after that, simply run your test command with --watch --esm
:
yarn test --watch --esm
Please let me know how this is working for you!
I've added auto-detection of esm watch mode now, so the --esm
argument is not required anymore:
https://github.com/lehni/mocha/commit/64c5fcc79ce4f2232b0450db2a7f5e87e0f538a7
Just fyi as of May 2022 this is still an open issue and quite a significant impediment.
As an interim workaround I ended up with nodemon in front of Mocha, which works flawlessly and doesn't have a memleak issue mentioned in the PR π.
As a reference, here's the nodemon.test.json
that works for me (I'm using TypeScript, hence out
dir):
{
"exec": "npx mocha --node-option=experimental-network-imports",
"watch": [
"./out/**/*"
],
"delay": 100,
"env": {
"NODE_ENV": "test"
}
}
Possible workaround, using fswatch:
fswatch lib/ test/ --event Updated | xargs -I _ mocha test/file.js -b
Having to use
"test-watch":"nodemon --exec mocha spec",
in package.json scripts
is a workaround, but it'd be better if it Just Worked
Another simple workaround is to use entr to watch your source files:
{
"scripts": {
"test:watch": "ls lib/*.js | entr -r mocha"
}
}
I've tried @boneskull solution and combined the --parallel
with --watch
flag. It worked for me.
Here is the part of my package.json
scripts
section
"test:watch": "mocha --watch --parallel --slow 100"
I found one pretty simple solution for typescript and esm. I use tsx
in mocha config file. Post here. Now mocha works with simple script "test:watch": "mocha --watch"
This is now possible using a new flag from node 22. This should work:
mocha --watch --experimental-require-module
Here is the person who found the "fix" https://joyeecheung.github.io/blog/2024/03/18/require-esm-in-node-js/
The docs https://nodejs.org/api/modules.html#loading-ecmascript-modules-using-require
Here is where I first saw the merge https://github.com/nodejs/node/pull/51977#issuecomment-2093972575
Prerequisites
faq
labelnode node_modules/.bin/mocha --version
(Local) andmocha --version
(Global). We recommend that you not install Mocha globally.Description
When running
--watch
within a package that has"type": "module"
set in itspackage.json
, Mocha fails to properlyimport
, instead attempting torequire()
the file.Steps to Reproduce
For convenience, the following respository was created that adequately reproduces the issue:
npm i
npm run test-mocha
npm run test-mocha:watch
Expected Behavior:
Actual Behavior:
Versions
Package Versions
Environment
Additional Information
It is my understanding that the following scenarios are applicable:
import
should be used under the following conditions:package.json
file contains"type": "module"
and its file extension is.js
.mjs
, regardless of what is inside its associatedpackage.json
filerequire()
should be used under the following conditions:package.json
file does NOT contain"type": "module"
and its file extension is.js
.cjs
, regardless of what is inside its associatedpackage.json
fileConclusion
Presently, it appears as though
--watch
is assuming the target file is a CommonJS module when its extension is.js
, and failing to yield to itspackage.json
file's"type": "module"
.Considerations
It's worth considering the fact that the
package.json
file associated with the file being imported may be different than thepackage.json
in the directory that mocha is being called, even in the event that the target file's path does not includenode_modules
.