Custom jQuery matchers in Jasmine


Implementing your custom matchers (or custom assertions in case of xUnit-like frameworks) is a very good testing practice. In theory, as you’re verifying if a given expectation is correct, ‘.toBeTrue()’ is the only matcher you need. In practice however, using convoluted constructs like:

expect(someVariable != undefined).toBeTrue();

severely hinders readability of your tests. Thats why more clear and explicit matchers like:


come in handy. Such neat matchers are of course more comfortable to use, but their real power comes from revealing the intent of a test – what is one of primary goals (and strengths) of the whole Behavior Driven Development concept.

Different frameworks provide different sets of built in matchers. The one provided by Jasmine is relatively bare-bone, but it is not a bad thing, as it offers neat and robust mechanism for creating your own matchers when needed without polluting an API with a myriad of predefined matchers for all occasions (most of which you’ll never use). In this post I’ll show how to built a custom jQuery matcher library for Jasmine (provided by my jasmine-jquery plugin).

The simplest way to create a custom matcher, presented in Jasmine docs, is to use “.addMatchers()” method in your “beforeEach()” block:

beforeEach(function() {
    toHaveClass: function(className) {
      return this.actual.hasClass(className);

“this.actual” is automatically set by Jasmine to the variable on which we set expectations via “expect(…)” method. Other parameters for your matcher can be set as usual, as input parameters of your callback function (see “className” in above example). Your matcher function must return a boolean value indicating if it succeeded or not.

Now, when you have your first jQuery matcher defined, you can use it in your tests like this:

it('should have class "my-class"', function() {
  var myElement = $(<div class="my-class"></div>');

instead of much less readable:

it('should have class "my-class"', function() {
  var myElement = $('<div class="my-class"></div>');

Jasmine also automatically allows your custom matchers to be inverted by prepending them with “.not”, so you can also use your freshly created jQuery matcher like this:

it('should have class "my-class"', function() {
  var myElement = $('<div class="my-class"></div>');

So far so good. Your tests are now much more readable and their intent is expressed more clearly. However, when written in such a way (placed in “beforeEach()”), your matchers are local to your test file. In more specific cases this may be not so bad, but in case of e.g. jQuery related matchers, we will want to re-use them in many tests across many projects, so making a local copy each time is definitely not an option.

The solution to the above problem is simple – as you could see, “addMatchers()” method takes a JS object as a parameter. So instead of declaring this object locally, lets move it to a separate file:

in my_jquery_matchers.js:

jQueryMatchers = {
  toHaveClass: function(className) {...},
  toBeVisible: function() {...},

in my_spec.js:

beforeEach(function() {

Now the matchers are neatly separated into their own file, allowing you to reuse this “library” among may test files. And as Jasmine allows you to use “beforeEach()” at arbitrarily high level – not only in your “describe” block but also at a level global to your whole test file, or even at a level of the test runner itself (global for all test files executed by this runner), you need to invoke “addMatchers()” only once, so your tests stay reasonably DRY.

When creating custom matchers specific to your code, above solution is sufficient. However, a matcher library for an external framework like jQuery feels more like a part of the test framework core, not as a part of test suite. Therefore, two problems that don’t bother me that much in case of my custom matchers, make me not fully satisfied in case of jQuery matcher library. First, variable containing matchers (jQueryMatchers in the above example) pollutes global namespace. Second, having to instantiate a part of the core library inside one of your “beforeEach()” blocks is awkward – these blocks should rather contain code related to your SUT (system under tests), not a framework’s boilerplate.

So, let’s take it one step further and “hack” our jQuery matchers into Jasmine framework directly. The idea may seem scary at first, but it is really straightforward. Jasmine keeps all its core matchers in a separate object called “Matchers”. All you need to do is to add your new matchers directly to the “Matchers” object’s prototype instead of passing them via “addMatchers()” method:

jasmine.Matchers.prototype.toHaveClass: function(className) {
  return this.actual.hasClass(className);

Now the only thing you need to do is to include the file in a test runner (the same way you include Jasmine core or jQuery library) and our jQuery matchers are transparently available in all test files, without polluting the namespace or any of “beforeEach()” blocks. (I’d like to reiterate here that for matchers related to your custom SUT only, this may be a little overkill, but it is a neat and elegant solution when creating “core” matcher libraries, reused among many projects).

OK, we’re almost there with our solution, however, I’ll apply two more tweaks that will make our library more robust.

First annoyance to fix is the way Jasmine displays failed assertions for our jQuery matchers. Inside our matcher, this.actual is a jQuery element, and Jasmine by default can’t do anything smarter than dump it to string in an error message. So when you try:

var myElement = $(<div class="wrong-class"></div>');

you’ll get:

Expected { 0 : HTMLNode, length : 1, context : HTMLNode, selector : '#sandbox', init : Function, jquery : '1.4.2', size : Function, toArray : Function, get : Function, pushStack : Function, each : Function,
a _LOT_ of similar jQuery element dump code here
, width : Function } to have class 'some-class'.

This makes an error message almost impossible to comprehend. However, it may be quite easily fixed by using a simple trick – modifying “actual” variable inside our matcher before returning:

jasmine.Matchers.prototype.toHaveClass: function(className) {
  var result = this.actual.hasClass(className);
  this.actual =
      $('<div />').append(this.actual.clone()).html();
  return result;

What we do with “this.actual” above, is conversion from jQuery element into a plain HTML string. This results in much more explanatory message, leaving no doubt why our test didn’t pass:

Expected '<div class="wrong-class"></div>' to have class 'some-class'.

The last problem left for us to solve is a situation when there is naming collision between our jQuery matchers and built-in Jasmine matchers. E.g. I’d like to have a matcher called “toContain()” that will check if a Query element contains another element, specified by a jQuery selector, but Jasmine already has a “toContain()” matcher that checks if an array contains specified item.

The simplest way to solve this issue is just to check what matcher names are already taken by Jasmine and to avoid potential collisions by renaming our jQuery matcher to e.g. “toContainElement()” or “toContainSelector()”; However, I’m quite stubborn and I want a simple “toContain()”. I’m also lazy, and I don’t want to check all built-in Jasmine matchers – and what’s even more important, I don’t want a naming collision when new matchers are added to Jasmine core in future.

Another simple trick will do it:

var builtInMatcher = jasmine.Matchers.prototype.toContain;

jasmine.Matchers.prototype.toContain = function() {
  if (this.actual instanceof jQuery) {
    // our jQuery matcher code here
    // return results

  return builtInMatcher.apply(this, arguments);

If the tested variable is a jQuery element our jQuery matcher will be used, otherwise we pass the control to the original Jasmine matcher. Also, invoking original matcher by using “apply(this, arguments)” ensures that even if our overlapping jQuery matcher and original Jasmine matcher expect different number of arguments the above code will still work correctly.

And that’s all. The full, more polished implementation can be found in my jasmine-jquery library (it contains also support for HTML fixtures – see my previous post about fixtures in Jasmine for a more detailed overview).



  1. Christian Williams said

    Awesome blog post!

    One issue however: extending the jasmine.Matchers prototype is not supported for adding custom matchers. You can easily do this with a global beforeEach() function which calls this.addMatchers().

    You bring up a couple other interesting points — the desire to modify the behaviour of toContain() and the way that jQuery matchers are pretty-printed. I’d like to address both of those needs directly in the framework. See and

    In the meantime, consider changing the behaviour of jasmine.Env.contains_ instead of changing the toContain matcher so you can avoid the matcher wrapping issues.

    Again, thanks for a great blog post.

  2. velesin said

    Thanks for your remarks!

    As for extending jasmine.Matchers prototype: this is already changed to using this.addMatchers() (I didn’t update this post afterwards).

    Extending jasmine.Matchers prototype resulted in problems with jasmine-gem. It must be done before jasmine.getEnv() is executed but in case of jasmine-gem all libraries specified in jasmine.yml file are loaded after getEnv() is invoked, which resulted in my additional jQuery matchers being not properly loaded.

    So, I refactored the code to add my jQuery matchers via standard addMatchers() method (invoked in a global beforeEach(), placed directly in my library’s source file, so users don’t have to do it manually).

    However, the manipulation of this.actual and invocation of jasmine.Matchers.prototype.toContain from inside my matcher is still there (so the current implementation is better, but still not perfect).

    I’ll take a look at your idea of changing jasmine.Env.contains_, however I targeted a bit more general solution. Right now I overlap not only toContain but also toBe matcher. I also wanted to be future proof in case you’ll add some new matchers to the core Jasmine library that will collide with my jQuery related matchers.

    PS: thanks for interest in this post and for adding stories, esp. the one that will allow custom pretty printing!

  3. Chris said

    Hey, great post! Just noticed a small type:

    var myElement = $(‘);
    should be:
    var myElement = $(”);

RSS feed for comments on this post

Comments are closed.

%d bloggers like this: