尝试将Jest引入Angular7.2
简而言之
这是关于在Angular 7中尝试引入Jest时的笔记。
有些网站上写着只需运行四个命令就可以运行,但实际上并非如此,我通过反复试错找到了解决方法并进行了整理。
有两种导入的方式。
-
- A. もう作ってある Karma環境を @briebug/jest-schematic で変換する
-
- B. パッケージがないところから、環境を作る
- A.のついでに、試して動いたので手順を一応メモを残す。
环境
-
- Angular CLI: 7.2.4
-
- Node: 11.13.0
-
- OS: win32 x64
-
- Angular: 7.2.15
-
- Jest
@angular-builders/jest@7.4.4
jest-preset-angular@8.0.0
jest@24.9.0
将已经创建的Karma环境进行转换。
npm install -g @briebug/jest-schematic
ng g @briebug/jest-schematic:add
ng add @briebug/jest-schematic
npm i -D @angular-builders/jest@7.4.4
一. 编辑package.json文件.
似乎发生错误,需要修改 astTransformers 这部分。
"jest": {
"preset": "jest-preset-angular",
"roots": [
"src"
],
"transform": {
"^.+\\.(ts|js|html)$": "ts-jest"
},
"setupFilesAfterEnv": [
"<rootDir>/src/setup-jest.ts"
],
"moduleNameMapper": {
"@app/(.*)": "<rootDir>/src/app/$1",
"@assets/(.*)": "<rootDir>/src/assets/$1",
"@core/(.*)": "<rootDir>/src/app/core/$1",
"@env": "<rootDir>/src/environments/environment",
"@src/(.*)": "<rootDir>/src/src/$1",
"@state/(.*)": "<rootDir>/src/app/state/$1"
},
"globals": {
"ts-jest": {
"tsConfig": "<rootDir>/src/tsconfig.spec.json",
"stringifyContentPathRegex": "\\.html$",
"astTransformers": [
"jest-preset-angular/build/InlineFilesTransformer",
"jest-preset-angular/build/StripStylesTransformer"
]
}
}
A. 修改2个angular.json文件。
"test": {
- "builder": "@angular-devkit/build-angular:karma",
+ "builder": "@angular-builders/jest:run",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
A. 添加 src/jest.config.js
请注意 “snapshotSerializers” 部分。
module.exports = {
"transform": {
"^.+\\.(ts|js|html)$": "ts-jest",
"^.+\\.[t|j]sx?$": "babel-jest"
},
moduleFileExtensions: ['ts', 'html', 'js', 'json'],
moduleNameMapper: {
'^src/(.*)$': '<rootDir>/src/$1',
'^app/(.*)$': '<rootDir>/src/app/$1',
'^assets/(.*)$': '<rootDir>/src/assets/$1',
'^environments/(.*)$': '<rootDir>/src/environments/$1',
},
transformIgnorePatterns: ['node_modules/(?!@ngrx)'],
snapshotSerializers: [
'jest-preset-angular/build/AngularSnapshotSerializer.js',
'jest-preset-angular/build/HTMLCommentSerializer.js',
],
};
A. 编辑 4 个 src/tsconfig.spec.json
diff --git a/list-server-nohttp/src/tsconfig.spec.json b/list-server-nohttp/src/tsconfig.spec.json
index de77336..400bd63 100644
--- a/list-server-nohttp/src/tsconfig.spec.json
+++ b/list-server-nohttp/src/tsconfig.spec.json
@@ -3,8 +3,7 @@
"compilerOptions": {
"outDir": "../out-tsc/spec",
"types": [
- "jasmine",
- "node"
+ "jest"
]
},
从没有包装的地方创造一个环境。
B.1 编辑 package.json 文件
参考以 A 已经获得成就的 package.json 文件来导入。
索引 1fbf179..e9b1bfd 100644
— a/list-server-nohttp/package.json
+++ b/list-server-nohttp/package.json
@@ -5,9 +5,10 @@
“ng”: “ng”,
“start”: “ng serve”,
“build”: “ng build”,
– “test”: “ng test”,
+ “test”: “jest”,
“lint”: “ng lint”,
– “e2e”: “ng e2e”
+ “e2e”: “ng e2e”,
+ “test:watch”: “jest –watch”
},
“private”: true,
“dependencies”: {
@@ -19,12 +20,14 @@
“@angular/platform-browser”: “~7.2.0”,
“@angular/platform-browser-dynamic”: “~7.2.0”,
“@angular/router”: “~7.2.0”,
+ “@briebug/jest-schematic”: “^2.1.0”,
“core-js”: “^2.5.4”,
“rxjs”: “~6.3.3”,
“tslib”: “^1.9.0”,
“zone.js”: “~0.8.26”
},
“devDependencies”: {
+ “@angular-builders/jest”: “^7.4.4”,
“@angular-devkit/build-angular”: “~0.12.0”,
“@angular/cli”: “~7.2.4”,
“@angular/compiler-cli”: “~7.2.0”,
@@ -32,17 +35,45 @@
“@types/node”: “~8.9.4”,
“@types/jasmine”: “~2.8.8”,
“@types/jasminewd2”: “~2.0.3”,
+ “@types/jest”: “24.0.21”,
“codelyzer”: “~4.5.0”,
“jasmine-core”: “~2.99.1”,
“jasmine-spec-reporter”: “~4.2.1”,
– “karma”: “~3.1.1”,
– “karma-chrome-launcher”: “~2.2.0”,
– “karma-coverage-istanbul-reporter”: “~2.0.1”,
– “karma-jasmine”: “~1.1.2”,
– “karma-jasmine-html-reporter”: “^0.2.2”,
+ “jest”: “24.9.0”,
+ “jest-preset-angular”: “8.0.0”,
“protractor”: “~5.4.0”,
“ts-node”: “~7.0.0”,
“tslint”: “~5.11.0”,
“typescript”: “~3.1.6”
+ },
+ “jest”: {
+ “preset”: “jest-preset-angular”,
+ “roots”: [
+ “src”
+ ],
+ “transform”: {
+ “^.+\\.(ts|js|html)$”: “ts-jest”
+ },
+ “setupFilesAfterEnv”: [
+ “/src/setup-jest.ts”
+ ],
+ “moduleNameMapper”: {
+ “@app/(.*)”: “/src/app/$1”,
+ “@assets/(.*)”: “/src/assets/$1”,
+ “@core/(.*)”: “/src/app/core/$1”,
+ “@env”: “/src/environments/environment”,
+ “@src/(.*)”: “/src/src/$1”,
+ “@state/(.*)”: “/src/app/state/$1”
+ },
+ “globals”: {
+ “ts-jest”: {
+ “tsConfig”: “/src/tsconfig.spec.json”,
+ “stringifyContentPathRegex”: “\\.html$”,
+ “astTransformers”: [
+ “jest-preset-angular/build/InlineFilesTransformer”,
+ “jest-preset-angular/build/StripStylesTransformer”
+ ]
+ }
+ }
}
}
B.2. 修改 angular.json
- angular.json の修正 (Aに同じ)
在Chinese的native version中,B.3. src/jest.config.js 的追加 可以是:“增加src/jest.config.js文件”。
参考A的步骤,并融入有成果的元素。
“transform”: {
“^.+\\.(ts|js|html)$”: “ts-jest”,
“^.+\\.[t|j]sx?$”: “babel-jest”
},
moduleFileExtensions: [‘ts’, ‘html’, ‘js’, ‘json’],
moduleNameMapper: {
‘^src/(.*)$’: ‘/src/$1’,
‘^app/(.*)$’: ‘/src/app/$1’,
‘^assets/(.*)$’: ‘/src/assets/$1’,
‘^environments/(.*)$’: ‘/src/environments/$1’,
},
transformIgnorePatterns: [‘node_modules/(?!@ngrx)’],
snapshotSerializers: [
‘jest-preset-angular/build/AngularSnapshotSerializer.js’,
‘jest-preset-angular/build/HTMLCommentSerializer.js’,
],
globals: {
‘ts-jest’: {
diagnostics: {
ignoreCodes: [151001]
}
}
}
};
src/jest.config.js
module.exports = {
“transform”: {
“^.+\\.(ts|js|html)$”: “ts-jest”,
“^.+\\.[t|j]sx?$”: “babel-jest”
},
moduleFileExtensions: [‘ts’, ‘html’, ‘js’, ‘json’],
moduleNameMapper: {
‘^src/(.*)$’: ‘/src/$1’,
‘^app/(.*)$’: ‘/src/app/$1’,
‘^assets/(.*)$’: ‘/src/assets/$1’,
‘^environments/(.*)$’: ‘/src/environments/$1’,
},
transformIgnorePatterns: [‘node_modules/(?!@ngrx)’],
snapshotSerializers: [
‘jest-preset-angular/build/AngularSnapshotSerializer.js’,
‘jest-preset-angular/build/HTMLCommentSerializer.js’,
],
globals: {
‘ts-jest’: {
diagnostics: {
ignoreCodes: [151001]
}
}
}
};
添加 src/setup-jest.ts
根据A的步骤参考并吸收有成就的事例。
/* jsdom的全局模拟 */
const mock = () => {
let storage: { [key: string]: string } = {};
return {
getItem: (key: string) => (key in storage ? storage[key] : null),
setItem: (key: string, value: string) => (storage[key] = value || ”),
removeItem: (key: string) => delete storage[key],
clear: () => (storage = {})
};
};
Object.defineProperty(window, ‘localStorage’, { value: mock() });
Object.defineProperty(window, ‘sessionStorage’, { value: mock() });
Object.defineProperty(window, ‘getComputedStyle’, {
value: () => [‘-webkit-appearance’],
});
Object.defineProperty(document.body.style, ‘transform’, {
value: () => {
return {
enumerable: true,
configurable: true,
};
},
});
/* 输出更简短和更有意义的Zone错误堆栈跟踪 */
// Error.stackTraceLimit = 2;
添加 src/test-config.helper.ts 到 B.5
参考A的步骤,并借鉴其中的成功经验。
B.6 编辑 src/tsconfig.spec.json
参考文献A的步骤取得业绩成功的部分。
diff --git a/list-server-nohttp/src/tsconfig.spec.json b/list-server-nohttp/src/tsconfig.spec.json
index de77336..400bd63 100644
--- a/list-server-nohttp/src/tsconfig.spec.json
+++ b/list-server-nohttp/src/tsconfig.spec.json
@@ -3,8 +3,7 @@
"compilerOptions": {
"outDir": "../out-tsc/spec",
"types": [
- "jasmine",
- "node"
+ "jest"
]
},
故障排查
找不到模块“karma”。
我没有修改angular.json。
list-server-nohttp> ng test
Could not find module "karma" from "~\\list-server-nohttp".
Error: Could not find module "karma" from "~\\list-server-nohttp".
at Object.resolve (~\list-server-nohttp\node_modules\@angular-devkit\core\node\resolve.js:141:11)
at resolveProjectModule (~\list-server-nohttp\node_modules\@angular-devkit\build-angular\src\angular-cli-files\utilities\require-project-module.js:13:19)
at Object.requireProjectModule (~\list-server-nohttp\node_modules\@angular-devkit\build-angular\src\angular-cli-files\utilities\require-project-module.js:22:20)
at Observable.rxjs_1.Observable.obs [as _subscribe] (~\list-server-nohttp\node_modules\@angular-devkit\build-angular\src\karma\index.js:28:52)
at Observable._trySubscribe (~\list-server-nohttp\node_modules\rxjs\internal\Observable.js:44:25)
at Observable.subscribe (~\list-server-nohttp\node_modules\rxjs\internal\Observable.js:30:22)
at ~\list-server-nohttp\node_modules\rxjs\internal\util\subscribeTo.js:22:31
at Object.subscribeToResult (~\list-server-nohttp\node_modules\rxjs\internal\util\subscribeToResult.js:10:45)
at MergeMapSubscriber._innerSub (~\list-server-nohttp\node_modules\rxjs\internal\operators\mergeMap.js:82:29)
at MergeMapSubscriber._tryNext (~\list-server-nohttp\node_modules\rxjs\internal\operators\mergeMap.js:76:14)
at MergeMapSubscriber._next (~\list-server-nohttp\node_modules\rxjs\internal\operators\mergeMap.js:59:18)
at MergeMapSubscriber.Subscriber.next (~\list-server-nohttp\node_modules\rxjs\internal\Subscriber.js:67:18)
at Observable._subscribe (~\list-server-nohttp\node_modules\rxjs\internal\observable\scalar.js:6:20)
at Observable._trySubscribe (~\list-server-nohttp\node_modules\rxjs\internal\Observable.js:44:25)
at Observable.subscribe (~\list-server-nohttp\node_modules\rxjs\internal\Observable.js:30:22)
at MergeMapOperator.call (~\list-server-nohttp\node_modules\rxjs\internal\operators\mergeMap.js:39:23)
list-server-nohttp>
验证错误:…在snapshotSerializers选项中未找到node_modules\jest-preset-angular\AngularSnapshotSerializer.js。
没有找到 jest.config.js。
另外,如果 jest-preset-angular 的版本是 7 系列,可能会出现 “AngularSnapshotSerializer.js in the snapshotSerializers option was not found.” 的错误。在这种情况下,可能会通过 npm install -D jest-preset-angular@8 来解决。
list-server-nohttp> ng test
warning: unable to locate custom jest configuration file at path "~\list-server-nohttp\src\jest.config.js"
● Validation Error:
Module ~\list-server-nohttp\node_modules\jest-preset-angular\AngularSnapshotSerializer.js in the snapshotSerializers option was not found.
<rootDir> is: D:\develop\angular\angular7.x-jest\angular-examples\list-server-nohttp
Configuration Documentation:
https://jestjs.io/docs/configuration.html
list-server-nohttp>
- javascript – Angular 7 & Jest & Babel Integration over Jasmine/Karma – AngularSnapshotSerializer.js in the snapshotSerializers option was not found – Stack Overflow
验证错误:在setupFilesAfterEnv选项中未找到模块/src/setup-jest.ts。
缺少setup-jest.ts文件。
list-server-nohttp> ng test
● Validation Error:
Module <rootDir>/src/setup-jest.ts in the setupFilesAfterEnv option was not found.
<rootDir> is: ~\list-server-nohttp
Configuration Documentation:
https://jestjs.io/docs/configuration.html
list-server-nohttp>
参考文献
-
- briebug/jest-schematic: Angular schematic for adding Jest and the required files to an Angular CLI project
-
- Snapshot Testing · Jest
-
- module: esnext triggers the module warning diagnostic · Issue #748 · kulshekhar/ts-jest
Jest with Angular | Anders Skarby
typescript toMatchSnapshot fixture import angular jest
Tried to introduce Jest on Angular 7 – Tomohiro Uemura – Medium
Angular CLI: “ng test” with Jest in 3 minutes – codeburst
【Jest】AngularでJestを使用する – 開発覚書はてな版
Use Jest instead of Karma and Jasmine for your Angular project
Angular8
File not found: jest-preset-angular/InlineHtmlStripStylesTransformer.js · Issue #332 · thymikee/jest-preset-angular
2019-11-04 現在、次の Issue でうまくいかない模様。
Add Support for jest-preset-angular 8.0 · Issue #596 · just-jeb/angular-builders
How I do configure Jest to test my Angular 8 Project – itnext
Nrwl Nx
Angular 8 に関しては、npm test で動かすことはできるものの ng generate などのコマンドが未対応で Angular CLI を捨てるのに似た状況。Nrwl Nxの拡張機能を使うほうが正道かもしれませんね。
Nx 6.3: Faster Testing with Jest – Nrwl
Create Workspace with Angular defaults to Jest for testing · Issue #1698 · nrwl/nx
How to Set Up Angular Unit Testing with Jest – Amadou Sall
闲聊
-
- Node.js を触り始めて日が浅いが、semantic versioning の major.minor.patch の minor あたりは割と破綻してるんじゃないかなと思う
結局、依存VL合わせはうまくいかず、テストで動けばよいぐらい考えでよい気がしてきた
GitHub の @angular-builders/jest の package.json の dependency にある要求VLを見る限り、警告の出ない組み合わせは無理
→ どうあるべきかなと考えて GNU autoconf を思い出した。
Jest vs Karma
対比してみて、Karma の知識が高まった。良くも悪くも、Karma の方がブラウザを使ったテストができる分、趣旨が異なる
Jest の方は、機能的なリグレッションテストに特化する使い方かな?
ブラウザ非互換とかの目的には使えない。スナップショットの管理は便利かなという印象。
Karma のサポートブラウザに JSDOM とかある。スピードだけで言えば、Karma も時間短縮なのかもしれない
Google と Facebook のアプローチがツールにも出ている気はする
Google(Karma) … ブラウザやデバイス依存の機能など最新機能をどんどんリリースする
Facebook(Jest) … あまり最新機能を追う必要のないから、ブラウザの互換のテストはそこまで頑張らなくてよい
Angular8 は2019-11-04 現在、うまくいかなかった
今、この瞬間に Jestが超使いたい! ……というわけでもないので、別に良い
Jest押しの記事が増えているけれども、ちょっと一歩引いてみたほうが良さげな印象
もう少し、Karmaを使い込んでみて比較するのがいいか。