|
| 1 | +# Migration from Karma/Jasmine to Jest |
| 2 | + |
| 3 | +Given the faster execution, clearer stack trace of Jest, Karma is being deprecated; decided to migrate to Jest. |
| 4 | + |
| 5 | + |
| 6 | + |
| 7 | +Authors: Utku, Omar Rojas |
| 8 | +Date: unpublished |
| 9 | +Category: frontend |
| 10 | + |
| 11 | +tags: web,testing,test,unit,frontend,karma,jest,jasmine |
| 12 | + |
| 13 | +--- |
| 14 | + |
| 15 | +## Introduction |
| 16 | + |
| 17 | +In Angular 16, Karma was deprecated while Jest was introduced in experimental mode. The Angular team moved towards Jest as the recommended testing framework for Angular applications. While Karma was the default testing framework for Angular in the past, Jest is being explored as a potential replacement due to its simplicity, speed, and built-in features like snapshot testing and mocking. However, it’s important to note that Jest is still in the experimental stage in Angular 16 and Angular 17, and using it in production may have limitations or unsupported features. |
| 18 | + |
| 19 | +Given the faster execution, clearer stack trace of Jest, Karma is being deprecated; decided to migrate to Jest. |
| 20 | + |
| 21 | +## Migration |
| 22 | + |
| 23 | +In Backbase, we use Nx Angular schematics to generate our applications. The steps described below to complete the migration follow that specific project structure. If you have a different project structure, these steps may still provide you with the direction you want to take, considering the needed changes applicable to the different folder structures. |
| 24 | + |
| 25 | +1. Delete the tests properties inside targets object completely in **project.json** files. |
| 26 | + |
| 27 | +2. Delete all the references to **karma.conf.js** files by globally searching in your project. |
| 28 | + |
| 29 | +3. Delete all **karma.conf.js** files. |
| 30 | + |
| 31 | +4. Delete all **test.ts** files. |
| 32 | + |
| 33 | +5. Delete all Karma and Jasmine related dependencies from **package.json**. |
| 34 | + |
| 35 | +6. Run `npm i` to update **package-lock.json** and **node_modules**. |
| 36 | + |
| 37 | +7. Go to [@nx/jest | Nx](https://nx.dev/nx-api/jest) to follow the instructions below: |
| 38 | + |
| 39 | + 1. Do not install the **nx/jest** unless you don’t already have it in **package.json**. |
| 40 | + |
| 41 | + 2. To add Jest to projects, run `nx g @nx/jest:configuration --project=<project-name>` for all projects in the repository one by one except e2e and assets projects. This command will add required config to **project.json** files as well as making changes in **tsconfig.spec.json** and **jest.config.ts** files per project. This will allow Nx to run tests properly. Content of **jest.config.ts**: |
| 42 | + |
| 43 | + ```typescript |
| 44 | + export default { |
| 45 | + displayName: 'demo-angular', |
| 46 | + preset: '../../jest.preset.js', |
| 47 | + coverageDirectory: '../../coverage/apps/demo-angular', |
| 48 | + }; |
| 49 | + ``` |
| 50 | + |
| 51 | +8. Replace compilerOptions → types property value in **tsconfig.editor.json** to `["jest", "node"]`. |
| 52 | + |
| 53 | +9. Add `jest-preset-angular` as devDependency (along with **jest** and **@types/jest** if they don’t already exist) with `npm install -D jest jest-preset-angular @types/jest` |
| 54 | + |
| 55 | +10. Make sure that you have **setup-jest.ts** files inside src directory of each Nx lib and app. If it doesn’t exist, manually create it. There should be one in the root directory of the repo. |
| 56 | + |
| 57 | + 1. **setup-jest.ts** files will likely need mocking **TextEncoder** and import of **@angular/localize/init** additionally. Can be tested without them and added if required. Here is an example content of it: |
| 58 | + |
| 59 | + ```typescript |
| 60 | + import 'jest-preset-angular/setup-jest'; |
| 61 | + import '@angular/localize/init'; |
| 62 | + import { TextEncoder } from 'node:util'; |
| 63 | + // Workaround for Jest error - ReferenceError: TextEncoder is not defined |
| 64 | + Object.defineProperty(window, 'TextEncoder', { |
| 65 | + writable: true, |
| 66 | + value: TextEncoder, |
| 67 | + }); |
| 68 | + ``` |
| 69 | + |
| 70 | +11. **jest.preset.js** file in root of the repo will likely need to have below content. **transform** and **transformIgnorePatterns** values can be changed depending on your needs. |
| 71 | + |
| 72 | + ```typescript |
| 73 | + const nxPreset = require('@nx/jest/preset').default; |
| 74 | + module.exports = { |
| 75 | + ...nxPreset, |
| 76 | + coverageReporters: ['lcov'], |
| 77 | + collectCoverage: true, |
| 78 | + coverageThreshold: { |
| 79 | + global: { |
| 80 | + branches: 80, |
| 81 | + functions: 80, |
| 82 | + lines: 80, |
| 83 | + statements: -10, |
| 84 | + }, |
| 85 | + }, |
| 86 | + setupFilesAfterEnv: ['<rootDir>/src/setup-jest.ts'], |
| 87 | + transform: { |
| 88 | + '^.+.(ts|mjs|js|html)$': [ |
| 89 | + 'jest-preset-angular', |
| 90 | + { |
| 91 | + tsconfig: '<rootDir>/tsconfig.spec.json', |
| 92 | + stringifyContentPathRegex: '\\.(html|svg)$', |
| 93 | + }, |
| 94 | + ], |
| 95 | + }, |
| 96 | + transformIgnorePatterns: ['node_modules/(?!(d3.*|internmap|.*\\.mjs$))'], |
| 97 | + }; |
| 98 | + ``` |
| 99 | + |
| 100 | +12. Transform all the Jasmine tests to Jest. There will likely be failing existing tests. Run tests again and again and fix them until there is no failing test. |
| 101 | + |
| 102 | +13. If you have Sonar in your project, make sure to add **setup-jest.ts** files to the **sonar.test.exclusions** and **sonar.coverage.exclusions** properties of **sonar-project.properties** file. An example glob pattern: |
| 103 | + |
| 104 | + ``` |
| 105 | + sonar.test.exclusions=\ |
| 106 | + libs/**/setup-jest.ts,\ |
| 107 | + apps/**/setup-jest.ts,\ |
| 108 | + ............. |
| 109 | + sonar.coverage.exclusions=\ |
| 110 | + libs/**/setup-jest.ts,\ |
| 111 | + apps/**/setup-jest.ts,\ |
| 112 | + ............. |
| 113 | + ``` |
| 114 | + |
| 115 | + |
| 116 | +### Eventual Folder Structure |
| 117 | + |
| 118 | + |
| 119 | +``` |
| 120 | +. |
| 121 | +├── jest.config.ts |
| 122 | +├── jest.preset.js |
| 123 | +├── apps |
| 124 | +│ ├── app |
| 125 | +│ │ ├── jest.config.ts |
| 126 | +│ │ └── src |
| 127 | +│ │ └── setup-jest.ts |
| 128 | +└── libs |
| 129 | + ├── lib |
| 130 | + │ ├── jest.config.ts |
| 131 | + │ └── src |
| 132 | + │ └── setup-jest.ts |
| 133 | +``` |
| 134 | + |
| 135 | +## References |
| 136 | + |
| 137 | +**transformIgnorePatterns**: [Troubleshooting | jest-preset-angular](https://thymikee.github.io/jest-preset-angular/docs/guides/troubleshooting/#unexpected-token-importexportother) |
| 138 | + |
| 139 | +[@nx/jest](https://nx.dev/nx-api/jest) |
0 commit comments