Angular2でDIしてテストを書いたけどhtmlファイルの重複をなんとかしたかった。
index.htmlとindex.test.htmlの重複排除, テスト(Jasmine), System.js, Angular2, Dependency Injection
前回↓の記事の続きです。
Angular2でDI(依存性注入)してテスト(Jasmine)を書いてみた。
前回は本番用のindex.htmlとテスト用のindex.test.htmlはほぼ同じ内容で書いて用意しておく、
みたいな感じでしたが、それだとindex.htmlに何か変更を加えたらindex.test.htmlも直さないといけなくなるので、
そういうかったるい重複もなんとかならないかなと思って色々やってみたらできた、というのが今回の趣旨です。
(できたと思ったらChromeはOKでFirefoxではNGでした。他のブラウザでは試していません。)
↑修正しました。Windows10のChrome, Firefox, Edgeで動作確認済みです。
こういうの需要があるのかわかりませんがまとめておかないと僕が忘れてしまうので。
まずは準備
npm init -y npm install angular2 systemjs jquery system-text --save npm install live-server typescript jasmine-core --save-dev
前回の記事から増えているのはsystem-text
です。これはSystem.jsでテキストファイルを
importできるようにするためのプラグインです。
(root)/src/system.config.js
System.config({ baseURL: '/', paths: { '*': 'src/*', 'node:*': 'node_modules/*' }, map: { 'text': 'node:system-text/text.js', 'jquery': 'node:jquery/dist/jquery.js' }, packages: { 'app': { defaultExtension: 'js' } }, meta: { '*.html': { loader: 'text' } } });
今回のケースではSystem.config()
は上記のようになります。
1.map
にtext
の記述を加えています。
2.meta
プロパティを追加して、.html
ファイルをimportするときはsystem-text
プラグインを使うよう指定しています。
(root)/src/index.html (npm startのときに呼ばれる)
<html> <head> <title>Angular 2</title> <script src="../node_modules/systemjs/dist/system.src.js"></script> <script src="../node_modules/angular2/bundles/angular2.dev.js"></script> <script src="system.config.js"></script> </head> <body> <script> System.import('app/app'); </script> <my-app>loading...</my-app> </body> </html>
npm start
したときに呼ばれるファイルです。Jasmineの気配は微塵もありません。テストする気は無いのかとさえ思えます。
(root)/src/index.test.html (npm testのときに呼ばれる)【今回のエントリーの要です】
<title>Angular 2 Test</title> <link rel="stylesheet" href="../node_modules/jasmine-core/lib/jasmine-core/jasmine.css"> <script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script> <script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script> <script src="../node_modules/jasmine-core/lib/jasmine-core/boot.js"></script> <script src="../node_modules/systemjs/dist/system.src.js"></script> <script src="system.config.js"></script> <script> System.import('jquery') .then(function () { return System.import('./index.html') }) .then(function (html) { $('inject-here').append(html); }) .then(function () { return System.import('app/app.spec').then(window.onload); }); </script> <inject-here></inject-here>
npm test
したときに呼ばれるファイルです。<html>
タグもありません。
このファイルがロードされるとまずはJasmineのCSSとJavaScriptライブラリを読み込みます。
その後System.import()
を使うためにSystem.jsのライブラリとsystem.config.js
を読み込みます。
System.import()
の部分では、
1.jQueryのライブラリを読み込んで、
2.index.html
を文字列として読み込んで、
3.<inject-here>
タグに流し込んで、
4.app.js
のテストファイルであるapp.spec.js
を読み込む、
という処理を行なっています。
(app.spec.js
はJasmineを使っているので.then(window.onload)
は決まり文句です)
これにより本番用のindex.html
からテスト用の記述を排除し、index.html
をどのように変更しても
index.test.html
は影響を受けない状態となりました。これはJasmineのテストを書くときに汎用性のある手法かもしれません。
(当初これがChrome以外では動作しなくてかなり悩んだのですが、Promiseチェーンの最後のapp.spec.js
のimportもreturn
する
のがコツみたいです。詳細はよくわかりません)
package.jsonの"scripts"
"scripts": { "test": "live-server --open=src/index.test.html", "start": "live-server --open=src", "tsc": "./node_modules/.bin/tsc -p . -w" },
本番はnpm start
、テストはnpm test
です。(npm run tsc
でTypeScriptファイルをコンパイルします)
以上です。ありがとうございました。