Geeks With Blogs

News Please visit me at my new blog!!

profile for Aligned at Stack Overflow, Q&A for professional and enthusiast programmers
"free in Christ Jesus from the law of sin and death." Romans 8:2 (ESV) Check out the Falling Plates video on YouTube.
more about the Gospel
And then listen to Francis Chan speaking at LifeLight in SD.



Programming and Learning from SD

I’m using jQuery UI’s droppable for drag and drop capabilities. I wanted to be able to test it with Jasmine, but I couldn’t find a way to mock it. I found Jasmine jQuery, but wasn’t able to figure out how to spyOn or mock

$('#jQueryElement').droppable({
    accept: function (d) {
        return accept(d);
    },
    drop: function (event, ui) {
        drop(event, ui);
    }
});

So I created a wrapper for this function. I’ve found that creating wrappers is an easy way to make things testable and to remove coupling to libraries (dialogs, jQuery UI elements, Wijmo elements, or anything else you can try). It’s a little more work, but an easy way, if spyOn doesn’t work for you.

namespace.DroppableWrapper = function (jQueryElement, acceptMethod, dropMethod) {
    'use strict';
    var accept = function (d) {
            return acceptMethod(d);
        },
        drop = function (event, ui) {
            dropMethod(event, ui);
        },
        init = function () {
            jQueryElement.droppable({
                accept: function (d) {
                    return accept(d);
                },
                drop: function (event, ui) {
                    drop(event, ui);
                }
            });
        };
    return {
        Accept: accept,
        Drop: drop,
        Init: init
    };
};

Here is how I consume it in my view model:

acceptDialogDrop = function (d) {
    // only accept dialogs in the area
    if (d.attr("id") === "insDialog") {
        return true;
    }
    return false;
},
 dialogDrop = function (event, ui) {
    dialogIdCount++;
    var ld = new namespace.LayoutDialogModel(99999 + dialogIdCount, 
       event.pageX, event.pageY, 400, 300, 'New Dialog', 'dialog', layoutId, []),
        viewModel = namespace.DashboardUtils.DialogVmFactory(
                  ld, userId, true, null, $(window).width(), $(window).height());
    dialogs.push(viewModel);
},

afterInit = function () {
    // setup the droppable area
    droppableAreaElement = $("#" + droppableAreaId);
    if (droppableAreaElement.length === 0) {
        throw new Error("The droppable area with DOM Id: " + droppableAreaId + " is needed and was not found");
    }
    droppable = new namespace.DroppableWrapper(droppableAreaElement, acceptDialogDrop, dialogDrop);
    droppable.Init();
},

Here is a test:

describe("Dialog Dropped", function () {
    // the dialog was dropped on the page.
    it("should add a new dialog to the screen", function () {
        // Arrange
        vm.Init(true, 1, 1, 'droppableArea');
        vm.AfterInit();
        var event = {},
            ui = {};
        event.pageX = 5;
        event.pageY = 10;
        // Act
        vm.GetDroppable().Drop(event, ui);
        // Assert
        expect(vm.Dialogs().length).toBe(3);
    });
});
Let me know if you have a different way of doing this and what you think of this approach. Posted on Tuesday, March 26, 2013 9:47 AM Unit Testing , JavaScript , Mocking | Back to top


Comments on this post: Making jQuery UI Droppable Testable

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Aligned | Powered by: GeeksWithBlogs.net