If you've ever run a script like npm run test from your package.json:
{
"scripts": {
"test": "node --test src/**/*.test.js"
}
}You'll notice we are using a globstar here src/**/*.test.js.
The thing is, on Linux, npm run runs scripts with sh by default.
By default, sh doesn't support globstar paths like **/*. So you'll notice that it'll only find files one directory deep, and will treat src/**/*.test.js as if you only wrote src/*/*.test.js.
This is a major pitfall that can easily go by undetected. For example, imagine your CI skipping 90% of your tests since it was looking at only some of the directories!
β οΈ NOTE: This was only tested on Linux, and was not tested on Windows or Mac.
To fix this, figure out how to enable globstar in your shell. Or do what I did and just update npm to use zsh as the default shell for running scripts.
Unlike sh, zsh understands and expands globstar paths by default.
Here's how to do that:
- First run
npm config ls -l | grep shellto see what config you have. It'll probably say:
script-shell = null
shell = "/bin/bash"
-
Now, run
npm config set script-shell=zshto update thescript-shelloption to usezsh. -
Confirm that the update worked. Run
npm config ls -l | grep shell. It'll probably say:
; script-shell = null ; overridden by user
shell = "/bin/bash"
script-shell = "zsh"
- Now, try using globstar paths again in your scripts. All the matching files should be discovered now by the shell (even several subdirectories deep).
You're all set! π
The problem now is... remembering to do this everywhere you use npm. π’
(GitHub Codespaces, other laptop, work computer..................)
By the way, many tools that you would use within
npm runscripts, likemocha, support quoting the globstar in the script, like'src/**/*.test.js', in which case they will perform the globstar matching for you, not relying on the shell you are using. This is a great solution! Use this wherever possible.Unfortunately, some tools don't support this yet, like the native Node.js v20 test runner
node --test. When Node.js supports this, likenode --test 'src/**/*.test.js', I won't really need this hack anymore!
Interesting! So I ran some tests and
shaliases to bash on my Linux system. Bash doesn't support globstars by default but in any modern version you can enable support withshopt -s globstarwhich resolves this problem. This may be a better solution since it doesn't introduce any other potential changes that might be experienced moving to another shell.