What makes Jest and Testing Library worth the switch?
Transferring every Angular project I maintain to Jest and Testing Library came down to a handful of concrete benefits.
Jest gives you:
- Better speed compared to Karma.
- Test reports that are simple to scan and understand.
- Built-in code coverage, no extra setup required.
- A command-line interface that handles tests with ease.
- An active ecosystem with plenty of resources.
Testing Library brings:
- Tests that center on how a user actually interacts with the app.
- A workflow that feels quick and straightforward.
If you prefer a plug-and-play approach, the jest schematic at https://github.com/briebug/jest-schematic can handle much of this for you.
Clearing out Jasmine and Karma
Start by removing those packages from your package.json and saving the file.
"@types/jasmine": "~3.10.0",
"jasmine-core": "~3.10.0",
"karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.1.0",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
Return to the terminal and run npm install so that any packages no longer referenced are pruned.
After that, remove both karma.conf.js and src/test.ts from your project.
rm karma.conf.js
rm src/test.ts
Within angular.json, delete the entire test section.
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.css"],
"scripts": []
}
Now we can put Jest into place.
Setting up Jest from scratch
From the terminal, install the core Jest library, the Angular preset for Jest, and the TypeScript type definitions for Jest with one command.
npm install --save-dev jest jest-preset-angular @types/jest
At the root of your project, add a file called setup-jest.ts that brings in the Angular preset.
import 'jest-preset-angular/setup-jest';
In package.json, swap the test script from test: "ng test" to test: "jest".
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "jest"
},
Update the script further by adding a Jest block that connects to jest-preset-angular and points to the Jest configuration file.
"jest": {
"preset": "jest-preset-angular",
"setupFilesAfterEnv": ["<rootDir>/setup-jest.ts"]
}
Inside tsconfig.json, adjust the compiler options as shown below.
"esModuleInterop": true,
Finally, review tsconfig.spec.json — remove node and jasmine, switch the types to jest, and align it with the example provided.
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": ["jest"]
},
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}
Because the existing tests were written in Jasmine and Jest is designed to be compatible, you can run your unchanged test suite from the terminal using the updated test script.
npm run test
> lab@0.0.0 test
> Jest
PASS src/app/app.component.spec.ts
AppComponent
✓ should create the app (169 ms)
✓ should have as title 'lab' (43 ms)
✓ should render title (47 ms)
Test Suites: 1 passed, one total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 1.635 s, estimated 4 s
Ran all test suites.
Set up the testing library
The @testing-library is designed to test UI components from the perspective of the user.
npm install --save-dev @testing-library/angular
Next, create a new file named app.component.ui.spect.ts, where we will leverage the testing library to interact with the UI.
Start by importing render and screen from @testing-library/angular. The render function handles loading the component, while screen gives you a comprehensive set of methods to locate elements in the browser.
In this simple example, we look up the "Next steps" text to explore more about the testing library at https://testing-library.com/docs/.
The await keyword is used to wait for both the render and screen results.
import { render, screen } from '@testing-library/angular';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
it('should render Welcome', async () => {
await render(AppComponent);
await screen.getByText('Welcome');
});
});
Execute your test once more
npm run test
> lab@0.0.0 test
> Jest
PASS src/app/app.component.spec.ts
PASS src/app/app.ui.component.spec.ts
Test Suites: 2 passed, 2 total
Tests: 4 passed, 4 total
Snapshots: 0 total
Time: 4.631 s
Ran all test suites.
Wrap-up
To recap, we covered removing Karma and Jasmine, installing and configuring Jest so your existing tests run, and integrating the testing library into your Angular projects.
We hope this gives you some practical guidance on using Jest and the Testing Library. If you found it useful, please share it!
