I have following code which listens for keydown event in given array of nodeList.
var obj = {
method: function(nodeSelector) {
var nodeContainers = document.querySelectorAll(nodeSelector);
var keyListenerFunc = this.keyListener.bind(this);
this.bindListener(nodeContainers, keyListenerFunc);
},
isListNode: function (evt){
return evt.target.nodeName.toLowerCase() === 'li';
},
isContainer: function(evt){
return evt.target.parentNode.classList.contains(this.indicatorClass);
},
keyListener: function(evt) {
if (evt.keyCode === 32 && (this.isContainer(evt) && this.isListNode(evt))) {
evt.preventDefault();
evt.target.click();
}
},
bindListener: function(targets, callbackFunc) {
[].forEach.call(targets, function(item) {
item.addEventListener('keydown', callbackFunc);
});
},
indicatorClass: 'indicator'
};
I'm using it like: obj.method('.someClassNames');
But now I want to test it completely including the triggering of keydown event. How can I attach event listener and then trigger keydown event on given dom nodes so that my Jasmine tests would work ? How can I create some dummy html code here and then trigger event on it ? I am expecting to write tests of this type =>
it('It should put event listeners on each carousel passed to the service', function(){});
it('It should call event.preventDefault', function(){});
it('It should call event.target.click', function(){});
My markup is follwing
var html = '<div class="someClassNames">'+
'<div class="indicator">'+
'<li>text</li>'+
'</div>'
'</div>';
I am assuming that I am going to need to trigger following keydown event but I am not sure as to how to trigger is on the given markup and check in the test description.
var e = new window.KeyboardEvent('keydown', {
bubbles: true
});
Object.defineProperty(e, 'keyCode', {'value': 32});
I am very much new to testing with Jasmine and I couldn't find any examples that would help me test this scenario. I hope my example makes it clear.
few observations:
Note that the callbackFunc is actually assigned to the onkeydown
attribute of the element. Hence you may want to spy on the
element.onkeydown rather than obj.keyListener
Sometimes the render of the UI element may take place after spec has been run.
here is how I've it running. I've used mouseover as I'm lazy :)
var obj = {
testVar : "Object",
method: function(nodeSelector) {
var nodeContainers = document.querySelectorAll(nodeSelector);
var keyListenerFunc = this.keyListener.bind(this);
this.bindListener(nodeContainers, keyListenerFunc);
},
isListNode: function(evt) {
return evt.target.nodeName.toLowerCase() === 'li';
},
isContainer: function(evt) {
return evt.target.parentNode.classList.contains(this.indicatorClass);
},
keyListener: function(evt) {
console.log('Yo! You hovered!');
},
bindListener: function(targets, callbackFunc) {
targets.forEach(function(item) {
item.addEventListener('mouseover', callbackFunc, false);
});
},
indicatorClass: 'indicator'
};
describe('Sample tests', function() {
//this ensures you have the element set up
beforeEach(function() {
jasmine.clock().install();
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200;
setTimeout(function() {
obj.method('div.indicator');
}, 0);
});
it('It should put event listeners', function() {
jasmine.clock().tick(10);
var ele= document.getElementsByClassName("indicator")[0];
spyOn(ele, 'onmouseover').and.callThrough();
$('.indicator').trigger('mouseover');
expect(ele.onmouseover).toHaveBeenCalled();
expect(typeof ele.onmouseover).toBe('function');
});
});
HTML CONTENT:
<div class="someClassNames">
<div class="indicator">
<li>text</li>
<br/> </div>
</div>