There’s been a trend I have been seeing around the front end world where folks are switching their test suites to use Jest over something like Karma and Mocha. Usually the main benefit that’s touted is speed 🏎💨
What’s not commonly talked about is the the trade-off you’re making here — you’re no longer testing in an environment any users actually use. You can’t test in Safari, Chrome, Edge, or Firefox anymore. You’re running your tests in JSDOM, which is an implementation of the DOM spec. I don’t see this being any better than something like PhantomJS (RIP in peace). Cross browser bugs exist, and the DOM is not just an implementation detail.
Don’t get me wrong, Jest is a really nice test runner. There’s a whole lot to love about it. Which is why I have a vested interest in getting it to run inside of a real browser. But the speed boost you get from running your tests in the JSDOM is not worth the trade-off you’re making, imo.
Best of both worlds
It’s totally possible to have blazing fast component unit tests that fully mount into the DOM inside of a real browser. How fast? How about 661 tests that complete in 17 seconds? Here’s your proof. With compiling everything and launching the browser the total time is 51 seconds. Here’s the source of the repo that those tests are coming from.
Karma isn’t slow. The real DOM isn’t slow as you think it is. It’s probably the tools you picked to help write those tests. The example I mentioned above that runs so fast uses a package called Interactor.js. Interactor.js is a composable, immutable, asynchronous way to interact with components or applications like a user would. From the introduction in the docs:
Interactors work anywhere there is DOM, and run alongside your tests to produce blazingly fast results. They automatically wait for elements to exist in the DOM before interacting with them and also provide a simple interface for making asynchronous assertions against the DOM as well.
Not only are those tests extremely fast with Interactor.js, it carries many benefits with no trade offs like JSDOM does (and is faster). You’re testing in real browsers while actually interacting with the DOM like a user would in real life.
Combine Interactor.js with something like testing-hooks or dom-testing-library to mount the components into the DOM and you have a seriously powerful combo! Imagine this example that completes in less than a second:
This is only scratching the surface of the possibilities that Interactor.js unlocks. I think it would be worth taking a look before moving your tests over to Jest (or JSDOM).