2

I want to test the Form submission by using jasmine.
The form is defined in a backbone view which looks like this (1).
I implemented the following test (2), but I am not sure how it is effective.
For example if the textarea is empty onError function should be called.
Any ideas the best way to test the submission of a form, in this context, by using jasmine?


(1)

var MyView = Backbone.View.extend({

    events: {
        'focus [data-tid="message"]' : 'focusForm',
        'blur [data-tid="message"]' : 'blurForm',
        'submit   form' : 'submitForm'
    },

    focusedClass: 'is-form-focused',

    focusForm: function () {
        this.$el.find('form').addClass(this.focusedClass);
    },

    blurForm: function () {
        this.$el.find('form').removeClass(this.focusedClass);
    },

    submitForm: function (event) {
        event.preventDefault();

        var formElement =  event.currentTarget,
            message = this.$el.find('.message');

        if (formElement.checkValidity && !formElement.checkValidity()) {
            this.onError();
        } else {
            // makes a POST ajax call
            backendController.submitFeedback(message.val()).done(this.onSuccess).fail(this.onError);

        }
    },

    onError: function () {
        this.$el.find('.message').focus();
    },

    onSuccess: function () {
        this.$el.find('.message').val('');
        this.$el.find('form').removeClass(this.focusedClass);
    }
});

(2)

describe('When Submit button handler fired', function () {
    beforeEach(function () {
        this.popupSpy = sinon.spy();
        this.view.render();
        this.view.$el.find('form').on('submit', this.popupSpy);
        this.view.$el.find('form').trigger('submit');
    });
    it('submitForm should be called', function () {
        expect(this.popupSpy.callCount).toBe(1);
    });
});
Lorraine Bernard
  • 13,000
  • 23
  • 82
  • 134

1 Answers1

4

In your example you are testing your own test.

I rather would propose something like this:

// code simplified and no tested
describe("When Submit button handler fired", function () {
  it("submitForm should be called", function () {
    this.view.render();
    spyOn( this.view, "submitForm" );
    this.view.$el.find("form").submit();
    expect( this.view.submitForm ).toHaveBeenCalled();
  });
});

Update

Probably my above code is not gonna work, due like in spying over Router methods the handlers are seted at initializing time so any further spy is not gonna be called.

You should spy at class level and before you have instantiated your View:

// code simplified and no tested
describe("When Submit button handler fired", function () {
  it("submitForm should be called", function () {
    spyOn( MyView.prototype, "submitForm" );

    this.view = new MyView();
    this.view.render();

    this.view.$el.find("form").submit();

    expect( MyView.prototype.submitForm ).toHaveBeenCalled();
  });
});
Community
  • 1
  • 1
fguillen
  • 36,125
  • 23
  • 149
  • 210
  • +1 thanks for your response. Actually I get the following error `Expected spy submitForm to have been called` are you sure about the code you wrote?. thanks – Lorraine Bernard Aug 14 '12 at 15:18
  • _// code simplified and no tested_ ;).. I'm just offering an starting point, likely you should clean up a little bit. – fguillen Aug 14 '12 at 15:29
  • I can work in a _working example_ but you should offer me a playground, you can fork [this jsFiddle](http://jsfiddle.net/fguillen/63WPu/). – fguillen Aug 14 '12 at 15:32
  • @LorraineBernard check my update. And if it still not working check my above comment. – fguillen Aug 14 '12 at 15:37
  • this time it seems to work, but there is a huge problem: I get an infinite loop on the page browser which is making the test :( – Lorraine Bernard Aug 14 '12 at 15:50