2016-08-05 86 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]; 
    } 
});