Incandescent Software

tales of web & veterinary software development

Extending Jasmine Matchers

Jasmine is a behavior-driven development framework for testing JavaScript from Pivotal Labs (I believe Rajan Agaskar was/is the original author). I’ve been using Jasmine for a while now to test my JavaScript code. Today I ran into interesting situation where I wanted to test events bound to jQuery element. Basically by writing code like this:

1
2
3
$('#el').bind('click', function (e) {
  // handler code goes here
});

I wanted to know if element $(‘#el’) had any events attached to it. I looked around but couldn’t find any predefined matchers in jasmine or jasmine-jquery to accomplish it. I realized that it’s pretty easy to extend jasmine and define my own matchers (which is pretty cool). Here is how you can do it:

First create your new matchers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var eventMatchers = {
  toHaveEvent: function (event) {
    var data = jQuery.data(this.actual.get(0));
    for (obj in data) {
      if (data.hasOwnProperty(obj)) {
        for (eventName in data[obj].events) {
          if (data[obj].events.hasOwnProperty(eventName)) {
            if (event === eventName) {
              return true;
            }
          }
        }
      }
    }
    return false;
  }
};

Then in your spec add your matchers inside beforeEach:

1
2
3
4
5
describe("Element", function () {
  beforeEach(function () {
    this.addMatchers(eventMatchers);
  });
});

That’s it! Now you can use your new matchers inside your spec. In this case I was able to use it like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
describe("Element", function () {
  beforeEach(function () {
    this.addMatchers(eventMatchers);
  });

  describe("when event attached", function () {
    it("should contain attached event", function () {
      setFixtures("<div id='el'></div>");
      $('#el').bind('click', function () {});
      expect($('#el')).toHaveEvent('click');
    });
  });
});