In my case, with Ionic 5, Angular 10 and NX monorepo, I had to do the following to enable Jest testing of an Ionic app.
Note: Skip the first 4 steps if you already have standard Jest setup.
Note 2: The order of steps doesn't really matter.
1. Delete all Karma and Jasmine files and dependencies
- Delete
karma.conf.js
and src/test.ts
.
- Delete everything related to
karma
and jasmine
from package.json
(e.g. @types/jasmine
, karma
etc.)
2. Add Jest dependencies
Add jest
, jest-preset-angular
, @types/jest
and ts-jest
to your devDependencies
, if you don't have them yet:
# if you use yarn:
yarn add --dev jest jest-preset-angular @types/jest ts-jest
# or if you use npm:
npm install --save-dev jest jest-preset-angular @types/jest ts-jest
3. Update angular.json
Update your angular.json
file. Replace architect
-> test
configurations for Karma with configurations for Jest:
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "apps/my-app/jest.config.js",
"polyfills": "apps/my-app/src/polyfills.ts"
}
}
Note: I use @nrwl/jest:jest
builder. If you aren't using NX monorepo, just specify @angular-builders/jest:run
as a builder, and remove "apps/my-app/" from the config options.
4. Create test-setup.ts
Create src/test-setup.ts
file with a single line content:
import 'jest-preset-angular';
5. Add Babel dependencies
Add babel-jest
, @babel/preset-env
and @babel/plugin-syntax-dynamic-import
to your devDependencies
:
# if you use yarn:
yarn add --dev babel-jest @babel/preset-env @babel/plugin-syntax-dynamic-import
# or if you use npm:
npm install --save-dev babel-jest @babel/preset-env @babel/plugin-syntax-dynamic-import
6. Update tsconfig.spec.json
Add "allowJs": true
and types
to the compilerOptions
in your TypeScript config. Add files
to compile test-setup.ts
file created earlier.
My final version of tsconfig.spec.json
:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"allowJs": true,
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"files": ["src/test-setup.ts"],
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}
7. Create or update jest.config.js
Create jest.config.js
in your app root (where you have package.json
), if you haven't yet.
Note: I added transformIgnorePatterns
and global.ts-jest.babelConfig
settings to the default version of Jest config for Angular.
The final version of the file looks like this:
const esModules = ['@ionic'].join('|');
module.exports = {
preset: '../../jest.preset.js',
coverageDirectory: '../../coverage/apps/mobile-ui',
snapshotSerializers: [
'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js',
'jest-preset-angular/build/AngularSnapshotSerializer.js',
'jest-preset-angular/build/HTMLCommentSerializer.js',
],
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], // leave `<rootDir>` string as is
globals: {
'ts-jest': {
babelConfig: {
presets: [
[
'@babel/preset-env',
{ targets: { node: true }, modules: 'commonjs' }
]
],
plugins: ['@babel/plugin-syntax-dynamic-import']
},
tsConfig: '<rootDir>/tsconfig.spec.json',
stringifyContentPathRegex: '\\.(html|svg)$',
astTransformers: {
before: [
'jest-preset-angular/build/InlineFilesTransformer',
'jest-preset-angular/build/StripStylesTransformer',
]
},
},
},
// To transform Ionic modules to UMD, because Jest can't import them otherwise
// (see here: https://medium.com/@gregor.woiwode/how-to-setup-jest-in-an-ionic-4-project-ff1e5b72dd79)
transformIgnorePatterns: [
`/node_modules/(?!${esModules})`
],
displayName: 'my-app',
};
Kudos to this article which helped me with identifying these steps: How to setup Jest in an Ionic 4 project | Gregor Woiwode | Apr 25, 2019 | Medium