Search code examples
jqueryjasminejasmine-jquery

How to write Jasmine test cases for jQuery on() method


I am new to Jasmine. Appreciate if someone can please brief me about how to write test cases for the following jquery code:

$(document).on('startViewDetail', function(event, transactionId) {
  $(document).trigger('ClearMessages', [{
    containerName: 'EnterDetails'
  }]);
  logger.debug('view transaction detail started');
  startViewTransaction(transactionId);
});

var startViewTransaction = function(transactionId){...}

Thanks in anticipation!

Jasmine test case for the above code:

describe('Working with transaction details component', function() {
    beforeEach(function() {
        spyOnEvent(document, 'startViewDetail');
        $(document).trigger('startViewDetail', mockDataObject.transactionId);
    });
    it('test startViewTransaction', function() {
        spyOn(document, 'startViewTransaction').and.callFake(function(e) {
           console.log("This is a spy call for startViewTransaction");
          });
        expect(document.startViewTransaction).toHaveBeenCalled();
          expect(document.startViewTransaction).toHaveBeenCalledWith(mockDataObject.transactionId);
    });
}); 

Solution

  • This post has a broad scope so I'd start with one approach

    So here are a few things you need to ask before you want to unit test your code

    • Are you testing the functionality of your code or the functionality of the event binding
    • If it is testing the event binding, then I'm afraid the jQuery has already thoroughly unit-tested it

    I personally do not feel the need to test jQuery methods. That simply diverts the aim to test the actual hand-written code. Having said that here is a sample test I've prepared based on your code.

    $(document).on('startViewDetail', function(event, transactionId) {
      $(document).trigger('ClearMessages', [{
        containerName: 'EnterDetails'
      }]);
      console.log('view transaction detail started');
      startViewTransaction(transactionId);
    });
    
    var startViewTransaction = function(transactionId) {
      console.log('started transaction with transactionId: ' + transactionId);
    }
    
    describe('sample test', function() {
      it('test startViewTransaction', function() {
        spyOn(window, 'startViewTransaction').and.callFake(function(e) {
          console.log("This is a spy call for startViewTransaction");
        });
        var obj = $(document);
        obj.trigger('startViewDetail', 1);
        expect(window.startViewTransaction).toHaveBeenCalled();
        expect(window.startViewTransaction).toHaveBeenCalledWith(1);
      })
    });
    

    EDIT: Answering the comments:

    • startViewDetail is not a method, it is an event name, so your line spyOnEvent(document, 'startViewDetail'); is invalid. Remove it as it doesn't serve any purpose.
    • I wonder why you are spying on the document object, the stray/stand-alone functions of javascript always go under window. So switch your spy to go against window rather than document.
    • You should not use this line $(document).trigger('startViewDetail', mockDataObject.transactionId); in beforeEach, this should be used in your test like I used above.
    • spyOn(document, 'startViewTransaction').and.callFake(function(e) {
 console.log("This is a spy call for startViewTransaction");
 }); also needs modification, it should go against window object and NOT document.
    • Same is the case with expect(document.startViewTransaction).toHaveBeenCalled();
 expect(document.startViewTransaction).toHaveBeenCalledWith(mockDataObject.transactionId);
      • Jasmine documentation is the best source to understand how beforeEach, it, afterEach blocks work.