嵌套组件的Redux /酶测试

时间:2018-12-28 15:40:38

标签: reactjs typescript jestjs enzyme

我有一个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);  
  })

2 个答案:

答案 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} />);

    ...
 })
...