blog podcast

Windows, NPM and Me

When I left Windows many years ago and instead started to work myself into the Linux eco-system, one of the things I would miss was that whereas in Windows some problems were easily solvable by running a .msi file, in Linux the corresponding problem could send you deeper and deeper down a rabbit hole. I had the feeling that most software at the time were designed for Windows and that Linux had to squeeze their way in by trying to backward engineer whatever Windows was doing.

Time passes and now I’m back to using Windows for a contract. It’s curious then suddenly to find that the feeling of endless Odyssey I’d involuntarily would experience in Linux , now suddenly is to be found also in Windows. I think that in the time that has passed since I left Windows, the revolution of DevOps has started made Linux and Mac OSX drive when it comes to innovation in certain sectors of software engineering.

So this is the story of when I wanted to use npm to run some tests and to my dismay find that it simply didn’t work.

Now npm (the package manager for NodeJS) is a pretty widely adopted thing, finding it not being able to perform such basic tasks as running jest was definitely a surprise. It was an even bigger surprise for me to see that this problem wasn’t really discussed much on the internet. Either no one using Windows are using npm (that would be pretty wild) or, I was thinking to myself, I’ve unwittingly past my computer into the twilight zone.

Now unlike Linux where you can go in everywhere and change whatever text files you want to see chaos wreck havoc on your system, Windows as more conservative, it’s not an OS that invites you to do weird things. Still, I know from experience that if internet isn’t talking about your problem, then you’ve really managed to do something unique.

So my problem was I would write npm test (with the test script set to run jest), I would have jest installed as a dev dependency but my command line would just spit out:

'jest' is not recognized as an internal or external command, operable program or batch file

I ended up on an adventure of sorts. I found that when you execute a script with npm (you execute npm run ...) it will look in your node_modules/.bin folder to find what to execute. I also found that in Windows it uses an environment variable called ComSpec to know which command line interpreter to use. By default this is CMD. Furthermore, CMD uses the environment variable PathExt to know which file extensions it should automatically find as executable. For example if you have a file called program.exe you can launch it by just running program in CMD. This is because the file extension .exe is in PathExt.

I would look in my node_modules/.bin and see that jest indeed was there. I was puzzled. I got my break when I realized that running jest.cmd worked. It turned out that by default windows CMD runs case-insensitive. For this reason for example PathExt has all of it’s extensions written in upper case letters (come to think of it, having them lowercase would have made more sense). In my case my folder had been made case sensitive. For this reason CMD, that was looking for jest.CMD didn’t find any jest.

So what was the fix? Well it’s a matter of taste. Either one can add .cmd (lowercase) to the list of allowed extensions, or one could make the folder case-insensitive again (which might be tricky if you are depending on modern DevOps tools like Docker). Or you could change ComSpec to point to Git Bash instead, which is able to understand normal bash and hence execute the jest file that also exists and is used by linux / mac. Whatever you happen to do, remember that the next person working in your repository is likely to have the same issue.