使用Jest和Enzyme测试Material UI DatePicker时模拟change事件无效如何解决
问题根因
从你打印的input属性日志可以看到readOnly={true},这是MUI DatePicker的默认行为:输入框默认设为只读,直接触发change事件会被内部拦截,无法修改值。同时Enzyme的simulate方法对多层封装的组件事件触发支持度有限,也可能导致事件不生效。
解决方案
方案1:模拟用户手动输入场景
- 先修改
DatePickerFilter.tsx中renderInput的配置,关闭输入框只读状态:
renderInput={(params) => <TextField {...params} inputProps={{ readOnly: false }} />}
- 修改测试代码,直接操作DOM节点赋值后再触发对应事件:
import { StyledDatePicker } from '../../common/DatePickerFilter'; describe('MyBookings > DatePickerFilter', () => { it('should not change date if its before today', () => { const wrapper = mount( <Render> <DatePickerFilter /> </Render> ); const inputDom = wrapper.find('input').getDOMNode() as HTMLInputElement; inputDom.value = '11/10/2021'; wrapper.find('input').simulate('change'); // MUI DatePicker默认会在blur事件时同步值到组件状态 wrapper.find('input').simulate('blur'); wrapper.update(); console.log(wrapper.find('input').debug()) wrapper.unmount(); }); });
方案2:直接调用组件API(更适合逻辑校验场景)
如果不需要模拟真实输入流程,只是要校验日期变更后的业务逻辑,可以直接调用DatePicker暴露的onChange方法,跳过输入层的封装处理:
import { StyledDatePicker } from '../../common/DatePickerFilter'; describe('MyBookings > DatePickerFilter', () => { it('should not change date if its before today', () => { const wrapper = mount( <Render> <DatePickerFilter /> </Render> ); // 直接调用DatePicker的onChange方法传入新日期 wrapper.find(StyledDatePicker).prop('onChange')(new Date('2021-11-10')); wrapper.update(); // 可以直接加断言校验值是否符合预期 expect(wrapper.find('input').prop('value')).toBe('11/10/2021'); wrapper.unmount(); }); });
补充说明
如果你需要实现「早于今天的日期不允许修改」的逻辑,需要在DatePicker组件上添加minDate={new Date()}属性,目前你的组件未加该限制,即使输入早于今天的日期也会正常更新。
内容的提问来源于stack exchange,提问作者Shary
相关产品推荐
相关产品推荐

