我有一个Redux连接的导航栏组件,该组件呈现两个子组件。其中一个是美化按钮(不是redux),另一个是redux连接的搜索栏。
在测试中,我希望能够呈现该按钮并确认单击该按钮时发生正确的行为。但是,如果我使用shallow()
,则它仅为按钮呈现一个占位符,并且按钮本身不可被找到和单击。如果我使用mount(),则测试失败,因为我的单元测试使用导航栏的非redux导出,然后尝试呈现子搜索栏组件(已连接redux),并且没有要存储的存储。传下来。
使用非redux导出可以很好地测试浅层渲染,但是如何才能通过单击按钮来测试我的导航栏组件-该按钮只能通过mount()
调用来完全渲染?
我遇到的问题是在下面的测试中,如果我使用shallow(),则它无法找到模拟点击的按钮,因为它仅呈现为占位符。如果我使用mount(),它将无法呈现<Searchbar />
组件,因为这是一个Redux连接的组件,并且我的测试是在没有连接存储的情况下手动传递道具。
如果商店不存在,是否可以配置我的导航栏组件以将道具传递到搜索栏?还是仅有条件地深度渲染某些组件?我只想呈现PanelTileButton,而不是SearchBar
我的导航栏组件
interface IControlBarProps {
includeValidated: boolean,
includeValidatedChanged: (includeValidated:boolean) => void,
}
export class ControlBar extends React.Component<IControlBarProps, {}> {
constructor(props: any) {
super(props);
}
public render() {
return <div className="Control-bar">
<div className="Control-left" >
<SearchBar />
</div>
<div className="Control-center" />
<div className="Control-right">
{this.getDashboardButton("IV", "Include Validated", this.props.includeValidated, () => this.props.includeValidatedChanged(!this.props.includeValidated))}
</div>
</div>
}
private getDashboardButton(key: string, title: string, newValue: boolean, action: (value:boolean) => void)
{
return <div className="Control-Bar-Right" key={key}>
<PanelTileButton text={title} iswide={false} highlighted={newValue}
// tslint:disable
onClick={() => action(newValue)} />
</div>
}
}
function mapStateToProps(state: IStoreState) {
return {
includeValidated: state.trade.includeValidated
};
}
const mapDispatchToProps = (dispatch: Dispatch) => {
return {
includeValidatedChanged: (includeValidated:boolean) => {
dispatch(getIncludeValidatedChangedAction(includeValidated))
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ControlBar);
我的测试
it('should handle clicking include validated button', () => {
const mockCallback = jest.fn();
const wrapper = mount(<ControlBar includeValidated={false} includeValidatedChanged={mockCallback} />);
expect(wrapper.find('div.Control-bar').exists()).toEqual(true);
expect(wrapper.find({highlighted: false}).exists()).toEqual(true);
const pb = wrapper.find("PanelTileButton").first();
pb.find('button').simulate('click', {preventDefault() {} });
expect(mockCallback.mock.calls.length).toBe(1);
})
答案 0 :(得分:0)
对于其他研究如何执行此操作的人,我最终通过将安装的组件包装在<Provider>
标签中并使用redux-mock-store将模拟存储向下传递给子组件来解决了该问题,至少让他们渲染。
import configureMockStore from 'redux-mock-store'
it('should handle clicking include validated button', () => {
const mockCallback = jest.fn();
const mockStore = configureMockStore([])(getTestStore());
const wrapper = mount(<Provider store={mockStore}><ControlBar includeValidated={false} includeValidatedChanged={mockCallback} /></Provider>);
expect(wrapper.find('div.Control-bar').exists()).toEqual(true);
expect(wrapper.find({highlighted: false}).exists()).toEqual(true);
const pb = wrapper.find("PanelTileButton").first();
pb.find('button').simulate('click', {preventDefault() {} });
expect(mockCallback.mock.calls.length).toBe(1);
})
答案 1 :(得分:0)
您还可以mock components,这样就可以避免在喜欢使用shallow
的时候一直都在模拟redux存储。
在与SearchBar.tsx
相同的文件夹中,创建一个名为__mocks__
的子文件夹,并在其中放置一个具有相同名称SearchBar.tsx
(按照惯例)的文件,该文件将返回最少的html < / p>
import * as React from 'react';
export default function SearchBar() {
return <div>SearchBar</div>
}
然后在您的测试文件中
jest.mock('../SearchBar') // this detects the corresponding mock automatically
import { ControlBar } from '../ControlBar';
import { shallow } from 'enzyme';
...
it('should handle clicking include validated button', () => {
const mockCallback = jest.fn();
const wrapper = shallow(<ControlBar includeValidated={false} includeValidatedChanged={mockCallback} />);
...
})
...