You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React测试中无法修改<input type="date">值的问题求助

日期输入框测试无法修改值的问题解决

我尝试了多种方法与日期输入框交互,但均未成功。有时默认日期保持不变,有时会变成空字符串,始终无法将值修改为新日期。

尝试过的方法

  • 使用fireEvent.change:
const startDate = screen.getByLabelText('from');
act(() => {
  fireEvent.change(startDate, {target: {value: '2019-10-08'}});
});

操作后值变为空字符串。

  • 使用userEvent.type(v13.5.2):
act(() => {
  userEvent.type(startDate, '08102019');  // 以及带横杠、斜杠或年份在前的所有变体
});

此操作对值无影响。

  • 使用最新版userEvent(v14+):
const user = userEvent.setup();
await act(async () => {
  await user.type(startDate, '08102019');
});

操作仍无效果。

  • 其他尝试:fireEvent点击、userEvent点击、userEvent.keyboard等组合,均无效。

复现代码

DateComp.test.tsx

import { render, screen, fireEvent } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import DateComp from './DateComp';
import '@testing-library/jest-dom';

test('changing date value works', async () => {
  render(<DateInput onChange={()=>{return;}} className="" />);

  const startDate = screen.getByLabelText('from');
  const endDate = screen.getByLabelText('to');
  act(() => {
    fireEvent.change(startDate, {target: {value: '2019-10-08'}});
  });
  act(() => {
    fireEvent.change(endDate, {target: {value: '2020-10-08'}});
  });
  expect(startDate.getAttribute('value')).toEqual('2019-10-08');
  expect(endDate.getAttribute('value')).toEqual('2020-10-08');
});

DateComp.tsx

import { useState, useEffect } from 'react';

interface IProps {
  onChange: CallableFunction,
  className: string,
}

const DateComp = ({ onChange, className }: IProps): JSX.Element => {
  // Default dates
  const dateFrom = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().substring(0, 10);  // 7 days ago
  const dateTo = new Date().toISOString().substring(0, 10);  // today

  const [selectedFrom, setSelectedFrom] = useState(dateFrom);
  const [selectedTo, setSelectedTo] = useState(dateTo);

  const handleFrom = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSelectedFrom(e.target.value);
  };
  const handleTo = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSelectedTo(e.target.value);
  };

  return (
    <div className={className}>
      <label htmlFor='date_inputs'>Period</label>
      <div id='date_inputs' className='date-inputs'>
        <label htmlFor='date_from' className='screen-reader-only'>from</label>
        <input id='date_from' type='date' defaultValue={dateFrom} onChange={handleFrom} />
        <label htmlFor='date_to'>to</label>
        <input id='date_to' type='date' defaultValue={dateTo} onChange={handleTo} />
      </div>
    </div>
  );
};

export default DateComp;

package.json

{
  ...,
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "typescript": "^4.9.5",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "./node_modules/.bin/react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  ...,
  "devDependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^14.4.3",
    "@types/jest": "^27.5.2",
    "@types/node": "^16.18.24",
    "@types/react": "^18.2.0",
    "@types/react-dom": "^18.2.0",
    "msw": "^1.2.3",
    "react-scripts": "5.0.1"
  },
  "jest": {
    "transformIgnorePatterns": [
      "node_modules/(?!@ngrx|(?!deck.gl)|ng-dynamic)"
    ]
  }
}

问题原因及解决办法

1. 输入框未绑定状态值

你的input标签使用了defaultValue,但未将value属性绑定到selectedFrom/selectedTo状态,导致状态更新后输入框显示值不同步。修改DateComp.tsx中的输入框:

<input id='date_from' type='date' value={selectedFrom} onChange={handleFrom} />
<input id='date_to' type='date' value={selectedTo} onChange={handleTo} />

去掉defaultValue,改用value绑定状态,确保输入框与状态同步。

2. 测试组件名称错误

测试代码中渲染的<DateInput />是错误的,实际组件是DateComp,修正为:

render(<DateComp onChange={()=>{}} className="" />);

3. 测试断言方式错误

对于受控组件,应通过screen.getByDisplayValue断言,而非getAttribute('value')。修改测试断言:

expect(screen.getByDisplayValue('2019-10-08')).toBeInTheDocument();
expect(screen.getByDisplayValue('2020-10-08')).toBeInTheDocument();

4. React 18+测试代码优化

React 18中render和fireEvent已自动包裹在act中,无需手动调用,简化后的测试代码:

test('changing date value works', async () => {
  render(<DateComp onChange={()=>{}} className="" />);

  const startDate = screen.getByLabelText('from');
  const endDate = screen.getByLabelText('to');
  
  fireEvent.change(startDate, {target: {value: '2019-10-08'}});
  fireEvent.change(endDate, {target: {value: '2020-10-08'}});
  
  expect(screen.getByDisplayValue('2019-10-08')).toBeInTheDocument();
  expect(screen.getByDisplayValue('2020-10-08')).toBeInTheDocument();
});

5. userEvent正确使用方式

使用userEvent时需传入ISO格式日期字符串,先清空输入框再输入:

test('changing date value with userEvent', async () => {
  const user = userEvent.setup();
  render(<DateComp onChange={()=>{}} className="" />);

  const startDate = screen.getByLabelText('from');
  await user.clear(startDate);
  await user.type(startDate, '2019-10-08');
  
  expect(screen.getByDisplayValue('2019-10-08')).toBeInTheDocument();
});

内容的提问来源于stack exchange,提问作者Matthias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 09:16:00