React Testing Library无法修改Material UI DatePicker输入值问题求解
问题根因
这个报错有两个核心原因:
- Material UI v4的
DatePicker默认会给输入框添加readonly属性,浏览器会默认阻止只读输入框的change事件触发,所以直接调用fireEvent.change不会生效 - 你当前测试里的
DatePicker是受控组件写法,但value绑定了实时生成的new Date(),且onChange回调没有做状态更新逻辑,就算输入框事件能触发,组件值也不会同步更新
解决方法
方案1:模拟真实用户交互(推荐,更符合测试库的用户导向原则)
直接模拟用户正常选择日期的完整流程,不需要修改组件属性,和实际使用场景完全一致:
import React, { useState } from "react"; import { render, screen, fireEvent } from "@testing-library/react"; import MomentUtils from "@date-io/moment"; import { DatePicker, MuiPickersUtilsProvider } from "@material-ui/pickers"; describe("DatePicker", () => { test("Change datepicker value", async () => { // 封装带受控状态的测试组件 const TestDatePicker = () => { const [date, setDate] = useState(new Date()); return ( <MuiPickersUtilsProvider utils={MomentUtils}> <DatePicker label="Start Date" id="startDate" onChange={(newDate) => setDate(newDate)} value={date} format={"yyyy/MM/DD"} /> </MuiPickersUtilsProvider> ) } render(<TestDatePicker />); const startDateInput = await screen.findByLabelText("Start Date"); // 点击输入框调出日历面板 fireEvent.click(startDateInput); // 找到对应日期元素点击,这里的aria-label格式和你用的日期工具库、语言配置有关,按需调整 const targetDate = await screen.findByRole('gridcell', { name: /jan 1, 2021/i }); fireEvent.click(targetDate); // 断言值正确 expect(startDateInput).toHaveValue("2021/01/01"); }); });
方案2:直接修改输入框值(适合快速测试输入场景)
如果不需要模拟面板选择,只想直接修改输入框的值,可以先移除输入框的readonly属性,再触发change事件:
import React, { useState } from "react"; import { render, screen, fireEvent } from "@testing-library/react"; import MomentUtils from "@date-io/moment"; import { DatePicker, MuiPickersUtilsProvider } from "@material-ui/pickers"; describe("DatePicker", () => { test("Change datepicker value", async () => { const TestDatePicker = () => { const [date, setDate] = useState(new Date()); return ( <MuiPickersUtilsProvider utils={MomentUtils}> <DatePicker label="Start Date" id="startDate" onChange={(newDate) => setDate(newDate)} value={date} format={"yyyy/MM/DD"} /> </MuiPickersUtilsProvider> ) } render(<TestDatePicker />); const startDateInput = (await screen.findByLabelText("Start Date")) as HTMLInputElement; // 先移除只读属性 startDateInput.removeAttribute('readonly'); // 再触发change事件 fireEvent.change(startDateInput, { target: { value: "2021/01/01" } }); // 触发blur事件让DatePicker完成值校验和同步 fireEvent.blur(startDateInput); // 断言值正确 expect(startDateInput.value).toBe("2021/01/01"); }); });
内容的提问来源于stack exchange,提问作者jimmybutton
相关产品推荐
相关产品推荐

