我只是用Jest / Enzyme学习单元测试 - 专门用于React / Redux。我正在尝试编写一个测试来从用户的角度进行检查(这是正确的方法吗?...)如果在点击某个链接后显示模态。接下来我想测试点击shade
包装器在modal
上关闭modal
。
模态(打开/关闭)由Redux控制。
基于Redux的当前状态 - 模态得到合适的风格:modal
或invisibleModal
。
我试图通过模拟Redux商店来做到这一点,但我觉得没有它应该完成 - 我想测试未连接的组件会更好,但如果我错了请纠正我。
到目前为止测试:
const mockFn = jest.fn();
describe('Contact components', ()=>{
it('<ContactModal /> renders correctly', ()=>{
shallow(<ContactModal />)
})
it('<ContactForm /> renders correctly', ()=>{
shallow(<ContactForm toggleContactModal={mockFn} />)
})
});
describe('In contact form link',()=>{
const link = shallow(<ContactForm toggleContactModal={mockFn}/>)
const modalWrapper = shallow(<ContactModal />);
it('toggleContactModal function is called upon clicking ContactForm',()=>{
expect(modalWrapper.find('#modal').hasClass('modal')).toBe(false);
link.simulate('click');
expect(mockFn.mock.calls.length).toBe(1);
})
})
模态组件:
export const ContactModal = props => {
return (
<>
<div
id='modal'
className={props.contactModal ? styles.modal : styles.invisibleModal}
>
hello from modal
</div>
<div
id='shade'
className={props.contactModal ? styles.shade : styles.invisibleShade}
onClick={props.toggleContactModal}
onKeyDown={props.toggleContactModal}
/>
</>
);
};
const mapStateToProps =state=> {
return {
contactModal: state.contactModal
}
}
const mapDispatchToProps = {
toggleContactModal
}
export default connect(mapStateToProps, mapDispatchToProps)(ContactModal);
减速器:
export const contactModal = (state=false, action) => {
switch (action.type){
case TOGGLE_CONTACT_MODAL:
return !state;
default:
return state
}
}
提前致谢。
来自Writing Tests Redux doc:
...有时您只想测试组件的渲染,而不需要Redux存储。
为了能够在不必处理装饰器的情况下测试App组件本身,我们建议您也导出未修饰的组件
所以,是的,导出未连接的组件并直接测试它是一种推荐的方法。
对于您的组件,您只需要根据contactModal
prop以及click和keydown处理程序测试UI更改。
这是一个稍微简化的工作示例,可帮助您入门:
import * as React from 'react';
import { shallow } from 'enzyme';
const ContactModal = props => {
return (
<>
<div
id='modal'
className={props.contactModal ? 'modal': 'invisibleModal'}
>
hello from modal
</div>
<div
id='shade'
className={props.contactModal ? 'shade' : 'invisibleShade'}
onClick={props.toggleContactModal}
onKeyDown={props.toggleContactModal}
/>
</>
);
};
describe('ContactModal', () => {
it('should render as expected when contactModal is true', () => {
const wrapper = shallow(<ContactModal contactModal={true} />);
expect(wrapper.find('#modal').prop('className')).toBe('modal'); // Success!
expect(wrapper.find('#shade').prop('className')).toBe('shade'); // Success!
});
it('should render as expected when contactModal is false', () => {
const wrapper = shallow(<ContactModal contactModal={false} />);
expect(wrapper.find('#modal').prop('className')).toBe('invisibleModal'); // Success!
expect(wrapper.find('#shade').prop('className')).toBe('invisibleShade'); // Success!
});
it('should call props.toggleContactModal on click', () => {
const spy = jest.fn();
const wrapper = shallow(<ContactModal contactModal={true} toggleContactModal={spy} />);
wrapper.find('#shade').prop('onClick')();
expect(spy).toHaveBeenCalled(); // Success!
});
it('should call props.toggleContactModal on keydown', () => {
const spy = jest.fn();
const wrapper = shallow(<ContactModal contactModal={true} toggleContactModal={spy} />);
wrapper.find('#shade').prop('onKeyDown')();
expect(spy).toHaveBeenCalled(); // Success!
});
});