mochajs / mocha

☕️ simple, flexible, fun javascript test framework for node.js & the browser
https://mochajs.org
MIT License
22.59k stars 3.01k forks source link

Mocha fails to reload watched files #4016

Open geigerzaehler opened 5 years ago

geigerzaehler commented 5 years ago

Under certain circumstances Mocha fails to reload source files in watch mode. Specifically, if a file is watched and modified but only required by a file that is not watched then the modified file is not reloaded and the change is not visible to the test suite.

This issue can be addressed by adding the unwatched files to --watch-files

Steps to Reproduce

Create the following three files

// lib-a/index.js
module.exports = true
// lib-b/index.js
module.exports = require('../lib-a')
// test/main.js
const assert = require('assert')
const value = require('../lib-b')
it('works', function () {
  assert(value)
})

Now run

mocha --watch --watch-files lib-a,test

The test suite passes.

Now modify lib-a/index.js so that the exported value is false. This will retrigger the tests but they will still succeed.

If lib-b is add to the --watch-files list then the modification results in a test failure.

MasonRhodesDev commented 5 years ago

I was able to reproduce with the steps above, and this is the same issue I am experiencing in my own project. In my specific case I am testing services that connect to mongodb through mongoose models. Hence the import chain. test file -> roles.service -> roles.model

The solution above does work for my tests but anything accessed via the recursive flag still experiences the issue.

For example if you add to the repro project above

// lib-c/lib-c-1/index.js
module.exports = true
// test/lib-c/index.js
const assert = require('assert')
const value = require('../../lib-c/lib-c-1')

it('lib-c-1 works', function() {
  assert(value)
})

You could reproduce the work around with mocha --watch --watch-files lib-a,lib-b,lib-c/lib-c-1,test --file ./test/lib-c which obviously get more and more clunky more files you add.

While you can run --recursive it still requires you add watch files to list which defeats the purpose of running tests recursively with watch at all, making the two flags a bit incompatible.

(edit: add my "solution") My personal workaround is using yarn test just runs mocha with any setup vars if necessary.

# .bashrc
testing() {
  yarn test "$@"
  while inotifywait -qqre modify "./"; do
    yarn test "$@"
  done
}

in the project I'm working on to get around the --watch-files flag for now and allow me to use the recursive flag. But this same solution doesn't help any of my Windows devs.

geigerzaehler commented 5 years ago

Have you tried using --watch-files .? This will watch all files in the current directory but still ignore .git and node_modules. Also note that --recursive is intended to have no effect on which files are watched. It is only for test file collection.

MasonRhodesDev commented 5 years ago

Hmm. In the test project it seems to work, but in my project there still seems to be an issue. Give me a bit to try and figure out a better way to reproduce

MasonRhodesDev commented 5 years ago

ok, so as I briefly mentioned before, we are using the mongoose package to register models. The code we are currently testing is heavily reliant on those models. And if you've ever used mongoose you'll know that models get registered on to the global mongoose object.

We were using

module.exports =
    mongoose.models.organizational_units ||
    mongoose.model(`organizational_units`, schema)

to get around an issue where the models would throw if they were already defined. (ie. everytime a file changed)

The solution I came up with is to set the global register to undefined before registering

mongoose.models.roles = undefined
module.exports = mongoose.model(`roles`, schema)

The side effect of my original solution was that changes to the model between test refresh were getting ignored since the model already existed.

Feel free to close this, not a bug in mocha, this was a bug on my end.

Thanks for all the help!

geigerzaehler commented 5 years ago

@solaris765 glad it worked out. I’ll keep this bug open because it is indeed an issue albeit not related to your case.

JoshuaKGoldberg commented 9 months ago

I can confirm this is still an issue in Mocha 10.2.0. I posted a standalone repro branch here: https://github.com/JoshuaKGoldberg/repros/tree/mocha-watchfile-updates