How to fix broken Jest in React 16.4.1 with CRA and debug your jest tests!

by
Tags: , , , ,
Category:

Once I upgraded to React 16.4.1 using Create React App for my training course, my Jest tests failed with a strange error:

TypeError: environment.setup is not a function

Reading through a small number of posts with the same error led me to believe it was a problem with Enzyme, since that was one area where this specific error was reported and the symptoms looked the same. But I was wrong, wrong, wrong.

Turns out it’s something with the react-scripts portion of create-react-app being out of date on its version of the Jest Testing API. I upgraded jest by hand first in node_modules/react-scripts/package.json to the latest version (23.3.0), and my bug went away. Obviously since I don’t check in node_modules, that approach is not going to work.

So, then I researched the status of react-scripts / create-react-app. Seems like development of the (production) 1.1.x branch has stalled since April, and they’ve been building a ‘@next’ line for 2.x which does use the more modern APIs. The 2.x line actually installs a more recent version of Jest, which works. But it’s not a panacea…

I tried upgrading react-scripts, to the 2.0.0 line, and the test framework started working again. Productivity! But this, too is problematic, because now I’m relying on nightly commits, perhaps betas, until they get their 2.x code line released. Even worse, I started to get random errors when starting the application. Of course, this was after hours of productivity writing/debugging Redux action tests (blog forthcoming). Sigh, there must be a better way to fix this.

On a related note, this is a perfect example of why using a federation of many different APIs moving at different speeds can be a real challenge. If you put the app down for a year and then try to update your handcrafted platform, lots of things might be out of sync, might go dark, or might be fine. You never really know. Angular tries to keep the entire core, including testing, vetted on one version, which I think is superior for enterprise development. But then you may not want a heavy set of APIs telling you how to run your development. Decisions, decisions.

Using Yarn and the “resolutions” section of package.json FOR THE WIN!

The Yarn tool, a replacement for npm from Facebook, deals with this problem rather nicely. There are standard Node alternatives, such as creating/editing NPM Shrinkwrap or editing package-lock.json, but that way be dragons… You’ll be wading in large lock files, and a new npm install could zap the entries, bringing you back to despair.

Instead, I switched over to Yarn. Add a “resolutions” section to package.json and let it override the sub-dependency. Here’s what I used:

  "resolutions": {
    "react-scripts/jest": "23.3.0"
  },

That added code in package.json says that the transitive dependency on jest from react-scripts should use version 23.3.0 instead of whatever version it has listed. Now, if your API breaks because of the new library, that’s your problem. But for me, I could now both test my code using the latest jest API with react-scripts and run the WebPack server, too.

Installing Yarn globally is a simple task:

npm install -g yarn

Yarn can be used like npm, but the syntax is ever so slightly different. For example, npm run test is just npm test. Get the docs and learn the commands. You’ll be rewarded with faster builds and some additional features.

Once you’ve edited the config and installed Yarn, delete package-lock.json, remove the node_modules directory, and if you’ve been using Yarn before this, yarn.lock. Do yarn install and watch it build. You may get some warnings about the versions of jest not being compatible, but it will install it anyway. And the good news is that it doesn’t seem to pose a problem for me in my case. For minor version patches, this is just the thing to use.

BONUS! Debugging React Jest tests from Chrome

And now, here’s how to debug your Jest tests from Chrome. See resources below for the citation from Stack Overflow that helped me here…

  1. Add an entry to your scripts section for debugging alongside your “test” entry:

    "debug": "node node_modules/.bin/react-scripts --inspect-brk test --env=jsdom --runInBand",
  2. Try this debugging procedure

    1. Add a breakpoint in your test or runtime code with the debugger; statement; this is where the debugger will stop once you begin your session
    2. Execute the npm run debug command on your OS command-line
    3. Fire up Chrome and hit chrome://inspect
    4. Pick your debuggable app instance by clicking its link
    5. The Jest runner will stop at the beginning.
    6. Hit play to begin running tests
    7. Your test will stop on the breakpoints you’ve set.

Resources

Happy hacking, and warning: you’re dealing with a beta of create-react-app’s scripts by doing this, so maybe do this in a throwaway branch until they release 2.x in the Fall of 2018 or so…

Ken