Jest is an open source test runner created by Facebook. It has a lot of great features:

  • Immersive watch mode for providing near instant feedback when developing tests.
  • Snapshot testing for validating features.
  • Great built-in reporter for printing out test results.

Setting up Jest

By default, Nx will use Jest when creating applications and libraries.

nx g @nx/web:app frontend

Nx 15 and lower use @nrwl/ instead of @nx/

Adding Jest to an Existing Project

Add Jest to a project using the configuration generator from @nx/jest.

First, install @nx/jest, if not already installed using your preferred package manager.

Keep Nx Package Versions In Sync

Make sure to install the @nx/jest version that matches the version of nx in your repository. If the version numbers get out of sync, you can encounter some difficult to debug errors. You can fix Nx version mismatches with this recipe.

npm install --save-dev @nx/jest

Nx 15 and lower use @nrwl/ instead of @nx/

Once installed, run the configuration generator

nx g @nx/jest:configuration --project=<project-name>

Nx 15 and lower use @nrwl/ instead of @nx/

Hint: You can use the --dry-run flag to see what will be generated.

Replacing <project-name> with the name of the project you're wanting to add Jest too.

Using Jest

Testing Applications

The recommended way to run/debug Jest tests via an editor

To run Jest tests via nx use

nx test frontend

Watching for Changes

Using the --watch flag will run the tests whenever a file changes.

nx test frontend --watch

Snapshot Testing

Jest has support for Snapshot Testing, a tool which simplifies validating data. Check out the official Jest Documentation on Snapshot Testing.

Example of using snapshots:

1describe('SuperAwesomFunction', () => { 2 it('should return the correct data shape', () => { 3 const actual = superAwesomFunction(); 4 expect(actual).toMatchSnapshot(); 5 }); 6}); 7

When using snapshots, you can update them with the --updateSnapshot flag, -u for short.

By default, snapshots will be generated when there are not existing snapshots for the associated test.

nx test frontend -u

Snapshot files should be checked in with your code.

Performance in CI

Typically, in CI it's recommended to use nx affected -t test --parallel=[# CPUs] -- --runInBand for the best performance.

This is because each jest process creates a workers based on system resources, running multiple projects via nx and using jest workers will create too many process overall causing the system to run slower than desired. Using the --runInBand flag tells jest to run in a single process.

Configurations

Jest

Primary configurations for Jest will be via the jest.config.ts file that generated for your project. This file will extend the root jest.preset.js file. Learn more about Jest configurations.

The root level jest.config.ts file configures Jest multi project support. This configuration allows editor/IDE integrations to pick up individual project's configurations rather than the one at the root.

The set of Jest projects within Nx workspaces tends to change. Instead of statically defining a list in jest.config.ts, Nx provides a utility function called getJestProjects which queries for Jest configurations defined for targets which use the @nx/jest:jest executor.

You can add Jest projects which are not included in getJestProjects(), because they do not use the Nx Jest executor, by doing something like the following:

1import { getJestProjects } from '@nx/jest'; 2 3export default { 4 projects: [...getJestProjects(), '<rootDir>/path/to/jest.config.ts'], 5}; 6
Nx 15 and lower use @nrwl/ instead of @nx/

Nx

Nx Jest Plugin options can be configured via the project config file or via the command line flags.

Hint: Use --help to see all available options

nx test <project-name> --help

Code Coverage

Enable code coverage with the --coverage flag or by adding it to the executor options in the project configuration file.

By default, coverage reports will be generated in the coverage/ directory under projects name. i.e. coverage/apps/frontend. Modify this directory with the --coverageDirectory flag. Coverage reporters can also be customized with the --coverageReporters flag.

coverageDirectory and coverageReporters are configurable via the project configuration file as well.

Global setup/teardown with nx libraries

In order to use Jest's global setup/teardown functions that reference nx libraries, you'll need to register the TS path for jest to resolve the libraries. Nx provides a helper function that you can import within your setup/teardown file.

global-setup.ts
1import { registerTsProject } from '@nx/js/src/internal'; 2const cleanupRegisteredPaths = registerTsProject('.', 'tsconfig.base.json'); 3 4import { yourFancyFunction } from '@some-org/my-util-library'; 5export default async function () { 6 yourFancyFunction(); 7} 8// make sure to run the clean up! 9cleanupRegisteredPaths(); 10
Nx 15 and lower use @nrwl/ instead of @nx/
@swc/jest & global scripts

When using @swc/jest and a global setup/teardown file, You have to set the noInterop: false and use dynamic imports within the setup function

apps/<your-project>/jest.config.ts
1/* eslint-disable */ 2import { readFileSync } from 'fs'; 3 4// Reading the SWC compilation config and remove the "exclude" 5// for the test files to be compiled by SWC 6const { exclude: _, ...swcJestConfig } = JSON.parse( 7 readFileSync(`${__dirname}/.swcrc`, 'utf-8') 8); 9 10// disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves. 11// If we do not disable this, SWC Core will read .swcrc and won't transform our test files due to "exclude" 12if (swcJestConfig.swcrc === undefined) { 13 swcJestConfig.swcrc = false; 14} 15 16// jest needs EsModule Interop to find the default exported function 17swcJestConfig.module.noInterop = false; 18 19export default { 20 globalSetup: '<rootDir>/src/global-setup-swc.ts', 21 transform: { 22 '^.+\\.[tj]s$': ['@swc/jest', swcJestConfig], 23 }, 24 // other settings 25}; 26
global-setup-swc.ts
1import { registerTsProject } from '@nx/js/src/internal'; 2const cleanupRegisteredPaths = registerTsProject('.', 'tsconfig.base.json'); 3 4export default async function () { 5 // swc will hoist all imports, and we need to make sure the register happens first 6 // so we import all nx project alias within the setup function first. 7 const { yourFancyFunction } = await import('@some-org/my-util-library'); 8 9 yourFancyFunction(); 10 11 // make sure to run the clean up! 12 cleanupRegisteredPaths(); 13} 14
Nx 15 and lower use @nrwl/ instead of @nx/

More Documentation