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.