Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Jest 26 blog post #9950

Merged
merged 18 commits into from
May 5, 2020
Merged
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions website/blog/2020-05-06-jest-26.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
title: Jest 26: Tick Tock
cpojer marked this conversation as resolved.
Show resolved Hide resolved
author: Christoph Nakazawa
authorURL: http://twitter.com/cpojer
authorFBID: 100000023028168
---

# Jest 26: Tick Tock

When we started rebuilding Jest five years ago our goal was to provide a batteries-included zero-configuration test runner that is approachable for beginners, extensible for almost all testing use cases and scalable to large projects. One of the most important releases was [Jest 15](https://jestjs.io/blog/2016/09/01/jest-15) which tied all the bits and pieces together and provided great defaults that allowed people to install and run Jest often without any setup. However, this approach has a big downside as Jest installs a lot of dependencies into your projects that you may not need.

We are now beginning to address this shortcoming and are working on reducing Jest’s install size while keeping it approachable and extensible. We have made the following breaking changes in Jest 26:

<!--truncate-->

- `[expect, jest-mock, pretty-format]` Remove `ES5` build files with a new minimum of support of ES2015 (Node 8) which were only used for browser builds ([#9945](https://github.com/facebook/jest/pull/9945))
- `[jest-config, jest-resolve]` Remove support for `browser` field ([#9943](https://github.com/facebook/jest/pull/9943))
- TypeScript definitions requires a minimum of TypeScript v3.8 ([#9823](https://github.com/facebook/jest/pull/9823))

With the above changes Jest 26 is now 4 MiB smaller than Jest 25.5.4 (53 → 49 MiB). Please keep in mind that many dependencies like Babel are likely already part of your project. Jest's own size was reduced by 1.2 MiB (4.3 -> 3.1 MiB).

While this is a good start, it isn’t enough to make Jest meaningfully leaner. We are planning on gradually reducing Jest's and its dependency tree size by about 70%. Most of the changes to reduce Jest’s default setup will be small breaking changes and we want to bring the community with us as much as possible. Therefore we will make the following changes in Jest 27 and Jest 28 using a [“Tick-Tock" release process](https://en.wikipedia.org/wiki/Tick%E2%80%93tock_model):
cpojer marked this conversation as resolved.
Show resolved Hide resolved

- Jest 27 will ship with a new test runner (`jest-circus`) and the Node.js environment by default. `jest-jasmine2` and `jest-environment-jsdom` will still be bundled so users can keep using them by changing one-line each in the configuration.
- Jest 28 will remove `jest-jasmine2` and `jest-environment-jsdom` from the default distribution of Jest. The packages will still be actively maintained as part of the Jest project and be published separately. Users will need to install these packages to use them.

Upon upgrading to these major releases, Jest will guide you through the necessary changes. If you’d like to get ahead and migrate to the new defaults now, and your project does not require a DOM environment, you can upgrade to Jest 26 and add the following configuration options:

```json
{
"jest": {
"testEnvironment": "node",
"testRunner": "jest-circus/runner"
}
}
```

Jest will continue to ship with `babel-jest` enabled by default. It currently powers a few Jest features beyond compiling modern JavaScript syntax to something understood by current versions of Node.js and browsers: It also powers Jest's code coverage and mocking of ES modules. Jest currently ships with experimental support for [V8 coverage](/blog/2020/01/21/jest-25#v8-code-coverage) and native support for ES Modules (more on that below!). It is not possible to mock static ES Modules per the specification without transforming the code first, so we will be encouraging patterns that work without the transformation we use Babel for today. Once V8 coverage and native ESM support stabilizes in Jest, we will also be able remove `babel-jest` as a default but we will keep maintaining it.

## New implementation of fake timers

Since 2017 we've been wanting to swap out Jest's implementation of fake timer with the more feature-complete implementation of Lolex - with Jest 26 this is finally happening! It took so long Lolex has even been renamed in the meantime to `@sinonjs/fake-timers`. It has taken so long since we wanted to make sure the implementation was solid and was usable for all the use cases Jest already supported. We're now confident it is stable enough for everybody to use.

The new implementation comes with some extra features, such as mocking `Date`, `queueMicrotask` and more, see their [readme](https://github.com/sinonjs/fake-timers/blob/master/README.md) for more details. We're calling the APIs through the Jest APIs you already know, so keep calling `jest.runAllTimers()` etc. like you've been doing. The docs as always are available [here](https://jestjs.io/docs/en/timer-mocks) on our website.

While we are confident this implementation is ready for prime time, we don't want to force people to rewrite their tests if they depend on Jest's current implementation to work, so for Jest 26 this new implementation will remain _opt-in_. Activate it by calling `jest.useFakeTimers('modern')` or by passing `modern` as the option in your config if you currently have `fake` there.

We will continue to support the legacy implementation going forward, but we will swap the default over to the "modern" timers in Jest 27. At that time you can opt-in to the legacy implementation by specifying `jest.useFakeTimers('legacy')`. If you know _now_ that you want to keep using the legacy implementation, you can specify that today and not have to change anything when Jest 27 comes around.

Huge thanks to [Carl-Erik Kopseng](https://github.com/fatso83), [Benjamin Gruenbaum](https://github.com/benjamingr) and other maintainers of `@sinonjs/fake-timers` for their help and patience when working with us to make this happen!

## New way to consume Jest - `@jest/globals`

Jest has used the widely known `describe`, `it`, `test` and `expect` globals throughout its lifetime - it's a widely used pattern, it's very easy to get started quickly and we all like the ease globals offers us when writing code. That said, we've heard (loud and clear) that many people don't like globals and that they'd like to import the functions in their tests instead.

With Jest 26<sup>\*</sup>, this is now a possibility through the use of a new package called `@jest/globals`. So now you can do `import { expect, jest, test } from '@jest/globals';` in your tests to your heart's content!

A couple of quick caveats:

1. The globals still exist in the environment - we will introduce a `noGlobals` mode in the future for those who wants no globals whatsoever
1. There's currently no clean way to add custom matchers to the TypeScript definitions. Help appreciated fixing that.
1. If you do `const {jest} = require('@jest/globals')` - i.e. don't use transpiled (or native) `import` syntax, you will get declaration errors as we still inject `jest` into the module scope of every file. The `noGlobals` mode will alleviate this issue

<sup>\*</sup>) This was released in 25.5, but we didn't blog about it!

## Native ESM support

As mentioned in the [Jest 25 blog post](/blog/2020/01/21/jest-25#ecmascript-modules-support) we have begun exploring native support for ECMAScript Modules. This work started shipping in Jest 25.3, and has received bug fixes and features in every release since. We're still some distance away from it stabilizing, but any and all help testing it would be highly appreciated! For an overview of the current state you can check out [this issue](https://github.com/facebook/jest/issues/9430), or browse all issues with that label [ES Modules](https://github.com/facebook/jest/labels/ES%20Modules).

cpojer marked this conversation as resolved.
Show resolved Hide resolved
SimenB marked this conversation as resolved.
Show resolved Hide resolved
cpojer marked this conversation as resolved.
Show resolved Hide resolved
cpojer marked this conversation as resolved.
Show resolved Hide resolved
cpojer marked this conversation as resolved.
Show resolved Hide resolved
## Other Breaking Changes in Jest 26

- Dropped support for Node 8 ([#9423](https://github.com/facebook/jest/pull/9423))
- `[jest-environment-jsdom]` Upgrade `jsdom` to v16 ([#9606](https://github.com/facebook/jest/pull/9606))
- `[jest-runtime]` Remove long-deprecated `require.requireActual` and `require.requireMock` methods ([#9854](https://github.com/facebook/jest/pull/9854))
- `[jest-haste-map]` Removed `providesModuleNodeModules` ([#8535](https://github.com/facebook/jest/pull/8535))
- `[jest-circus]` Fail tests if a test takes a done callback and have return values ([#9129](https://github.com/facebook/jest/pull/9129))
- `[jest-circus]` Throw a proper error if a test / hooks is defined asynchronously ([#8096](https://github.com/facebook/jest/pull/8096))
- **_TODO_**

## Stay Safe

We are all currently experiencing an unprecedented time of uncertainty. If you are struggling financially, we would like to use [Jest’s Open Collective fund](https://opencollective.com/jest) to help new and existing contributors. We place [bounties on some issues](https://github.com/facebook/jest/issues?q=is%3Aissue+is%3Aopen+bounty+label%3A%22Has+Bounty%22) and are open to offering a bounty on any of our current open issues - you can mention that an issue should have a bounty in the issue or contact [@cpojer via private message on Twitter](https://twitter.com/cpojer).

Please stay safe.