2016-08-05 48 views
6

我正在编写的组件需要根据是否按下ctrl来更改其行为。Reactjs中的测试窗口keydown事件

我使用window.onkeydown事件,而是从Simulate阵营测试utils的不允许我来分发事件对window。我也试过window.dispatchEvent(new KeyboardEvent('keydown', { keyCode: 17 }));,但摩卡/节点不识别KeyboardEvent

有没有办法测试window.onkeydown使用React Test Utils?如果没有,是否有更好的方法在摩卡上做节点?

下面是一些代码来ilustrate问题:

describe('On Keydown',() => { 
    it('fires the event',() => { 
     // Component 
     const Component = class extends React.Component { 
      constructor(props) { 
       super(props); 
       this.state = { key: false }; 
       window.addEventListener('keydown', e => this.setState({ key: true })); 
       window.addEventListener('keyup', e => this.setState({ key: false })); 
      } 
      render() { 
       return <span>test</span> 
      }; 
     }; 
     // Rendering 
     const rendered = renderIntoDocument(<Component/>); 
     // Firing event 
     expect(rendered.state.key).to.equal(false); 
     // Error here 
     Simulate.keyDown(window, { keyCode: 17 }); 
     expect(rendered.state.key).to.equal(true); 
    }); 
}); 

回答

1

如果你设置你的听众喜欢window.addEventListener('keydown', myFunc)那么你只需要测试myFunc,你实际上并不需要测试addEventListener调用您的功能时,一个​​发生。通过始终将事件绑定到函数(而不是在回调中工作),测试更直接(您正在测试您的代码),并且您可以在完成它们时移除事件侦听器。

+1

有关测试的事实compononent应该监听keydown事件是什么?也许这应该是规范的一部分。如果没有,可以删除'addEventListener',并且组件仍然会通过测试。 – jokka

+0

有效的点。就我个人而言,我依靠自动化测试来处理这些事情,并让单元测试测试逻辑。 –

+0

够好。它只是让我感到有些迷惑,事件处理程序基本上是一个私有方法,测试依赖于它。但这并不重要。 – jokka

1

我解决了这个问题,这要感谢David的评论,只是忽略了事件并将状态设置为我需要的测试。我还发现了一种测试未来窗口事件的不同方法。创建一个扩展EventEmitter的窗口类,您可以收到类似于ctrlwindow.emit('keydown',{keyCode: 17})的keydown/keyup事件。

这是我 _test_helper.js的代码:

import jsdom from 'jsdom'; 
import chai from 'chai'; 
import EventEmitter from 'events'; 

const doc = jsdom.jsdom('<!doctype html><html><body></body></html>'); 

const windowClass = class extends EventEmitter { 
    constructor() { 
     super(doc.defaultView); 
     this.__defineSetter__('onkeydown', f => this.on('keydown', f)); 
     this.__defineSetter__('onkeyup', f => this.on('keyup', f)); 
    } 
    addEventListener (e,f) { 
     this.on(e,f); 
    } 
}; 

const win = new windowClass(); 

global.document = doc; 
global.window = win; 

Object.keys(window).forEach((key) => { 
    if (!(key in global)) { 
    global[key] = window[key]; 
    } 
});