読者です 読者をやめる 読者になる 読者になる

vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

【Ruby Gem】JasmineでJSテスト 2

今回はBackbone.Viewのテストについて(そろそろRuby Gem版だろうがスタンドアローン版だろうが関係ない内容になっていますが…)。

以前から使用しているテスト用のプロジェクトをGithubにあげてみました。 * https://github.com/masanori840816/sntTabTest

やること

  • Backbone.Viewで作成したボタンのクリックイベントをテストする

準備

前回の後半にも登場した、jasmine-jqueryを使ってテスト対象のHTMLを読み込みます。
また、テスト対象のViewと、ボタンのHTML要素を取得します。

javascriptSpec.js

describe("javascript.js", function() {
  var fileModel;
  var viewArrowLeft, viewArrowRight;
  var tabView;
  beforeEach(function () {
    loadFixtures('viewTest.html');
    fileModel = new FileModel();
    tabView = new TabView();
    viewArrowLeft = document.getElementById('arrow_button_left');
    viewArrowRight = document.getElementById('arrow_button_right');
  });
  〜省略〜

テスト対象のボタン部分のHTMLはこんな感じです。

viewTest.html

< main id='main' >
  < section id='tab_frame' >
    < input id='arrow_button_left' class='button_arrow' type='button' >
    〜省略〜
    < input id='arrow_button_right' class='button_arrow' type='button' >
  < / section >
  〜省略〜

ボタンの動作について

Viewはこのようになっていて、ボタン「arrow_button_left」を押すとintRightTabNumが-1され、「arrow_button_right」を押すと+1されます。
また、intRightTabNumが2以下なら「arrow_button_left」をdisabledにし、intRightTabNumが4以上なら「arrow_button_right」をdisabledにします。

〜省略〜
var intRightTabNum = 2;
〜省略〜
var TabView = Backbone.View.extend({
    el: '#main',
    events: {
    'click .button_arrow': 'moveTab',
    〜省略〜
    },
    moveTab: function (e){
        switch (e.target.id){
        case 'arrow_button_left':
            // 一つ左隣のTabを表示.
            intRightTabNum--;
            updateTabStyles();
            break;
        case 'arrow_button_right':
            // 一つ右隣のTabを表示.
            intRightTabNum++;
            updateTabStyles();
            break;
        }
    },
  〜省略〜
  this.updateTabStyles = function(){
        // 矢印ボタンのEnable/Disableを設定.
        document.getElementById('arrow_button_left').disabled = (intRightTabNum <= DEFAULT_RIGHT_TAB_NUM);
        document.getElementById('arrow_button_right').disabled = (intRightTabNum >= 4);
  〜省略〜

Spec

ボタンをクリックしたあとのデータを確認する

javascriptSpec.js

〜省略〜
it('Clicking arrow buttons', function () {
  // intRightTabNumのデフォルト値を確認する.
  expect(intRightTabNum).toEqual(2);
  viewArrowLeft.click();
  expect(intRightTabNum).toEqual(1);
  expect(viewArrowLeft.disabled).toEqual(true);

  viewArrowRight.click();
  expect(intRightTabNum).toEqual(2);
  expect(viewArrowRight.disabled).toEqual(false);

  viewArrowRight.click();
  expect(viewArrowLeft.disabled).toEqual(false);
  viewArrowRight.click();
  expect(intRightTabNum).toEqual(4);
  expect(viewArrowRight.disabled).toEqual(true);
});
〜省略〜

click()を各ボタンの要素(document.getElementById('arrow_button_left'))で実行して、その後のintRightTabNumと要素がdisabledになっているかを確認しています。

ボタンをクリックした時に特定のメソッドが呼ばれているかを確認する

javascriptSpec.js

〜省略〜
it('Check if clicked events fire', function () {
  spyOn(tabView, 'moveTab');
  // Viewにイベントを関連付け.
  tabView.delegateEvents();
  viewArrowLeft.click();
  expect(tabView.moveTab).toHaveBeenCalled();
});
〜省略〜

以前使ったSpyを使って、Viewの「moveTab」が呼ばれたかを確認します。

ポイントは「tabView.delegateEvents();」でイベントをViewに関連付けるところで、これをしないとメソッド自体は呼ばれているのに、expect〜でテストに失敗します。
また、Spyを使うとテスト内でメソッドが置き換わってしまうので、上のボタンクリック後のデータを確認するテストとは別に分けたほうが良いかと思います。

参考

Jasmine

Javascriptのボタンイベント発火