pcjuzer pcjuzer - 7 months ago 189
Javascript Question

HTML Canvas Unit testing

How can I unit-test Javascript that draws on an HTML canvas? Drawing on the canvas should be checked.


As discussed in the question comments it's important to check that certain functions have been invoked with suitable parameters. pcjuzer proposed the usage of proxy pattern. The following example (RightJS code) shows one way to do this:

var Context = new Class({
    initialize: function($canvasElem) {
        this._ctx = $canvasElem._.getContext('2d');

        this._calls = []; // names/args of recorded calls

    _initMethods: function() {
        // define methods to test here
        // no way to introspect so we have to do some extra work :(
        var methods = {
            fill: function() {
            lineTo: function(x, y) {
                this._ctx.lineTo(x, y);
            moveTo: function(x, y) {
                this._ctx.moveTo(x, y);
            stroke: function() {
            // and so on

        // attach methods to the class itself
        var scope = this;
        var addMethod = function(name, method) {
            scope[methodName] = function() {
                scope.record(name, arguments);

                method.apply(scope, arguments);

        for(var methodName in methods) {
            var method = methods[methodName];

            addMethod(methodName, method);
    assign: function(k, v) {
        this._ctx[k] = v;
    record: function(methodName, args) {
        this._calls.push({name: methodName, args: args});
    getCalls: function() {
        return this._calls;
    // TODO: expand API as needed

// Usage
var ctx = new Context($('myCanvas'));

ctx.moveTo(34, 54);
ctx.lineTo(63, 12);

ctx.assign('strokeStyle', "#FF00FF");

var calls = ctx.getCalls();


You can find a functional demo here.

I have used a similar pattern to implement some features missing from the API. You might need to hack it a bit to fit your purposes. Good luck!