Testing jQuery.kinetic with Grunt and qUnit
30th Nov 2012
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.
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!