コンポーネントのキーバインド機能をテストしています。コンポーネントはかなり単純なkeyup
のイベントリスナーであり、コンポーネントを非表示にするredux actionを起動します。
ここでコードをクリーンアップして、関連する情報のみにしました。 store dispatchを使用してアクション呼び出しを行うだけでテストに合格することはできますが、もちろんこのテストの目的に反します。 Enzymeを使用して、適切なイベントデータ(keyup
のキーコード)を使用してesc
イベントをシミュレートしていますが、以下のエラーに遭遇します。
MyComponent.js
import React, {Component, PropTypes} from 'react';
import styles from './LoginForm.scss';
import {hideComponent} from '../../actions';
import {connect} from 'react-redux';
class MyComponent extends Component {
static propTypes = {
// props
};
componentDidMount() {
window.addEventListener('keyup', this.keybindingClose);
}
componentWillUnmount() {
window.removeEventListener('keyup', this.keybindingClose);
}
keybindingClose = (e) => {
if (e.keyCode === 27) {
this.toggleView();
}
};
toggleView = () => {
this.props.dispatch(hideComponent());
};
render() {
return (
<div className={styles.container}>
// render code
</div>
);
}
}
export default connect(state => ({
// code
}))(MyComponent);
MyComponent-test.js
import React from 'react';
import chai, {expect} from 'chai';
import chaiEnzyme from 'chai-enzyme';
import configureStore from 'redux-mock-store';
import {mount} from 'enzyme';
import {Provider} from 'react-redux';
import thunk from 'redux-thunk';
import {MyComponent} from '../../common/components';
import styles from '../../common/components/MyComponent/MyComponent.scss';
const mockStore = configureStore([thunk]);
let store;
chai.use(chaiEnzyme());
describe.only('<MyComponent/>', () => {
beforeEach(() => {
store = mockStore({});
});
afterEach(() => {
store.clearActions();
});
it('when esc is pressed HIDE_COMPONENT action reducer is returned', () => {
const props = {
// required props for MyComponent
};
const expectedAction = {
type: require('../../common/constants/action-types').HIDE_COMPONENT
};
const wrapper = mount(
<Provider store={store} key="provider">
<LoginForm {...props}/>
</Provider>
);
// the dispatch function below will make the test pass but of course it is not testing the keybinding as I wish to do so
// store.dispatch(require('../../common/actions').hideComponent());
wrapper.find(styles.container).simulate('keyup', {keyCode: 27});
expect(store.getActions()[0]).to.deep.equal(expectedAction);
});
});
エラー:このメソッドは、単一ノードでのみ実行されることを意図しています。代わりに0が見つかりました。
reactWrapper.single(/Users/[name]/repos/[repoName]/webpack/test.config.js:5454:18 <-webpack:///~/enzyme/build/ReactWrapper.js:1099:0)
reactWrapper.simulateで(/Users/[name]/repos/[repoName]/webpack/test.config.js:4886:15 <-webpack:///~/enzyme/build/ReactWrapper.js:531:0)
コンテキストで。 (/Users/[name]/repos/[repoName]/webpack/test.config.js:162808:55 <-webpack:///src/test/components/MyComponent-test.js:39:40)
そのエラーは、言うように、1以外の任意の数のノードで実行すると発生します。
JQueryと同様に、find
呼び出しはいくつかのノードを返します(実際には、find
セレクターが検出したノードの数を知っている単一のラッパーです)。また、0ノードに対してsimulate
を呼び出すことはできません!または複数。
解決策は、セレクター(wrapper.find(styles.container)
の_styles.container
_)が0ノードを返す理由を把握し、正確に1を返すことを確認し、simulate
が次のように機能することです。あなたは期待しています。
_const container = wrapper.find(styles.container)
expect(container.length).to.equal(1)
container.simulate('keyup', {keyCode: 27});
expect(store.getActions()[0]).to.deep.equal(expectedAction);
_
Enzymeの debug メソッドはここで非常に便利です。 console.log(container.debug())
またはconsole.log(container.html())
を実行して、テスト中にコンポーネントが期待どおりにレンダリングされることを確認できます。