@angular-builders/jest
v22.0.1
Published
Jest runner for Angular build facade. Allows ng test run with Jest instead of Karma
Downloads
786,193
Maintainers
Readme
Jest builder for Angular build facade
Allows running ng test with Jest instead of Karma & Jasmine.
The builder comes to provide zero configuration setup for Jest while keeping the workspace clear of boilerplate code.
This documentation is for the latest major version only
⚠️ Version alignment: The major version of
@angular-builders/jestmust match the major version of@angular/corein your project. For example, Angular 19 requires@angular-builders/jest@19.x, Angular 20 requires@angular-builders/jest@20.x, etc. Using a mismatched version is the most common source of issues.
Previous versions
- Version 21
- Version 20
- Version 19
- Version 18
- Version 17
- Version 16
- Version 15
- Version 14
- Version 13
- Version 12
- Version 11
- Version 10
- Version 9
- Version 8
- Version 7
Quick guide
Prerequisites
Installation
- Remove Karma related libraries and files:
$ npm remove karma karma-chrome-launcher karma-coverage-istanbul-reporter karma-jasmine karma-jasmine-html-reporter $ rm ./karma.conf.js ./src/test.ts - Install the builder (and
jestif you still haven't):$ npm i -D jest @types/jest @angular-builders/jest
Updating Typescript configurations
In tsconfig.spec.json (root directory, used by Jest):
- Replace
jasmineintypesarray withjest
You want your tests to be type-checked against Jest typings and not Jasmine. - Remove
test.tsentry fromfilesarray
This file was responsible for Karma setup, you don't need it here anymore.
- Replace
In tsconfig.json (root directory, used by IDE):
- Add
jesttotypesarray
Although you run your unit tests with Jest, Protractor (e2e tests) still has to use Jasmine. Due to this fact it’s possible that you favorite IDE will get confused with the typings and will propose you Jasmine types in unit tests.tsconfig.jsonis the config file that your IDE uses so you have to instruct it explicitly to use Jest typings.
Bear in mind that the other side of the coin is that your IDE will propose you Jest types in your e2e tests.
- Add
Running with Angular CLI
- In your
angular.json:"projects": { "[your-project]": { "architect": { "test": { "builder": "@angular-builders/jest:run", "options": { // see below } } } } } - Run the tests:
ng test
Multi-projects workspace support
The builder supports multi-project workspaces out of the box, the only thing required is editing tsconfig.spec.json in the relevant project directory as described above.
Builder options
config- path to jest config file or a Jest configuration object, relative to project root (or src/ directory in case of non-project app), defaults tojest.config.js. Other extensions are also supported. The Jest configuration might be written in TypeScript, but you should explicitly specify the path to thejest.config.ts. The configuration is merged on top of the default configuration, so there is no need to specify the whole jest configuration in this file. Just specify the changes you'd like to make to the default configuration.You can also provide configuration directly as an object:
"options": { "config": { "testTimeout": 10000, "verbose": true } }The way the configurations are merged is as following:
Take the default configuration from the library
Add on top of it default project specific config (that is dynamic due to different root directories). Used to scope single project test runs.
Add on top of it package.json jest config if exists (for all projects) or jest.config.js from workspace root directory if exists
⚠️ Note on the
projectsfield: The builder acts as the Jest orchestrator via Angular CLI's project system. If your rootjest.config.js(orpackage.jsonjest config) contains aprojectsfield (used for running Jest standalone across a monorepo), the builder will merge it in and Jest will run all sub-projects instead of just the targeted Angular project — resulting in duplicated or unexpected test runs.If you use both
ng test(via the builder) andjestdirectly (standalone), keep theprojectsfield out of the root config and use a separate config file for standalone runs:jest.config.js— used by the Angular builder (noprojectsfield):module.exports = { // shared options: transform, moduleNameMapper, coverageThreshold, etc. };jest.projects.config.js— used for standalone Jest CLI runs:const baseConfig = require('./jest.config'); module.exports = { ...baseConfig, projects: ['<rootDir>/apps/*', '<rootDir>/libs/*'], };Then run standalone Jest with
jest --config jest.projects.config.js.Add on top of it project specific config if it is specified inside angular.json or jest.config.js from project directory (or src/ directory in case of non-project app) if exists.
Thus, if you don't provide
configin options, and you'd like to customize the configuration of a single project in your workspace, you only have to add jest.config.js in this project's root directory and specify the configuration delta in this file. Or, if you'd like the same custom configuration to be applied to all the projects in the workspace, you just specify it in package.json. Another option in such a case is creating a single config file in the workspace root and specifying it in angular.json for each project.tsConfig- path to tsconfig file. If the path is relative then it is evaluated relative to the project root. Defaults totsconfig.spec.jsonthat is located in project root.zoneless- boolean (default:true).true(default): For Angular 21+ applications using zoneless change detection (the new Angular default)false: For applications that rely on zone.js automatic change detection
BREAKING CHANGE in v21: Previous versions always used zone.js. If your app uses zone.js change detection, set
zoneless: false:"options": { "zoneless": false }globalMocks- array (default:["matchMedia"]). OnlymatchMediais supported as jsdom still doesn't implementwindow.matchMedia.BREAKING CHANGE in v21: The
styleTransform,getComputedStyle, anddoctypemocks have been removed as Jest 30's jsdom now supports these natively.If you need custom browser API mocks, add your own setup file via
setupFilesAfterEnvin your jest config.[jest-cli-option]- any option from Jest CLI options. For example, to run unit tests without caching and withjunit-reporteruse:"options": { "no-cache": true, "reporters": "jest-junit" }These options can also be provided directly to
ng testcommand. For example, to run a single test from this suite:describe('My cool suite', () => { it('Should do one thing', () => { // do something... }); it('Should do another thing', () => { // do something... }); });Use the following command:
ng test --test-name-pattern="My cool suite Should do one thing"Notice that for array-like arguments you should use
,delimiter instead of space delimiter. These are limitations of Angular CLI.
Thus, if you want to provide multiple arguments tofind-related-testsoption you should be passing it like this:$ ng test --find-related-tests file1,file2Note: For multi-project workspaces, paths must be relative to the workspace root, not the project root:
$ ng test my-lib --find-related-tests projects/my-lib/src/lib/service.ts,projects/my-lib/src/lib/component.ts
Migrating existing tests to Jest
Use this for automatic migration of your Jasmine tests to Jest framework.
Troubleshooting
Please find below a selection of potential issues you might face when using this builder. Refer to jest-preset-angular Troubleshooting for jest-preset-angular specific issues.
Unexpected token [import|export|other]
This means that the library you're using doesn't use commonjs module format (which jest expects to see). You will need to implement the recommendations mentioned in jest-preset-angular Troubleshooting Guide.
One of the recommendations might require you to transpile js files through babel-jest.
In this case make sure you add allowSyntheticDefaultImports to the ts-jest configuration (see here for an explanation of this setting).
transform: {
'^.+\\.tsx?$': [
'ts-jest',
{
allowSyntheticDefaultImports: true,
},
],
}Your final jest.config.js file should look something like this:
const esModules = ['[thir-party-lib]'].join('|');
module.exports = {
transformIgnorePatterns: [`<rootDir>/node_modules/(?!${esModules})`],
transform: {
'^.+\\.tsx?$': [
'ts-jest',
{
allowSyntheticDefaultImports: true,
},
],
'^.+\\.js$': 'babel-jest',
},
};Top-level await in test files
Test files are compiled to CommonJS by ts-jest/jest-preset-angular, and top-level await (an await at module scope, e.g. const { AppComponent } = await import('./app.component'); outside of any function) is not valid in CommonJS. You will see:
SyntaxError: await is only valid in async functions and the top level bodies of modulesJest's native ES module support that would allow this is still experimental, so the builder does not enable it. Instead, move the dynamic import into an async hook:
let AppComponent;
beforeAll(async () => {
({ AppComponent } = await import('./app.component'));
});