2017-04-09 7 views
1

Reactとmaterial uiでコンポーネントを構築しました。私はReactとReduxを使用しています。TextFieldマテリアルのUI要素をテストする方法React Jest?

index.jsxは次のようになります。

import React, { PropTypes, Component } from 'react'; 
import TextField from 'material-ui/TextField'; 

class InputSearch extends Component { 
    ... 

    render() { 
    return (
     ... 
     <TextField 
     defaultValue={this.props.keyword} 
     ref={(input) => { this.input = input; }} 
     autoFocus 
     hintText='Type a keyword' 
     errorText={this.state.errorText} 
     floatingLabelText='Search for keyword' 
     style={styles.textField} 
     /> 
    ); 
    } 
} 

InputSearch.propTypes = { 
    keyword: PropTypes.string.isRequired, 
    resetSearch: PropTypes.func.isRequired, 
    searchBooks: PropTypes.func.isRequired, 
    toggleResultsOpacity: PropTypes.func.isRequired, 
    firstSearch: PropTypes.bool.isRequired, 
}; 

export default InputSearch; 

私はユニットテストの構築にAirbnb酵素と冗談を使用しています:

import React from 'react'; 
import { render } from 'react-dom'; 
import { Provider } from 'react-redux'; 
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; 
import configureStore from '../store/configureStore'; 
import Routes from '../routes/routes'; 
import '../styles/main.less'; 

const store = configureStore(); 
render(
    <Provider store={store}> 
    <MuiThemeProvider> 
     <Routes /> 
    </MuiThemeProvider> 
    </Provider>, 
    document.getElementById('app'), 
); 

私のコンポーネントInputSearchは次のようになります。 InputSearchコンポーネントへの私のテストでは、次のようになります。

import React from 'react'; 
import { shallow, mount } from 'enzyme'; 
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; 
import TextField from 'material-ui/TextField'; 
import InputSearch from '../components/InputSearch/InputSearch'; 

const resetSearchMock = jest.fn(); 
const searchBooksMock = jest.fn(); 
const toggleResultsOpacityMock = jest.fn(); 

const setup =() => { 
    const props = { 
    keyword: '', 
    resetSearch: resetSearchMock, 
    searchBooks: searchBooksMock, 
    toggleResultsOpacity: toggleResultsOpacityMock, 
    firstSearch: true, 
    }; 

    const wrapper = shallow(<MuiThemeProvider><InputSearch {...props} /></MuiThemeProvider>); 

    return { 
    props, 
    wrapper, 
    }; 
}; 

describe('Initial test',() => { 
    test('Shows error message when input search is empty.',() => { 
    const { wrapper, props } = setup(); 
    expect(wrapper.find(TextField).getValue()).toEqual(''); 
    }); 
} 

しかし、私は次のエラーを取得しています:

TypeError: wrapper.find(...).getValue is not a function

誰も私がチェックするための正しい方法を達するのを助けることができますマテリアルの値はTextFieldですか?

答えて

0

私はモカ、酵素およびチャイを使用して数日間の試験を行っています。 material-uiのテストに伴う問題は、inturn reactコンポーネントなので、通常のhtml要素をテストしてもテストできません。

あなたはあなたがすると仮定しているものであるTestFieldはvalue小道具を持っていることに気づくことができ、あなたのための全体の要素を出力します

console.log(wrapper.find('TextField').debug()); 

このようなコンポーネント全体を印刷することにより、どのような性質の変化を見つけることができます

describe('Initial test',() => { 
    test('Shows error message when input search is empty.',() => { 
    const { wrapper, props } = setup(); 
    expect(wrapper.find(TextField).props().value).to.equal(''); 
    }); 
} 
:この propだからコードは次のようになります TextField

に値を決めたものですので、ご確認ください

これはTextFieldコンポーネントのテスト方法です。

あなたが役に立ったら嬉しいです。

+0

こんにちは@Farhaan Bukhsh、それは良い先端 "デバッグ"機能です。しかし、私のTextFieldコンポーネントは "value"プロパティを持たず、 "defaultValue"プロパティしか持っていません。新しい値を渡して「変更」イベントをシミュレートしてテストするにはどうすればよいですか? –

+0

あなたが持っている '' prop''であれば、 '' value''を '' defaultValue''に置き換えることができます。また、私はあなたに ''材料-ui''を更新することを提案します。現在、「変更」イベントを「シミュレート」することは非常に簡単です。 '' Farhaan''を '' Farhaan''に置き換えます。 '' Farhaan''は '' Farhaan''を '' Farhaan''に置き換えます。 '' TextField''の中で、値を簡単に確認することができます。 –

1

酵素shallowは1レベルしかレンダリングしないため、あなたのケースではMuiThemeProviderInputSearchがレンダリングされます。 Jestスナップショット機能を使用して、何がレンダリングされたかをwrapper内で確認できます。

expect(wrapper.('InputSearch').dive().find(TextField).getValue()).toEqual(''); 

か、MuiThemeProviderでコンポーネントをラップし、直接InputSearchをレンダリングいけない:あなたは、コンポーネントのコンテンツをレンダリングするために酵素を強制的にdiveを使用することができます。スタイルpropを追加するだけです。今すぐInputSearchはトップレベルのコンポーネントであり、Enzymeはそのコンテンツをレンダリングします。

const setup =() => { 
    const props = { 
    keyword: '', 
    resetSearch: resetSearchMock, 
    searchBooks: searchBooksMock, 
    toggleResultsOpacity: toggleResultsOpacityMock, 
    firstSearch: true, 
    styles: {textfield: {fontSize:10}} 
    }; 

    const wrapper = shallow(<InputSearch {...props} />); 

    return { 
    props, 
    wrapper, 
    }; 
}; 
+0

こんにちは@AndreasKöberle、あなたの答えに感謝します。私は "浅い"は1レベルしか深く描かないことを知っていましたが、私は酵素 "マウント"も試みました。私はあなたの提案を "ダイビング"で試しましたが、これは解決しません。私も "MuiThemeProvider"を削除しようとしましたが、動作しません。あなたは材料uiとTextFieldのサンプルをコードしてみていただけますか?あなたの助けに感謝。 –

+0

だから、私は酵素のドキュメントで 'getValue'を見つけることができません。代わりに 'prop( 'value')'を探しているかもしれませんか? –

+0

Hey @ AndreasKöberle、 "getValue"は、 "TextField"コンポーネント値を取得するためのメソッドに組み込まれた重要なUIです。 –

1

もっと良い解決策がある場合は、私の質問に答えてください。いくつかの試みの後、私はいくつかの重要なUIコンポーネントをテストする方法を考え出しました。基本的には、酵素の検索を介してマテリアルUIコンポーネント内のネイティブhtml要素(入力、ボタンなど)を見つける必要があります。 @AndreasKöberle氏が以下のコメントで述べたように、「浅い」というのは、1レベルの深い検索だけを行うことに気付きました。 DOMツリーで深い検索を強制するには、酵素「マウント」を使用する必要があります。 http://airbnb.io/enzyme/docs/api/ReactWrapper/mount.html

ここに私の新しいテストコードがあります。

import React from 'react'; 
import { shallow, mount } from 'enzyme'; 
import getMuiTheme from 'material-ui/styles/getMuiTheme'; 
import { search } from '../sagas/search'; 
import TextField from 'material-ui/TextField'; 
import RaisedButton from 'material-ui/RaisedButton'; 
import Toggle from 'material-ui/Toggle'; 
import InputSearch from '../components/InputSearch/InputSearch'; 


const resetSearchMock = jest.fn(); 
const searchBooksMock = jest.fn(); 
const toggleResultsOpacityMock = jest.fn(); 
const muiTheme = getMuiTheme(); 
const props = { 
    keyword: '', 
    resetSearch: resetSearchMock, 
    searchBooks: searchBooksMock, 
    toggleResultsOpacity: toggleResultsOpacityMock, 
    firstSearch: true, 
}; 

const setup =() => { 
    const wrapper = mount(
    <InputSearch {...props} />, 
    { 
     context: {muiTheme}, 
     childContextTypes: {muiTheme: React.PropTypes.object} 
    } 
); 

    return { 
    props, 
    wrapper, 
    }; 
}; 

const { wrapper } = setup(); 
const textFieldMUI = wrapper.find(TextField); 
const toggleAuthor = wrapper.find(Toggle).find('input#author'); 
const toggleTitle = wrapper.find(Toggle).find('input#title'); 
const button = wrapper.find(RaisedButton).find('button'); 

describe ('Initial test, validate fields',() => { 
    test('TextField component should exists.',() => { 
    expect(textFieldMUI).toBeDefined(); 
    }); 

    test('Shows an error message when input search is empty and the search button is clicked.',() => { 
    const { props } = setup(); 
    props.keyword = ''; 

    const wrapper = mount(
     <InputSearch {...props} />, 
     { 
     context: {muiTheme}, 
     childContextTypes: {muiTheme: React.PropTypes.object} 
     } 
    ); 

    button.simulate('click'); 
    expect(textFieldMUI.props().errorText).toEqual('This field is required'); 
    }); 

    test('Shows an error message when both "author" and "title" toggles are off and the search button is clicked.',() => { 
    toggleTitle.simulate('click'); 
    button.simulate('click'); 
    expect(textFieldMUI.props().errorText).toEqual('Select at least one filter (Title or Author)'); 
    }); 

});