Sunday, November 27, 2011

BDDing Backbone with Sinon.js Fake Servers

‹prev | My Chain | next›

Up today, I continue my efforts to BDD a simple appointment list view in my calendar Backbone.js application. The only significant remaining feature is more of a bug—when switching from month view to list view, the list view is retaining the collection filter that only requests appointment from a single month.

In jasmine-speak, I might say:
    it("requests all appointments (forgets previous filter)");
Since I am faking the request to the server, how I go about expressing my expectations is going to be a little tricky. Tricky, perhaps, but I do not have many options. I am forced to spy on the AJAX request that goes out. Or maybe not...

In my setup, I am using sinon.js to stub out AJAX requests to anything under the "/appointments" URL space:
  describe("list view", function() {
    beforeEach(function() {
      // ...
      server.respondWith('GET', /\/appointments/,
         [200, { "Content-Type": "application/json" }, JSON.stringify(doc_list)]);
      server.respond();
    });
    it("requests all appointments (forgets previous filter)");
  });
If I change my setup to only respond when the "/appointments" URL is called (i.e. without filtering query parameters), then I ought get the desired result:
  describe("list view", function() {
    beforeEach(function() {
      // ...
      server.respondWith('GET', '/appointments',
         [200, { "Content-Type": "application/json" }, JSON.stringify(doc_list)]);
      server.respond();
    });
    it("requests all appointments (forgets previous filter)");
  });
In fact, I do get my desired result because my earlier list view tests fail:

To make those pass again, I need my application view to clear my collection's date and for the collection to not pass a date query parameter when the date is not set:
    var Application = Backbone.View.extend({
      // ...
      setListView: function() {
        this.view = 'list';
        this.collection.setDate();
        this.collection.fetch();
        return this.render();
      },
      // ...
    });

    var Appointments = Backbone.Collection.extend({
      // ...
      fetch: function(options) {
        options || (options = {});

        var data = (options.data || {});
        if (this.date) options.data = {date: this.date};

        // ...
        return Backbone.Collection.prototype.fetch.call(this, options);
      },
      // ...
    });
With that, I have all of my tests passing:

And, all appointments are now shows on the list view:

With that out of the way, I am ready to tackle a few things that need verifying in Recipes with Backbone. Tomorrow. For now, I have much proof-reading ahead of me.



Day #218

No comments:

Post a Comment