如何使用React Jest测试TextField Material-UI元素?

时间:2017-04-09 18:45:22

标签: reactjs material-ui jestjs enzyme

我使用React和Material-UI构建了一个组件。我使用的是React和Redux。

我的 index.jsx 如下所示:

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如下所示:

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 Enzyme和Jest来构建单元测试。 我对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的价值吗?

4 个答案:

答案 0 :(得分:1)

shallow仅渲染一个级别,因此在您的情况下,只会呈现MuiThemeProviderInputSearch。您可以使用Jest快照功能查看wrapper内呈现的内容。您可以使用dive强制Enzyme渲染组件的内容:

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

或者你不要用MuiThemeProvider包裹组件并直接渲染InputSearch。您只需要添加样式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,
  };
};

答案 1 :(得分:1)

如果有人有更好的解决方案,请回答我的问题。经过一些尝试,我想出了如何测试一些材料UI组件。基本上,我们需要通过酶find找到材料UI组件内的原生html元素(输入,按钮等)。我也意识到“浅薄”,只进行了一次深度搜索,正如@AndreasKöberle在下面的评论中所说。为了强制在DOM树中进行深度搜索,我们需要使用酶“mount”。 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)');
  });

});

答案 2 :(得分:0)

我用mocha,酶和柴一直在写测试几天。测试update="search:dlgViewStfPackId"带来的问题是内部反应组件,因此在测试常规material-ui元素时无法对其进行测试。

您可以通过打印整个组件来找出属性的变化,例如

html

这将为您打印整个元素,您可以注意到TestField有console.log(wrapper.find('TextField').debug()); 道具,这是您要检查的内容,因为value决定了{{1}中的值}}

所以代码将是这样的:

prop

这就是我测试TextField组件的方式。

希望你觉得它有用。

答案 3 :(得分:0)

const event = { 'target': { 'value': 'No' } };
wrapper.find('#selectBox').prop('onChange').call(null, event);