来自给定选择器的 nodeList 的 Jasmine 测试事件侦听器函数

Jasmine test event listener function for nodeList from given selector

我有以下代码侦听给定节点列表数组中的按键事件。

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

我假设我将需要触发以下按键事件,但我不确定如何在给定标记上触发并查看测试说明。

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

我对使用 Jasmine 进行测试非常陌生,我找不到任何可以帮助我测试这种情况的示例。我希望我的例子能说明问题。

很少观察到:

  • 注意callbackFunc实际上是赋给了onkeydown
    元素的属性。因此你可能想监视
    element.onkeydown 而不是 obj.keyListener

  • 有时 UI 元素的渲染可能发生在规范已经完成之后 运行.

  • 因此,为了确保元素存在,我使用了 用茉莉花设置超时 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>