如何使用 React Jest 测试 TextField Material-UI 元素?
How to test a TextField Material-UI element with React Jest?
我用 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
任何人都可以帮助我找到正确的方法来检查 Material UI TextField
的值吗?
Enzyme shallow
仅呈现一层深度,因此在您的情况下仅呈现 MuiThemeProvider
和 InputSearch
。您可以使用 Jest 快照功能查看 wrapper
中渲染的内容。您可以使用 dive
强制 Enzyme 呈现组件的内容:
expect(wrapper.('InputSearch').dive().find(TextField).getValue()).toEqual('');
或者您不使用 MuiThemeProvider
包装组件并直接渲染 InputSearch
。您只需要添加 styles 道具。现在 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,
};
};
如果有人有更好的解决方案,请回答我的问题。经过一些尝试,我想出了如何测试一些 material UI 组件。基本上,我们需要通过酶查找在 material UI 组件内找到原生 html 元素(输入、按钮等)。我还意识到 "shallow",只能进行一级深度搜索,正如@Andreas Kö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)');
});
});
几天来我一直在使用 mocha、enzyme 和 chai 编写测试。测试 material-ui
带来的问题是这些反过来是反应组件,因此无法像测试常规 html
元素那样测试它们。
您可以通过打印整个组件来找出 属性 发生的变化,例如
console.log(wrapper.find('TextField').debug());
这将为您打印整个元素,您会注意到 TestField 有 value
属性,这是您应该检查的内容,因为这个 prop
决定了 TextField
因此代码将如下所示:
describe('Initial test', () => {
test('Shows error message when input search is empty.', () => {
const { wrapper, props } = setup();
expect(wrapper.find(TextField).props().value).to.equal('');
});
}
这就是我测试 TextField 组件的方式。
希望对您有所帮助。
const event = { 'target': { 'value': 'No' } };
wrapper.find('#selectBox').prop('onChange').call(null, event);
我用 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
任何人都可以帮助我找到正确的方法来检查 Material UI TextField
的值吗?
Enzyme shallow
仅呈现一层深度,因此在您的情况下仅呈现 MuiThemeProvider
和 InputSearch
。您可以使用 Jest 快照功能查看 wrapper
中渲染的内容。您可以使用 dive
强制 Enzyme 呈现组件的内容:
expect(wrapper.('InputSearch').dive().find(TextField).getValue()).toEqual('');
或者您不使用 MuiThemeProvider
包装组件并直接渲染 InputSearch
。您只需要添加 styles 道具。现在 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,
};
};
如果有人有更好的解决方案,请回答我的问题。经过一些尝试,我想出了如何测试一些 material UI 组件。基本上,我们需要通过酶查找在 material UI 组件内找到原生 html 元素(输入、按钮等)。我还意识到 "shallow",只能进行一级深度搜索,正如@Andreas Kö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)');
});
});
几天来我一直在使用 mocha、enzyme 和 chai 编写测试。测试 material-ui
带来的问题是这些反过来是反应组件,因此无法像测试常规 html
元素那样测试它们。
您可以通过打印整个组件来找出 属性 发生的变化,例如
console.log(wrapper.find('TextField').debug());
这将为您打印整个元素,您会注意到 TestField 有 value
属性,这是您应该检查的内容,因为这个 prop
决定了 TextField
因此代码将如下所示:
describe('Initial test', () => {
test('Shows error message when input search is empty.', () => {
const { wrapper, props } = setup();
expect(wrapper.find(TextField).props().value).to.equal('');
});
}
这就是我测试 TextField 组件的方式。
希望对您有所帮助。
const event = { 'target': { 'value': 'No' } };
wrapper.find('#selectBox').prop('onChange').call(null, event);