KarmaでDOM操作のテストをする

このページでは、KarmaでDOM操作のテストをする方法を紹介します。

テスト対象

例として、下記のコードをテストしたいとします。index.htmlを開くと、メッセージが表示されるものです。

<!-- index.html -->
<!DOCTYPE html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <p id="message"></p>
  <script src="js/jquery.js">
  <script src="js/app.js">
  <script>
    $(function() {
      app.showMessage('init');
    }());
  </script>
</body>
</html>
// app.js
(function(global) {
  'use strict';
  global.app = {
    showMessage: function(message) {
      $('#message').text(message);
    }
  };
}(this.self));

フォルダ構成は下記の通りです。appフォルダにテスト対象のコードを入れ、specフォルダにテストコードを書いていきます。

Project
  ├─ app
  │    ├─ index.html
  │    └─ js
  │       ├─ jquery.js
  │       └─ app.js
  └─ spec

テスト環境構築

karma-html2js-preprocessorのインストール

karma-html2js-preprocessorはKarmaのプラグインであり、HTMLファイルをjsから読み込むことができるようになります。

$ npm install karma-html2js-preprocessor --save-dev

karmaの設定ファイルを変更し、filesとpreprocessorsにHTMLファイルを追加します。

// karma.conf.js
module.exports = function(config) {
  config.set({
    ...
    files: [
      'app/js/jquery.js',
      'app/js/app.js',
      'app/*.html'
      'spec/**/*.js',
    ],
    preprocessors: {
      'app/*.html': ['html2js']
    },
    ...
  });
};

テストコードの記述

specフォルダにテストコードappSpec.jsを作成し、beforeEachでdocumentのbodyにindex.htmlを読み込みます。テスト対象のコードでjQueryを使用しているので、テストコードからも使用しています。

// appSpec.js
describe('app', function() {
  var text = 'text';
  beforeEach(function() {
    document.body.innerHTML = __html__['app/index.html'];
  });
  it('should show message', function() {
    app.showMessage(text);
    expect($('#message').text()).toEqual(text);
  });
});

画像読み込みエラー

index.htmlで画像ファイルを読み込んでいる場合、テスト実行時にWARNINGが表示されます。

<!-- index.html -->
<!DOCTYPE html>
<html>
  ...
  <img src="img/image.png">
  ...
</html>
$ npm test
...
WARN [web-server]: 404: /img/image.png
...

このエラーが表示されないようにするには、プロキシを介して画像ファイルを読めるようにします。画像ファイルはファイルの変更監視が必要ないのと、ブラウザ起動時にscriptタグで読み込まないので、watchとincludedをfalseにします。プロキシには、ベースとなるフォルダのパスを基点にするために’base’を付加したパスを設定します。

// karma.conf.js
module.exports = function(config) {
  ...
  files: [
    'app/js/jquery.js',
    'app/js/app.js',
    'app/*.html',
    {pattern: 'app/**/*.png', watched: false, included: false, served: true},
    'spec/**/*.js'
  ],
  proxies: {
    '/img/': '/base/img/'
  },
  ...
};

コメントを残す