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…
-
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",
-
Try this debugging procedure
- 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 - Execute the
npm run debug
command on your OS command-line - Fire up Chrome and hit
chrome://inspect
- Pick your debuggable app instance by clicking its link
- The Jest runner will stop at the beginning.
- Hit play to begin running tests
- Your test will stop on the breakpoints you’ve set.
- Add a breakpoint in your test or runtime code with the
Resources
- Here’s the article on Yarn with transitive dependencies that got me going again.
- This post listed a few different scenarios for working with npm locks and shrinkwraps but none of them worked well for me. Your mileage may vary.
- See this stackoverflow post for details on the error and one potential solution (didn’t work for me)…
- The create-react-app project that I use as a seed for my React training examples app
- Github Developer Timer’s post on how to get debugging working with Jest in CRA rocks my world!
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