Trying to test that an event handler gets called on a clicked element with Jasmine. Have a “Pad” object that contains a DOM element “PadElement”, which gets clicked. The event handler is a method on the Pad object:
GRAPH.Pad = function(graphDiv, graph) {
this.graph = graph;
this.clickHandler = function(e) {
console.log('padElement clickHandler called');
//this.graph.createVertex(e.clientX, e.clientY);
};
this.padElement = GRAPH.padElement(graphDiv, this.clickHandler);
}
GRAPH.padElement = function(graphDiv, clickHandler) {
//Initialize pad
var NS="http://www.w3.org/2000/svg";
var pad=document.createElementNS(NS,"svg");
pad.setAttributeNS(null, 'id', 'pad');
graphDiv.appendChild(pad);
pad.addEventListener('click', clickHandler)
return pad;
}
The Jasmine test:
var testDiv = document.createElement('div');
var testGraph = new GRAPH.Graph(testDiv);
var testPad = new GRAPH.Pad(testDiv, testGraph);
it('has its clickHandler function called when its padElement is clicked',
function() {
spyOn(testPad, "clickHandler");
simulateClick(testPad.padElement);
//testPad.clickHandler();
expect(testPad.clickHandler).toHaveBeenCalled();
});
However, the test FAILS. Note that the event listener does get called (console.log writes successfully with a mouse click and with simulateClick), AND if I just call the testPad.clickHandler() directly Jasmine’s spy can pick it up. But what happens during the actual test? Does the event handler invocation get transferred to a different object at runtime? What’s the right way to do this?
You are actually testing that
GRAPH.padElementcalls the suppliedclickHandlerand not thatthis.clickHandlerofGRAPH.Padis called byGRAPH.padElement. How I would do that isThis may sound little different to what you are trying to achieve. But in ideal unit testing world you should be testing each unit independently, so I would first test that
padElementdoes what it’s supposed to do (as above) and then write another test to make sureGRAPH.Padis passing correct handler topadElement. Now to do that I would not createpadElementdirectly from withinGRAPH.Padbut somehow inject it from outside and then mock it in the jasmine specs. If you are not clear on this part let me know and I can put some code together for you.