CLOVER🍀

That was when it all began.

Karmaでkarma-html2js-preprocessorを使ってHTMLを読み込んでテストする

Karmaを使うとブラウザ上でのテストが行えますが、さらにPreprocessorのうちkarma-html2js-preprocessorを使用するとHTMLファイルを使ってテストができるようになるようです。

Karma - Preprocessors

GitHub - karma-runner/karma-html2js-preprocessor: A Karma plugin. Convert HTML files into JS strings to serve them in a script tag.

参考)
イマドキのJSテスト - karma + karma-html2js-preprocessorでブラウザ/DOMを絡めたUIテストを実行する編 〜 JSおくのほそ道 #031

CLIでJavaScriptのテストを実行する時にHTML fixtureを利用する方法。Karma... | niwaringo() {Tumblr}

KarmaでDOM操作のテストをする | shoarai.com

karma+mocha+power-assertでDOM操作を含むユニットテストをES6で書く | WebDesign Dackel

JavaScriptでHTMLを読み込んで、DOMを使ったテストができるようになる代物だとか。

というわけで、簡単に試してみます。

準備

Karmaおよびkarma-html2js-preprocessorを使うわけですが、個人的にBrowserifyとBabelは入れておきたいため、ここまでをセットにします。テスト自体にはMocha、Chai、そしてDOM操作にはjQueryを使用することにします。

以下、各種モジュールインストール。

## Babel
$ npm install --save-dev babelify babel-preset-es2015
$ npm install --save babel-polyfill

## Browserify
$ npm install --save-dev browserify watchify

## Mocha, Chai
$ npm install --save-dev mocha chai

## Karma
$ npm install --save-dev karma karma-browserify karma-chai karma-mocha
$ npm install --save-dev karma-chrome-launcher

## Karma Html2Js Preprocessor
$ npm install --save-dev karma-html2js-preprocessor

## jQuery
$ npm install --save jquery

今回は、「karma-html2js-preprocessor」をインストールするところがポイントです。

Babelの設定ファイルも用意して

$ echo '{ "presets": ["es2015"] }' > .babelrc

Karmaの設定ファイルも作成します。

$ ./node_modules/karma/bin/karma init

自動生成後からいじったところは、このあたりですね。

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['browserify', 'mocha', 'chai'],

    browserify: {
      transform: ['babelify']
    },


    // list of files / patterns to load in the browser
    files: [
      'src/**/*.js',
      'test/**/*-test.js',
      'html/**/*.html'
    ],


    // list of files to exclude
    exclude: [
    ],


    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'src/**/*.js': ['browserify'],
      'test/**/*-test.js': ['browserify'],
      '**/*.html': ['html2js']
    },

今回のテーマでいくと、「files」にHTMLファイルを含めるようにすることと、「preprocessors」でHTMLに対して「html2js」を指定しておくことがポイントです。

npm runで、Karmaが起動するように指定。

  "scripts": {
    "test:karma": "karma start"
  },

あとは、ソースコード、テストコード、HTML配置用のディレクトリを作成して、準備完了。

$ mkdir src test html

テスト対象のコードとHTML

テスト対象は、特定の要素をクリックすると、別の要素内に子要素とテキストを追加するものにします。
src/click-add.js

import "babel-polyfill";

import $ from "jquery";

export function bindClick() {
    $("#button").bind("click", () => {
        $("#messages").append("<div class='added-message'>Hello Karma!!</div>");
    });
};

HTMLファイルは、こんな感じの単純なものを用意。
html/index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Karma Test Code</title>
</head>
<body>
  <div id="messages"></div>
  <input id="button" type="button" value="クリック!!">
</body>
</html>

このうえで、先ほどのコードを動かすようにします。

テストコード

で、それを行うためのテストコードがこちら。3回クリックしてみます。
test/click-add-test.js

import "chai";
import $ from "jquery";

const should = chai.should();

import { bindClick } from "../src/click-add.js";

describe("click-add test", () => {
    it("click triple from HTML file.", () => {
        document.body.innerHTML = __html__["html/index.html"];

        bindClick();

        let button = document.getElementById("button");
        Array.from(Array(3), (v, k) => k + 1).forEach(i => button.click());

        let messages = document.getElementsByClassName("added-message");
        messages.should.to.have.lengthOf(3);

        let messageTexts = Array.from(messages).map(e => e.textContent);
        messageTexts
            .should
            .deep
            .equal(["Hello Karma!!", "Hello Karma!!", "Hello Karma!!"]);
    });
});

ポイントはこの部分で、

        document.body.innerHTML = __html__["html/index.html"];

karma-html2js-preprocessorを利用すると__html__という表記が利用できるようになり、これでHTMLファイルが読み込めます。読み込んだ内容を、documentに反映すればDOMとして構築される、と。

documentがグローバルなので、beforeやafterなどでdocument.body.innerHTMLをクリアした方がよいかも?みたいな記述も見かけましたが、変わらなかったというかやるならテスト内でないと意味がなさそうです…。

まとめ

karma-html2js-preprocessorを使って、HTMLファイルを使った簡単なテストを書いてみました。

Karmaを使うとブラウザ上でテストはできますが、あらかじめDOMがないと実際には厳しいことも多いでしょうから、これは便利そうですね。