JasmineでSammy.jsアプリをテストする

RSpecライクなJavascript用BDDフレームワークJasmineで、SinatraライクなWebフレームワークSammy.jsで作られたアプリをテストしてみる。

非同期処理を伴わない場合

Sammy.js app
var app = $.sammy(function() {
    this.get('#/', function() {
        $('h1').html("hoge");
    });
};

ルートの実行が終了すると、event-context-afterトリガーが起こる。
この発生を検知してからテストを行えばOK。

Jasmine
describe('testing sammy.js app', function() {

    beforeEach(function() {
        $('body').append('<div id="jasmine"><h1>Replace me</h1></div>');
        app.executed = false;
        app.bind('event-context-after', function() {
            app.executed = true;
        });
    });

    afterEach(function() {
        $('div#jasmine').empty().remove();
    });

    it('should set h1', function() {
        app.run('#/');

        waitsFor(function() {
            return app.executed;
        }, "app doesn't stop", 10000);

        runs(function() {
            expect($('h1').html()).toEqual('hoge');
        });
    });

非同期処理を伴う場合

Sammy.js app

var app = $.sammy(function() {

    this.get('#/async', function() {
       // 非同期処理
       this.load('/public/data/myfile.txt')
       .then(function(content) {
         $('h1').text(content);
       });
    });	
});

ルート内で非同期処理を行うと、非同期処理の終了を待たずしてevent-context-afterトリガーが起こってしまう。
なので独自にルートの実行が終了したことを通知するイベントトリガーを作る必要がある。

var app = $.sammy(function() {

    this.get('#/async', function() {
       this.load('/public/data/myfile.txt')
       .then(function(content) {
         $('h1').text(content);
		 
     // ルートの実行が終了したことを知らせる
	 this.trigger('executed');
       });
    });	
});
Jasmine
describe('testing sammy.js app', function() {

    beforeEach(function() {
        $('body').append('<div id="jasmine"><h1>Replace me</h1></div>');
        app.executed = false;
        
        app.bind('executed', function() {
            app.executed = true;
        });
    });

    afterEach(function() {
        $('div#jasmine').empty().remove();
    });

    it('should be h1 text equals to public/data/myfile.txt', function() {
        app.run('#/async');

        waitsFor(function() {
            return app.executed;
        }, "app doesn't stop", 10000);

        runs(function() {
             expect($('h1').html()).toEqual(myfile-data);
        });
    });
});