Testing jQuery.kinetic with Grunt and qUnit

30th Nov 2012

Testing jQuery.kinetic with Grunt and qUnit

I needed to add automated tests to jQuery.kinetic

I released jQuery.kinetic, a while ago. It's a simple jQuery plugin which adds smooth scrolling and decelleration to containers.

I built a series of manual test pages to make sure that subsequent releases didn't break the functionality but with recent requests for updates I decided to investigate writing some automated tests to catch potential issues quicker.

The issue with writing automated tests for this plugin is the fact that it's functionality is based on mouse and touch drag movements.

Selenium and SauceLabs

I began by writing some selenium tests using node's assert library and wd connecting to a locally running selenium server; managed to immitate the dragging movements using Selenium Web Driver's buttonDown, moveTo and buttonUp commands.

function dragOverElement(driver, elementId, cb){ // check element exists driver.elementByIdOrNull(elementId, function(err, element){ // place mouse inside element driver.moveTo(element, 300, 300, function(err){ // mouse buttonDown driver.buttonDown(function(){ // move (drag) mouse driver.moveTo(element, 10, 10, function(err){ // release to perform drag action driver.buttonUp(function(err){ // check kinetics internal settings // to see if the movement has created velocity driver.eval('$("#'+ elementId +'").data("kinetic-settings").velocity', function(err, velocity){ // return result cb(driver, err, velocity); }); }); }); }); }); }); }

Working really nicely, I decided to see if I could integrate the tests with the excellent Sauce Labs. The tests integrated well with the help of the sauce-node-demo project on Github and the related screen cast. And it was then I hit a brick wall. These mouse interactions did not work accross all the desktop browsers and very importantly the mobile devices which this plugin is especially used for.

Grunt's built in Server, qUnit Runner in PhantomJs

After stabalising my emotional state and peeling my head off the table I looked at alternative ways of checking that the functionality of the plugin worked as expected across all these devices.

qUnit soothed my soul, mocking the events generated by the interactions mousedown, mousemove, mouseup, touchstart, touchmove and touchend.

This looks a little like this:

var mdEvent = $.Event('mousedown'), mmEvent = $.Event('mousemove'), muEvent = $.Event('mouseup'); $.extend(mdevent, { target: target, clientx: from[0], clienty: from[1] }); $.extend(mmEvent, { target: target, clientX: to[0], clientY: to[1] }); $el .trigger(mdEvent) .trigger(mmEvent) .trigger(muEvent);

If you need to simulate a gradual drag then you would need to trigger multiple mousemove events but this is all I needed to get a velocity within the kinetic window.

Once I had written the tests to cover the core functionality I could then use some really useful in-built features of Grunt.js.

My default grunt task lints the JavaScript, starts an internal static server, then runs the qUnit tests through PhantomJs. I get feedback from all these steps within a few seconds which means I actually run them constantly because it's not a pain in the rear.

Travis CI integration

If you haven't taken a look at Travis CI yet I really recommend you do. They provide CI in the cloud for open-source projects as well as their pro service. It's easy to set up a hook from a Github project so that it runs automated tests on push.

Travis build status

They also provide a useful status image to show the project's current build status.

Build Status

if this image is red feel free to tweet me

Set up

The set up was pretty straight forward, you include the grunt dependency in your package.json and specify what command npm test should perform.

You also need a .travis.yml file in the root of your project which tells Travis what platform to run the tests on.

package.json

"devDependencies": { "grunt": "0.3.x", ... }, "scripts": { "test": "grunt --verbose" }

.travis.yml

language: node_js node_js: - 0.8

Issues

There is only one issue at the moment, that is that the PhantomJs runner occassionaly times out for no reason. But this looks to be resolved in the next major release of Grunt.

What Next

I finally need to hook up these tests with Selenium to check the qUnit results so that I can get them back in to Sauce Labs and check the qUnit results across all the supported desktop and mobile browsers.

p.s. I love Sauce Labs, what an amazing service!