来自给定选择器的nod​​eList的Jasmine测试事件监听器函数

时间:2016-11-17 11:37:39

标签: javascript unit-testing testing jasmine jasmine-jquery

我有以下代码在nodeList的给定数组中侦听keydown事件。

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'
};

我正在使用它:obj.method('.someClassNames'); 但现在我想完全测试它,包括触发keydown事件。如何附加事件监听器,然后在给定的dom节点上触发keydown事件,以便我的Jasmine测试可以工作?如何在此处创建一些虚拟html代码,然后在其上触发事件?我期待写这种类型的测试=>

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(){});

我的标记正在跟随

var html = '<div class="someClassNames">'+
    '<div class="indicator">'+
      '<li>text</li>'+
    '</div>'
  '</div>';

我假设我需要触发以下keydown事件,但我不确定如何触发给定标记并检查测试说明。

var e = new window.KeyboardEvent('keydown', {
      bubbles: true
});
Object.defineProperty(e, 'keyCode', {'value': 32}); 

我非常擅长使用Jasmine进行测试,但我找不到任何可以帮助我测试这种情况的示例。我希望我的例子能说清楚。

1 个答案:

答案 0 :(得分:1)

几点观察:

  • 请注意,callbackFunc实际上已分配给onkeydown
    元素的属性。因此你可能想窥探上 element.onkeydown而不是obj.keyListener

  • 有时,UI元素的渲染可能在spec之后发生 已经跑了。

  • 因此,为了确保元素存在,我已经使用了 setTimeout with a jasmine clock
  • 如果你真的想测试你的obk.keyListener,请尝试使用 像here
  • 这样的匿名函数

这是我如何运行。我使用鼠标悬停,因为我懒惰:)

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内容:

<div class="someClassNames">
  <div class="indicator">
    <li>text</li>
    <br/> </div>
</div>