Testing jQuery code (in particular jQuery plugins) can be a lot of fun. Below you will find a few tips on setting up the testing environment on MacOS X and running tests with Mocha, Chai and jsdom.
Mocha vs other test frameworks
Why did I choose Mocha? Jasmine also looks very nice and many people are happy with it, but its development seems to be a little slow lately. Mocha has good documentation and all the features I could ask for, so I decided to give it a try instead. Also let’s not forget Mocha has a nyan cat reporter:

Getting ready
Ideally the jQuery plugin we are going to test should be object-oriented. Luckily there is no need to reinvent the wheel, since there are ready, well-designed solutions to structure a plugin in an object-oriented way. I found this boilerplate quite useful. But I also wanted it to accept a method and/or options when calling the plugin:
$("element").myplugin(); or $("element").myplugin({ option1: true, option2: true }); or $("element").myplugin("some_other_method"); or $("element").myplugin("some_other_method", { option1: true, option2: true }); |
So here is a yet another take on a jQuery plugin boilerplate (with inline comments):
https://gist.github.com/3871611
Setting up Mocha
While setting up Mocha I first learned about package.json. It’s a file where npm packages store various metadata. This is where we can define all dependencies for our jQuery project. It looks something like this:
{
"name": "jquery-bar-rating",
"description": "Minimal, light-weight jQuery ratings."
"version": "0.1.0",
"main": "./jquery.barrating",
"devDependencies": {
"mocha": "*",
"chai": "*",
"jsdom": "*",
"jquery": "*"
}
} |
With a package.json file in place installing Mocha and all its dependencies is as simple as running “npm install” in the project directory. I assume npm is installed on the system. If not, installing npm is explained on the nodejitsu blog.
Bootstrapping DOM
Usually jQuery acts on DOM elements. But what if we want to execute tests outside of the browser environment, on the command line? jsdom (JavaScript implementation of the W3C DOM) will fill that gap. With jsdom you will be able to bootstrap a DOM by fetching a remote document with jsdom.env() method or creating it from scratch:
var jsdom = require("jsdom").jsdom; var doc = jsdom('<html><body></body></html>'); var window = doc.createWindow(); |
Writing tests
Mocha works with a few different assertion libraries. I picked Chai.js, because I liked its BDD assertion styles. You can choose between “expect” or “should” interfaces for writing tests or mix both. “Expect” interface is recommended over “should”, because it is fully compatible with Internet Explorer once you would decide to run tests in the browser.
describe('bar rating plugin on show', function () { beforeEach(function () { $('#rating').barrating('show'); }); it('should be initialized', function () { expect($('#rating').data('barrating')).to.be.a('object'); }); }); |
Tests should live in a spec file inside the “test” directory. See an example of a spec file with a few Mocha tests.
Running tests
./node_modules/mocha/bin/mocha |
Don’t forget to add “node_modules” to .gitignore if you are using git.
More information
Visit Mocha and Chai documentation for more details on writing tests.
Nils N. Haukås says:
Great post!
When testing client-side dom-manipulation should one use jquery click events for pressing buttons or instead run the functions bound to those buttons directly?
Cheers,
Nils
netboy says:
Good question.
Most of the times I trigger events, which comes natural with jQuery plugins and is quite convenient.
Owzzz says:
You mention you can run functions like so:
But how would you pass any expected params to those functions.. the object in the second call just overwrites the defaults/options object
You could add another conditional:
netboy says:
hi Owzzz,
This was only to demonstrate different ways of calling the plugin. I updated the post to make it more clear.