如何在Jest/RTL中测试mouseOut/取消悬浮事件?
解决Jest/RTL测试mouseOut时
currentDocument.elementFromPoint is not a function错误 先修正测试中的基础错误
你的组件里img标签的data-testid是info-icon,但测试代码中用的是screen.getByTestId('tooltip-icon'),这会导致找不到目标元素,事件无法正确触发,先把这个匹配错误修正。
针对elementFromPoint错误的解决方案
这个错误是因为Tooltip组件内部处理mouseOut事件时调用了elementFromPoint方法,但Jest的jsdom环境并未实现该API,以下是三种可行解决办法:
1. 模拟document.elementFromPoint方法
在测试文件顶部或Jest全局setup文件中添加模拟逻辑,让组件认为鼠标已完全离开元素:
beforeAll(() => { // 模拟elementFromPoint,返回null表示鼠标不在任何元素范围内 document.elementFromPoint = jest.fn(() => null); });
2. 使用@testing-library/user-event替代fireEvent
userEvent提供更贴近真实用户的交互API,能避免原生事件模拟的兼容性问题:
首先安装依赖:
npm install --save-dev @testing-library/user-event
然后修改测试代码:
import userEvent from '@testing-library/user-event'; it('Should test tooltip', async () => { const user = userEvent.setup(); render(<Tooltip />); // 触发悬浮 await user.hover(screen.getByTestId('info-icon')); // 自动等待元素出现并断言 expect(await screen.findByText("'Information'")).toBeInTheDocument(); // 取消悬浮 await user.unhover(screen.getByTestId('info-icon')); // 用queryByText判断元素不存在(找不到不会抛出错误) expect(screen.queryByText("'Information'")).not.toBeInTheDocument(); });
3. 改用mouseLeave事件替代mouseOut
mouseLeave不会冒泡,可绕过组件中基于elementFromPoint的子元素判断逻辑:
it('Should test tooltip', async () => { render(<Tooltip />); const icon = screen.getByTestId('info-icon'); fireEvent.mouseOver(icon); await waitFor(() => screen.getByTestId('tooltip-info')); expect(screen.getByText("'Information'")).toBeInTheDocument(); // 改用mouseLeave事件触发离开逻辑 fireEvent.mouseLeave(icon); await waitForElementToBeRemoved(() => screen.getByTestId('tooltip-info')); // 用queryByText断言元素不存在 expect(screen.queryByText("'Information'")).not.toBeInTheDocument(); });
内容的提问来源于stack exchange,提问作者Sole
相关产品推荐
相关产品推荐

