Greg's Blog

helping me remember what I figure out

Backbone-jasmine - Part 2 - Testing Routes

| Comments

The code for this post can be found over at GitHub

Routes

Before dealing with the submission and fetching results, a quick detour into routes where the application is glued together. What follows are some tests to make sure the routes defined are being triggered when we navigate to the url, starting with the index action:

describe('Application routes', function() {
    beforeEach(function() {
        this.router = new BackboneJasmine.ApplicationRouter();
        this.routerSpy = sinon.spy();

        try {
            Backbone.history.start({silent: true, pushState: true});
        } catch(e) {
        }

        this.router.navigate('/javascript/spec/SpecRunner.html');
    });

    afterEach(function() {
        this.router.navigate('/javascript/spec/SpecRunner.html');
        Backbone.history.stop();
    });

    it('should by default call the index route', function() {
        this.router.bind('route:index', this.routerSpy, this);
        this.router.navigate('', {trigger: true});

        expect(this.routerSpy).toHaveBeenCalledOnce();
        expect(this.routerSpy).toHaveBeenCalledWith();
    });

});

And here’s the ApplicationRouter file to make the test pass:

var BackboneJasmine = BackboneJasmine || {};

BackboneJasmine.ApplicationRouter = Backbone.Router.extend({
    routes: {
        '': 'index',
    },

    index: function() {

    }
});

A search route is also needed, test first:

it('should call the search route when #search is navigated to', function() {
    this.router.bind('route:search', this.routerSpy, this);
    this.router.navigate('search/1/2', {trigger: true});

    expect(this.routerSpy).toHaveBeenCalledOnce();
    expect(this.routerSpy).toHaveBeenCalledWith('1','2');
});

And the code to make it pass:

routes: {
    '': 'index',
    'search/:realm/:character': 'search'
},

...

search: function(realm, character) {
}

Now that the scaffold for the application is done, it’s time to flesh it out starting with the index route and making it initialise the search interface (SearchView). Start off with editing our initial beforeEach and afterEach

beforeEach(function() {
    this.router = new BackboneJasmine.ApplicationRouter();
    this.searchViewStub = sinon.stub(BackboneJasmine, 'SearchView').returns(new Backbone.View());

    ...
});

afterEach(function() {
    this.searchViewStub.restore();
    ...
});

Now for the actual test:

describe('index', function() {
    beforeEach(function() {
        this.router.index();
    });

    it('should created the search view', function() {
        expect(this.searchViewStub).toHaveBeenCalledOnce();
    });
});

A stub was created for our SearchView and we are now watching this and want to make sure it gets called when we call the index function. To make the test pass simply instantiate the SearchView in the ApplicationRouter.js file:

index: function() {
    this.searchView = new BackboneJasmine.SearchView();
},

That’s it for now with regards to the routes, I’ll coming back to these once the search component has been completed.

Demo

In the root of the code there’s a little demo index.html file that you can browse to if you are using the ‘node app.js’ server, just go to: http://localhost:3000/index.html.