Skip to main content

Jest 25: 🚀 Laying foundations for the future

· 7 min read

Jest 25 is laying the groundwork for many major changes in the future. As such, we kept breaking changes to a minimum, but internal architecture changes may require attention during the upgrade. The main changes are an upgrade of JSDOM from v11 to v15, 10-15% faster test runs, a new diff view for outdated snapshots and dropped Node 6 support.

There has been more than 200 commits since Jest 24.9 by more than 80 different contributors, so as always, take a look at the changelog for a full list of changes.

Bye Node 6

Node 6 has been EOL since April 30th 2019, and Jest 25 leaves it behind. Dropping Node 6 means we can upgrade our dependencies, the main one being JSDOM, which has been upgraded to version 15. Upgrading also means we no longer have to transpile async-await syntax, which results in both faster code execution and less memory consumption. As a bonus, Jest’s transpiled code should be easier to debug if anyone finds themselves tumbling down that particular rabbit hole.

Even though Node 8 has also entered EOL, Jest 25 will keep support for it to make the upgrade as easy as possible for those of us who still support Node 8. It does come with some tradeoffs though, such as JSDOM v16 having been released without Node 8 support, so you'll need to use jest-environment-jsdom-sixteen if you want to use the latest version.

Performance improvements

We’ve gotten reports that Jest has slowed down over the last couple of releases. Jest 25 includes upgraded Micromatch, which brings huge gains in startup time, and some bug fixes and performance tweaks which brings Jest back to the speed it was at for Jest 23. For Jest itself, like mentioned at the beginning of this post, that means a 10-15% reduction of test runtime. We're always looking to improve here of course, so please check how it stacks up against earlier versions and create issues if we should be better!

V8 Code Coverage

Jest’s current code coverage instrumentation is powered by babel-plugin-istanbul inserting code coverage collection code before creating reports. However, this is quite slow and memory-intensive, especially for large files and code bases. Luckily, V8 has built-in code coverage, which is becoming more and more usable in Node thanks to the hard work of Benjamin Coe and others on the V8 and Node.js teams. Jest 25 comes with experimental support for this via a new --coverage-provider flag. Please see its documentation for caveats and how to use it.

Thinking fast and slow when tests fail

Unnecessary effort to interpret the reports when tests fail hinders:

  • “thinking fast” to recognize patterns from your past experience
  • “thinking slow” to analyze changes and decide whether they are expected progress or unexpected regressions

Jest 25 completes the second half of an effort begun in Jest 24 to improve all matchers:

  • correct description line, including .rejects, .resolves, and .not modifiers
  • concise labels and consistent alignment for expected and received values
  • inverse highlight of substring differences when expected and received are strings
  • counts of change lines in differences to know if they are only delete or insert

Special thanks to Jest maintainer Mark Pedrotti for driving this effort and his continued work towards making expectation errors as good as they can be.

Colors of differences when snapshot tests fail

The most obvious change to replace confusion with confidence is the colors of change lines in differences when snapshot tests fail:

  • - Snapshot changes from green to magenta
  • + Received changes from red to teal foreground on cyan/aqua background

Examples of snapshot test reports (before at left and after at right)

  1. Counts of changed lines confirm your first impression which way did the snapshot change (that is, deleted or inserted lines)

snapshot-insert-lines

  1. Background colors attract your eyes to compare adjacent changed lines

snapshot-change-lines

  1. Background colors also help you see which toThrow tests require a decision whether or not to update the snapshot

snapshot-change-substrings

Here are some reasons why we chose unique colors:

  • The 95% of people who have full color vision can quickly recognize which reports are from snapshot tests versus all other matchers.
  • It solves the direct conflict between meaning of green/red in Jest tests versus red/green in code review.
  • Unlike a reversal to red/green which suggests that update is the default decision, it suggests that differences require more careful review for possible regression in local snapshot test failures than in code review (when problems have already been fixed).

The difference in hue from magenta at 300° to teal/cyan/aqua at 180° gives better color vision accessibility and the light background tint for changed lines gives consistent contrast on light and dark themes.

If you maintain a command line tool, you might find inspiration to improve its accessibility in #9132.

ECMAScript Modules support

Node 13 has unflagged ESM support, and we have started a tiny bit working towards native support in Jest. Jest 25 includes support for jest.config.cjs and jest.config.mjs configuration files, but tests themselves cannot yet be written using ESM without something like Babel or TypeScript transforming it into CJS.

The APIs Jest will use are still flagged and experimental, so don't expect support right away. These APIs are something the Node.js Modules team is actively working on, and we'll be keeping an eye on it moving forward and experiment with them so we can provide feedback. You can subscribe to this issue to get any updates about the implementation status in Jest.

Other improvements and updates

  • Jest has passed 1000 unique contributors. This is an incredible milestone! Thank you to everybody who helps us make testing as delightful as possible.
  • Thanks to community member Josh Rosenstein, Jest now comes with support for BigInt in most matchers, such as toBeGreaterThan. Jest will also understand bigint literals out of the box.
  • Jest’s feature --detect-leaks has been broken for Node 12 and newer - this has been fixed in Jest 25.
  • As announced in the blog post for Jest 24, Jest’s code base has been rewritten in TypeScript - this work was completed in Jest 24.3. So if you use any of Jest’s individual parts, you should get great IDE integration. Looking forward, we really want to make Jest mocks play nicer with type systems, and we’d love the community’s help with this. Please chime in here with ideas and send PRs! We’ll also be investigating moving the typings for using Jest as a test runner from DefinitelyTyped into Jest itself.
  • The jest-diff package now exports functions like diffLinesUnified and diffStringsUnified which have configuration options, so other applications can format differences in a custom way. For more information and code examples, see its new README.md file in the Jest repository or on package repositories.
  • Thanks to community member Wei An Yen, Jest will no longer highlight passing asymmetric matchers in expectation errors. This has been a long-standing pain point with asymmetric matchers and we're very happy it's finally solved.
  • For the second year running, Jest won the Highest Satisfaction award from State of JS. We are incredibly grateful for the support from the community, and hope we can build on this momentum to make 2020 even better!

Plans for the future

  • Jest’s configuration is vast and somewhat clunky - there is often at least two ways of doing the same thing, oftentimes even more. For Jest 26 we hope to condense the config down, and make it more predictable. See this issue for details.
  • We also hope to be able to provide a proper programmatic API for running Jest, to make integration into IDEs and other tooling easier. Please see this tracking issue.
  • There’s been an open PR for adding Lolex as an implementation of Jest’s fake timers since December 2017. While we’re not adding it to any public APIs in Jest 25, support for it is technically included and you we're looking into how to expose this so people can test and experiment with it. Using it means you can mock out Date and other timer function Jest currently doesn’t touch. Note that this should be considered experimental, and a proper API support will come in a later release. Follow this PR for the latest updates on the status.

Happy Jesting! 🃏