Aller au contenu principal

Jest 30: Faster, Leaner, Better

· 12 minutes de lecture
Svyatoslav Zaytsev
Svyatoslav Zaytsev

Today we are happy to announce the release of Jest 30. This release features a substantial number of changes, fixes, and improvements. While it is one of the largest major releases of Jest ever, we admit that three years for a major release is too long. In the future, we are aiming to make more frequent major releases to keep Jest great for the next decade.

If you want to skip all the news and just get going, run npm install jest@^30.0.0 and follow the migration guide: Upgrading from Jest 29 to 30.

What’s New?

Jest 30 is noticeably faster, uses less memory, and comes with tons of new features. First, let’s take a look at the breaking changes:

Changements de rupture

  • Jest 30 drops support for Node 14, 16, 19, and 21.
  • jest-environment-jsdom was upgraded from jsdom 21 to 26.
  • The minimum compatible TypeScript version is now 5.4.
  • Various expect aliases were removed. eslint-plugin-jest has an autofixer which you can run to automatically upgrade your codebase.
  • Non-enumerable object properties are now excluded from object matchers such as toEqual by default.
  • Jest now supports .mts and .cts files by default.
  • --testPathPattern was renamed to --testPathPatterns.
  • Jest now properly handles promises that are first rejected and then later caught to avoid false positive test failures.
  • We made various improvements to Jest’s printing of snapshots which might require you to update snapshots. Google deprecated goo.gl links which we were using in snapshots. We don’t like it either, but you’ll have to update all your snapshots.
  • Jest itself is now bundled into a single file per package. This improves performance, but might break if you built tools that reach into Jest's internals.

These are just some of the highlights. The full list of breaking changes can be found in the CHANGELOG and the Jest 30 migration guide.

Performance & Memory Improvements

Jest 30 delivers real-world performance gains thanks to many optimizations, especially related to module resolution, memory usage, and test isolation. By relying on the new unrs-resolver, module resolution in Jest became more feature-rich, standards-compliant, and faster. Thanks to @JounQin for the migration. Depending on your project, you may see significantly faster test runs and reduced memory consumption. For example, one large TypeScript app with a client and server observed 37% faster test runs and 77% lower memory usage in one part of their codebase:

Jest 29Jest 30
Server tests~1350s / 7.8 GB max~850s / 1.8 GB max
Client tests~49s / 1.0 GB max~44s / 0.8 GB max

Jest is fast, but due to Jest's test isolation, slow user code often exacerbates performance issues and leads to slow test runs. When tests leave behind open handles like unclosed timers or connections to other services, it can cause Jest to hang or slow down. Jest 30 has gotten better at detecting and reporting these issues, which helps you identify and fix slow or problematic tests more easily. For example, tests at Happo were sped up by 50% from 14 minutes down to 9 minutes by cleaning up open handles and upgrading to Jest 30.

If you are using files that consolidate the exports of multiple modules into a single file (i.e. "barrel files"), we recommend using tools such as babel-jest-boost, babel-plugin-transform-barrels or no-barrel-file to avoid loading large swaths of application code for each test file. This can lead to performance improvements of up to 100x.

Globals cleanup between test files

Jest achieves test isolation between files by running each test in a separate VM context, giving each file a fresh global environment. However, if your code does not clean up globals after each test file, it can lead to memory leaks across Jest and slow down your test runs. Jest 30 introduces a new feature that notifies you about globals that are not correctly cleaned up after a test run.

In the future, Jest will automatically clean up globals after each test run. If you don't get any warnings about uncleaned globals with Jest 30, you can already set the globals cleanup mode to "on" now to enable this feature fully, and benefit from major memory savings and performance improvements:

export default {
testEnvironmentOptions: {
globalsCleanup: 'on',
},
};

The default in Jest is globalsCleanup: 'soft'. To disable this feature you can set it to off. If you need to protect specific global objects from being cleaned up -- for example, shared utilities or caches -- you can mark them as protected using jest-util:

import {protectProperties} from 'jest-util';

protectProperties(globalThis['my-property']);

Thanks to @eyalroth for implementing this feature!

New Features

Improved ECMAScript Module & TypeScript Support

Support for import.meta.* and file:// was added when using native ESM with Jest. In addition, you can now write your Jest config files in TypeScript, and .mts and .cts files are natively supported without requiring extra configuration. If you are using Node’s native TypeScript type stripping feature, we no longer load the TypeScript transformer to strip types, leading to faster test runs.

Spies and the using keyword

You can now use JavaScript’s new explicit resource management syntax (using) with Jest spies. If your environment supports it, writing using jest.spyOn(obj, 'method') will automatically restore the spy when the block ends, so you don’t have to manually clean up.

test('logs a warning', () => {
using spy = jest.spyOn(console, 'warn');
doSomeThingWarnWorthy();
expect(spy).toHaveBeenCalled();
});

Documentation

expect.arrayOf

Jest 30 introduces a new asymmetric matcher, expect.arrayOf, which lets you validate every element of an array against a condition or type. For instance, you can expect an array of numbers ensuring all items are numbers:

expect(someArray).toEqual(expect.arrayOf(expect.any(Number)));

Documentation

New test.each placeholder: %$

If you use data-driven tests with test.each, you can now include a special placeholder %$ in your test titles to inject the number of the test case. Par exemple :

test.each(cases)('Case %$ works as expected', () => {});

will replace %$ with the test’s sequence number.

Documentation

jest.advanceTimersToNextFrame()

@sinonjs/fake-timers was upgraded to v13, adding jest.advanceTimersToNextFrame(). This new function allows you to advance all pending requestAnimationFrame callbacks to the next frame boundary, making it easier to test animations or code that relies on requestAnimationFrame without having to guess millisecond durations.

Documentation

Configurable test retries

Jest 30 enhances jest.retryTimes() with new options that give you control over how retries are handled. You can specify a delay or immediately retry a failed test instead of waiting until the entire test suite finishes:

// Retry failed tests up to 3 times, waiting 1 second between attempts:
jest.retryTimes(3, {waitBeforeRetry: 1000});

// Immediately retry without waiting for other tests to finish:
jest.retryTimes(3, {retryImmediately: true});

Documentation

jest.unstable_unmockModule()

Jest 30 adds new experimental jest.unstable_unmockModule() API for finer control when unmocking modules (especially when using native ESM).

Documentation

jest.onGenerateMock(callback)

A new onGenerateMock method was added. It registers a callback function that is invoked whenever Jest generates a mock for a module. This callback allows you to modify a mock before it is returned to your test environment:

jest.onGenerateMock((modulePath, moduleMock) => {
if (modulePath.includes('Database')) {
moduleMock.connect = jest.fn().mockImplementation(() => {
console.log('Connected to mock DB');
});
}
return moduleMock;
});

Documentation

Other Improvements

Custom object serialization

Jest’s matcher utilities now support defining a static SERIALIZABLE_PROPERTIES on custom objects. This allows you to control which properties of a custom object are included in snapshots and error messages, making the output more focused and relevant.

Documentation

Asynchronous setup support

Test files listed in setupFilesAfterEnv can now export an async function or use top-level await similar to setupFiles.

And so much more…

Check out the full CHANGELOG for all changes, improvements and new features.

Known Issues

jsdom has made changes to become more spec compliant. This might break some use cases, most notably mocking window.location in tests. Jest now ships with @jest/environment-jsdom-abstract to make it easier for you to compose your own custom test environment based on jsdom. If you are just looking to patch jsdom, you can apply this jsdom patch to your project. In the future, we may look into providing an alternative to jsdom that is better suited for testing.

What's Next

Jest has been the most popular JavaScript testing framework for a decade. It is used by millions of developers, supporting a wide range of projects from small libraries to the largest codebases in the world. Jest has constantly been improved over time, and as with all long-lasting software projects used in the real world, we accumulated technical debt. We support some features that only few people or companies use, and we have kept breaking changes to a minimum to avoid disrupting users. Some features should be made possible by Jest, but not as part of the core framework. Other features promote testing the wrong things, and should maybe not be part of Jest at all. In terms of Jest's team, a few of us moved on over time which led to slower progress and fewer releases. Here is how we are going to address these issues going forward:

  • Performance / Technical Debt: Slim Jest down into a leaner, more performant core. Remove features that are not used by the majority of users, and focus on what makes Jest great.
  • Consistent Release Cycles: We will aim to be more consistent with our release cycles and deprecation policies.
  • Be Open: Build everything in the open, and be transparent about our plans. Provide more opportunities to get involved and increase the number of contributors.
  • Be Bold: As the Jest team, we should be more bold. There are a bunch of things that holds Jest back from what it could be. It's time to make moves.

The great news is that Jest has always been well set up to deliver on these principles, ever since we built the framework as a modular system with clear separation of concerns. Now it's time to execute. More on all that soon!

Remerciements

This release wouldn’t have been possible without the hard work of our community. Thank you.

@SimenB, @mrazauskas, @Connormiha, @liuxingbaoyu, @k-rajat19, @G-Rath, @charpeni, @dubzzz, @stekycz, @yinm, @lencioni, @phawxby, @lukeapage, @robhogan, @fisker, @k-rajat19, @connectdotz, @alesmenzel, @rickhanlonii, @mbelsky, @brunocabral88, @brandon-leapyear, @nicolo-ribaudo, @dj-stormtrooper, @eryue0220

A special thanks to everyone who made their first contribution to Jest in this release. Thank you for making Jest better for everyone!

@eyalroth, @KhaledElmorsy, @mohammednumaan, @bensternthal, @BondarenkoAlex, @phryneas, @jayvdb, @brandonchinn178, @latin-1, @rmartine-ias, @fa93hws, @Dunqing, @gustav0d, @noritaka1166, @andreibereczki, @Dreamsorcerer, @satanTime, @icholy, @ecraig12345, @cgm-16, @sebastiancarlos, @dancer1325, @loganrosen, @zakingslayerv22, @dev-intj, @tez3998, @anbnyc, @pengqiseven, @thypon, @co63oc, @danielrentz, @jonasongg, @andrew-the-drawer, @phryneas, @hyperupcall, @tonyd33, @madcapnmckay, @dongwa, @gagan-bhullar-tech, @ikonst, @ZuBB, @jzaefferer, @brandonnorsworthy, @henny1105, @DmitryMakhnev, @askoufis, @RahulARanger, @Jon-Biz, @fynsta, @KonnorRogers, @BondarenkoAlex, @mouadhbb, @kemuridama, @Avi-E-Koenig, @davidroeca, @akwodkiewicz, @mukul-turing, @dnicolson, @colinacassidy, @ofekm97, @haze, @Vadimchesh, @peterdenham, @ShuZhong, @manoraj, @nicolo-ribaudo, @georgekaran, @MathieuFedrigo, @hkdobrev, @Germandrummer92, @CheadleCheadle, @notaphplover, @danbeam, @arescrimson, @yepitschunked, @JimminiKin, @DerTimonius, @vkml, @ginabethrussell, @jeremiah-snee-openx, @WillianAgostini, @casey-lentz, @faizanu94, @someone635, @rafaelrabelos, @RayBrokeSomething, @DaniAcu, @mattkubej, @tr1ckydev, @shresthasurav, @the-ress, @Mutesa-Cedric, @nolddor, @alexreardon, @Peeja, @verycosy, @mknight-atl, @maro1993, @Eric-Tyrrell22

Jest rejoint la fondation OpenJS

· Une minute de lecture
Ricky Hanlon
Ricky Hanlon

Banner image for Meta Open Source and OpenJS Foundation

Aujourd'hui, nous sommes heureux d'annoncer que Jest rejoint la Fondation OpenJS !

Ce changement transfère la propriété du projet de Meta à l'équipe principale de Jest via la Fondation OpenJS en tant que projet d'impact. Nous sommes reconnaissants envers Meta pour la création de Jest et pour tout son soutien au fil des ans, et nous nous réjouissons de l'avenir de Jest en tant que projet appartenant à la communauté Jest !

Check out the Meta Engineering blog and OpenJS Foundation blog announcements for more info.

Jest 28 : Perte de poids et compatibilité accrue 🫶

· 9 minutes de lecture
Simen Bekkhus
Simen Bekkhus

Jest 28 is finally here, and it comes with some long requested features such as support for sharding a test run across multiple machines, package exports and the ability to customize the behavior of fake timers. Il ne s'agit là que de quelques points marquants et nous en soulignerons d'autres dans cet article du blog.

Additionally, as announced in the Jest 27 blog post last year, we have removed some packages that no longer are used by default from the default installation. En conséquence, la taille de l'installation a diminué d'environ 1/3.

Jest 27 : nouvelles valeurs par défaut pour Jest, édition 2021 ⏩

· 8 minutes de lecture
Tim Seckinger
Tim Seckinger

In the Jest 26 blog post about a year ago, we announced that after two major releases with few breaking changes, Jest 27 will flip some switches to set better defaults for projects that are new or can migrate smoothly. Cela nous donne l'opportunité de retirer certains paquets de la distribution par défaut de Jest 28 et de les publier en tant que modules installables et connectables séparément. Tous ceux qui utilisent les nouvelles valeurs par défaut peuvent bénéficier d'une installation plus petite, tandis que ceux qui ont besoin de ces paquets peuvent toujours les installer séparément.

With the first major change of defaults since the New Defaults for Jest that came with the seminal version 15, Jest 27 is now here, to keep Jest fast, lean, and relevant in the future. Nous expliquerons ces changements de valeurs par défaut et d'autres changements notables dans cet article, mais tout d'abord, nous allons aborder les nouvelles fonctionnalités !

Jest 26 : Tic Tac

· 8 minutes de lecture

Lorsque nous avons commencé à reconstruire Jest il y a cinq ans, notre objectif était de fournir un exécuteur de tests sans configuration, accessible aux débutants, extensible pour presque tous les cas d'utilisation de tests et évolutif pour les grands projets. One of the instrumental releases was Jest 15 which tied everything together and provided good defaults that allowed people to run Jest often without any setup. Cependant, cette approche a un gros inconvénient car Jest installe beaucoup de dépendances dans vos projets dont vous n'avez peut-être pas besoin.

Nous commençons à remédier à cette lacune et nous nous efforçons de réduire la taille de l'installation de Jest tout en le gardant accessible et extensible. We have made the following breaking changes in Jest 26:

Jest 25 : 🚀 pose des fondations pour le futur

· 9 minutes de lecture
Simen Bekkhus
Simen Bekkhus

Jest 25 pose les bases de nombreux changements majeurs à l'avenir. Nous avons donc limité au maximum les changements de rupture, mais les modifications de l'architecture interne peuvent nécessiter une attention particulière pendant la mise à niveau. Les principaux changements sont une mise à niveau de JSDOM de la v11 à la v15, des tests 10-15% plus rapides, une nouvelle vue diff pour les instantanés périmés et l'abandon du support de Node 6.

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.

Jest 24 : 💅 Actualisation, polissage, facilité d'utilisation de TypeScript

· 11 minutes de lecture
Simen Bekkhus
Simen Bekkhus

Aujourd'hui, nous sommes heureux de vous annoncer la prochaine version majeure de Jest - la version 24 ! Quatre mois se sont écoulés depuis la dernière version mineure, et huit mois depuis Jest 23. Cette mise à jour est donc importante, et chacun y trouvera son compte ! Parmi les points forts, citons la prise en charge intégrée de TypeScript par la mise à niveau des internes de Jest vers Babel 7, la correction de certains problèmes de longue date concernant l'absence de sortie de la console et les problèmes de performance lors du calcul de diffs importants, ainsi qu'un tout nouveau site Web étincelant. ✨

For a full list of all changes see the changelog.

Soutien de Jest Open Source

· 4 minutes de lecture
Ricky Hanlon
Ricky Hanlon

Jest est maintenu par une communauté de contributeurs open source et d'employés de Facebook.

Nos contributeurs open source travaillent au nom de la communauté pour créer de nouvelles fonctionnalités, corriger les bogues et maintenir l'arriéré des problèmes. Les employés de Facebook font de même, concentré sur les problèmes spécifiques à l'échelle de Facebook, et exécutent toutes les publications proposées sur l'énorme suite de test de Facebook avant de les publier.

Nous faisons tous notre partie pour rendre les tests agréables.

Lors du sommet de Jest, nous avons annoncé le Jest Open Collective. C'est notre façon d'aider à soutenir les efforts de la communauté Jest open source. To be absolutely clear: Facebook employees cannot benefit from the Jest Open Collective. The collective's sole purpose is to support the open source side of the Jest community.

Dans ce poste, nous décrirons ce qu'est l'Open Collective Jest, la structure et les buts que nous avons.