Reactコンポーネントのテストをenzymeを使って書きます。
ボタンがクリックされたとき、テキストフィールドの入力値を引数に親コンポーネントのメソッドが呼び出されることを検証するテストです。
Sample.jsx
class Sample extends React.Component {
handleClickEvent() {
const text = document.querySelector('#text-field').value
this.props.methodExpectedToBeCalled(text)
}
render() {
return (
<div>
<input id="text-field" type="text"/>
<button onClick={()=>{this.handleClickEvent()}}>post</button>
</div>
)
}
}
うまくいくテスト
mountメソッドで、作った要素にattachする
Sample.test.js
test('成功するしWarningも出ないテスト', () => {
const methodSpy = jest.fn()
const component = mount(
<Sample methodExpectedToBeCalled={methodSpy} />,
{ attachTo: document.body.appendChild(document.createElement('div')) } // ここと、
)
component.find('input').getDOMNode().setAttribute('value', 'hoge') // ここ
component.find('button').simulate('click')
expect(methodSpy).toHaveBeenCalledWith('hoge')
})
mountメソッドは実際にDOMを構築します。attachToでコンポーネントを追加する場所を指定することで、document.querySelectorで要素を見つけられるようになります。テストからはgetDOMNode()で要素を取得できます。
うまくいくけどWarningが出るテスト
mountメソッドで、bodyにattachする
Sample.test.js
test('成功するけどWarningが出るテスト', () => {
const methodSpy = jest.fn()
const component = mount(
<Sample methodExpectedToBeCalled={methodSpy} />,
{ attachTo: document.body } // ここ
)
component.find('input').getDOMNode().setAttribute('value', 'hoge')
component.find('button').simulate('click')
expect(methodSpy).toHaveBeenCalledWith('hoge')
})
attachToの対象がdocument.bodyだと以下のWarningが出ます。bodyにするな要素指定せよということです。
実行結果
console.error node_modules/react-dom/cjs/react-dom.development.js:530
Warning: render(): Rendering components directly into document.body is discouraged, since its children are often manipulated by third-party scripts and browser extensions. This may lead to subtle reconciliation issues. Try rendering into a container element created for your app.
うまくいかないテスト
shallowメソッドで、changeイベントをsimulateする
Sample.test.jsx
test('失敗するテスト', () => {
const methodSpy = jest.fn()
const component = shallow(
<Sample methodExpectedToBeCalled={methodSpy} />
)
component.find('input').simulate('change', {target: {value: 'hoge}}) // ここ
component.find('button').simulate('click')
expect(methodSpy).toHaveBeenCalledWith('hoge')
})
shallowを利用した場合、実際のDOMは生成されないためDOMNodeが取得できません。そのためinput要素が取得できないという結果になります。shimulateメソッドはイベントをシミュレートするものでDOMには影響しません。
実行結果
TypeError: Cannot read property 'value' of null
42 | key: "handleClickEvent",
43 | value: function handleClickEvent() {
> 44 | var text = document.querySelector('#text-field').value;
| ^
45 | this.props.methodExpectedToBeCalled(text);
46 | }
47 | }, {
少しハマったのでメモ。