4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

enzymeでテキストフィールドの値が取得できない

Posted at

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 |   }, {

少しハマったのでメモ。

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?