如何使用React和testing-library测试交互后元素的焦点状态
如何用React Testing Library测试元素焦点状态
完全可行,React Testing Library结合Jest可以轻松验证元素的焦点变化,以下是具体实现方法:
核心思路
- 定位目标元素:使用RTL的查询方法(如
screen.getByRole()、screen.getByTestId())获取需要验证焦点的元素。 - 触发交互操作:通过
fireEvent或userEvent(推荐后者,更贴近真实用户行为)触发会改变焦点的交互(比如点击按钮、触发键盘事件)。 - 验证焦点状态:通过
document.activeElement判断当前焦点元素,或直接使用Jest的toHaveFocus()匹配器验证目标元素是否获焦。
示例代码
组件示例
import { useState } from 'react'; function FocusDemo() { const [inputRef, setInputRef] = useState(null); const handleFocusInput = () => { inputRef?.focus(); }; return ( <div> <button onClick={handleFocusInput}>聚焦输入框</button> <input ref={setInputRef} aria-label="测试输入框" /> </div> ); } export default FocusDemo;
测试用例(使用fireEvent)
import { render, screen, fireEvent } from '@testing-library/react'; import FocusDemo from './FocusDemo'; test('点击按钮后输入框获得焦点', () => { render(<FocusDemo />); const triggerBtn = screen.getByRole('button', { name: /聚焦输入框/i }); const testInput = screen.getByRole('textbox', { name: /测试输入框/i }); // 初始状态输入框无焦点 expect(document.activeElement).not.toBe(testInput); // 触发点击事件 fireEvent.click(triggerBtn); // 验证输入框已获焦 expect(document.activeElement).toBe(testInput); // 或使用toHaveFocus匹配器(需确保测试环境支持) expect(testInput).toHaveFocus(); });
测试用例(推荐使用userEvent)
userEvent模拟真实用户的交互流程,比fireEvent更符合实际场景:
import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import FocusDemo from './FocusDemo'; test('点击按钮后输入框获得焦点', async () => { const user = userEvent.setup(); render(<FocusDemo />); const triggerBtn = screen.getByRole('button', { name: /聚焦输入框/i }); const testInput = screen.getByRole('textbox', { name: /测试输入框/i }); await user.click(triggerBtn); expect(testInput).toHaveFocus(); });
注意事项
- 确保目标元素是可聚焦元素:比如
<input>、<button>,或设置了tabindex的元素,否则无法获得焦点。 - 如果使用React ref控制焦点,需确保ref正确绑定到目标元素上。
内容的提问来源于stack exchange,提问作者Andy Stannard
相关产品推荐
相关产品推荐

