Question

I'm trying to use Jasmine (gem with yaml config) to test a Backbone.js application. I'm using the underscore templating like the Todo example.

template: _.template($('#item-template').html())

My problem is that I'm unable to have the templates loaded before my models/views so the template call causes those classes to error out at load.

I've read about the jasmine-jquery plugin to do fixtures but the problem is that my src files (models/views) are being loaded and failing before I ever get the the spec file and am able to setup the fixtures needed.

How do I get the templates loaded early enough they can be used for the reset of my classes?

Was it helpful?

Solution

You can delay the jQuery selector until you need it:

render: function(){
  var templateHtml = $(this.template).html();
  _.template(templateHtml);
}

Or you can run the selector when the view initializes:

initialize: function(){
  this.template = _.template($(this.template).html());
}

Or, if you really want to leave your code as-is and have the selector evaluate when you define the View, you can wrap all of your Backbone code in a function that you call when you want to initialize your entire app code... such as a jQuery $(function(){} function on your real HTML page, or a beforeEach function in your Jasmine tests:

MyApp = (function(){
  var myApp = {};

myApp.MyView = Backbone.View.extend({ template: _.template($("#item-template").html()) // ... });

return myApp; });

Then in your app, to start this up:

$(function(){
  var myApp = MyApp();
  new myApp.MyView();
  // ...
});

And in your Jasmine test:

describe("how this thing works", function(){
  beforeEach(function(){
    var myApp = MyApp();
    this.view = new myApp.MyView();
    // ...
  });
});

Once you have one of these solutions in place, you can use something like Jasmine-jQuery to load your fixtures.

FWIW: I tend to use a combination of these techniques, as needed.

OTHER TIPS

The one issue with the first part of the accepted answer is that the template gets compiled every time the view is instantiated. One alternative is to set the template directly on the prototype of the view:

app.TodoView = Backbone.View.extend({
    initialize: function(){
        if (!app.TodoView.prototype.template) {
            app.TodoView.prototype.template = _.template($("#item-template").html());
        }
    }            
});

This way, the template is compiled once, when the first instance of TodoView is instantiated.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top