Перейти к основной части

Jest 26: Tick Tock

Когда мы начали переделывать Jest пять лет назад, наша цель была предоставить систему тестирования без конфигурации, которая доступна для новичков, расширяется почти для всех вариантов использования и масштабирования в больших проектах. Одним из релизов инструмента был Jest 15, который связал все вместе и установил хорошие значения по умолчанию, которые позволяют людям запускать Jest часто без дополнительной настройки. Однако, этот подход имеет большой недостаток, так как Jest устанавливает множество зависимостей в ваши проекты, которые вам не нужны.

Сейчас мы начинаем устранять этот недостаток и работаем над уменьшением размера установки Jest'а, сохраняя его доступным и расширяемым. Мы внесли следующие изменения в в Jest 26:

  • [expect, jest-mock, pretty-format] Удалены файлы сборки ES5 с поддержкой ES2015 (Node 8), которые использовались только для браузерной сборки(#9945)

    Миграция: С этим изменением мы возлагаем на разработчиков ответственность за объединение затрагиваемых пакетов, а не Jest поставляет их из коробки, так как они знают свои целевые среды наилучшим образом. Если вы хотите, мы открыты для отправки их в виде отдельных пакетов. PR-ы приветствуются!

  • [jest-config, jest-resolve] Поддержка удаления поля browser (#9943)

    Миграция: Установите browser-resolve модуль и используйте следующую конфигурацию:

    {
    "jest": {
    "resolver": "<rootDir>/resolver.js"
    }
    }
    // resolver.js
    const browserResolve = require('browser-resolve');
    module.exports = browserResolve.sync;
  • Определение TypeScript требует минимальную версию TypeScript v3.8 (#9823)

С вышеуказанными изменениями Jest 26 теперь весит 4 MiB меньше, чем 25.5.4 Jest (53 → 49 MiB). Пожалуйста, имейте в виду, что многие зависимости, такие как Babel уже должны являться частью вашего проекта. Размер Jest был уменьшен на 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 up to 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:

  • 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:

{
"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 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.

Установка фиктивного таймера#

With Jest 26 we are shipping a new implementation of fake timers based on @sinonjs/fake-timers. We've wanted to do this for years and are happy this has finally progressed far enough to support all of Jest's existing fake timer use cases.

The new implementation comes with extra features such as mocking Date, queueMicrotask and more, see this README. It works transparently using the existing timer APIs like jest.runAllTimers() – check out the documentation on our website.

We are confident this implementation is ready for prime time, however we don't want to force people to rewrite their tests if they depend on subtle differences between the old and new implementation. In Jest 26, this new implementation will remain opt-in and can be activated by calling jest.useFakeTimers('modern') or by passing modern to the timers option in your config if you opted all tests into fake timers previously.

In Jest 27 we will swap the default to the new "modern" implementation but we will keep supporting and maintaining the legacy implementation which can be used by calling jest.useFakeTimers('legacy'). If you are unsure whether you'll be able to upgrade all your tests by the time Jest 27 rolls out, you can add this to your tests now to keep the old behavior.

We'd like to thank Carl-Erik Kopseng, Benjamin Gruenbaum and other maintainers of @sinonjs/fake-timers for their help and patience when working with us to make this happen! Exciting.

A new way to consume Jest - @jest/globals#

Jest has relied on globals popularized by the Jasmine testing framework and others such as describe, it, test and expect. While this is a widely used pattern, many people have expressed their preference for importing testing related functions instead. To support this use case, we added a new package @jest/globals that can be used to import testing functions: import {expect, jest, test} from '@jest/globals';.

Caveats:

  • Currently the globals still exist in the environment but we will introduce a mode to disable globals in the future. Similarly, you cannot use const jest = require('@jest/globals') as you'll get declaration errors because the jest variable is still a global for now.
  • There is currently no way to add custom matchers to the TypeScript definitions when using globals like this.
  • While this allows running tests without globals, it does not allow running tests without Jest's test runner at this time.

Нативная поддержка M1#

As mentioned in the Jest 25 blog post we have been working on native support for ECMAScript Modules. It is not stable yet but it is ready to be tested. We'd love to hear your feedback and bug reports! For an overview of the current state you can check out this issue, or browse all issues with that label ES Modules.

Другие изменения в Jest 26#

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

Stay Safe#

В настоящее время все мы переживаем очень тяжелое время. Если вы имеете трудности с финансовой точки зрения, мы советуем попробовать Открытый коллективный фонд Jest, чтобы помочь новым и давним участникам. We place bounties on some issues 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.

Please stay safe.