使用react-testing-library测试@dnd-kit拖拽功能时基础事件未触发
解决@dnd-kit拖拽测试中核心事件不触发的问题
针对@dnd-kit拖拽测试时onDragStart/onDragMove/onDragOver/onDragEnd等核心事件不触发的问题,以下是几个可行的解决方案:
1. 使用@testing-library/user-event替代fireEvent
fireEvent是低级事件触发工具,无法模拟真实用户拖拽时的完整事件序列和交互逻辑。user-event更贴近真实用户行为,能正确触发@dnd-kit依赖的pointer事件链。
示例代码:
import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; test('验证元素拖拽功能', async () => { const user = userEvent.setup(); const dragSource = screen.getByTestId('draggable-item-1'); const dropTarget = screen.getByTestId('draggable-item-3'); // 模拟完整拖拽流程:按住 → 拖动到目标 → 松开 await user.pointer({ target: dragSource, keys: '[MouseLeft]', // 按住鼠标左键 moveTo: dropTarget, }); // 这里添加业务断言,比如验证元素顺序是否变化 expect(screen.getAllByTestId(/draggable-item-/)).toHaveLength(3); // ...其他自定义断言 });
如果需要更细粒度的控制,可以拆分步骤:
await user.pointerDown(dragSource); await user.pointerMove(dropTarget, { clientX: 200, clientY: 200 }); // 指定拖动坐标 await user.pointerUp();
2. 确保测试环境支持Pointer Events
@dnd-kit基于Pointer Events实现拖拽,部分测试环境(如jsdom)默认未完全启用该特性,需要手动配置。
Jest配置示例(jest.config.js):
module.exports = { testEnvironmentOptions: { jsdom: { features: { PointerEvent: true, }, }, }, };
3. 给fireEvent补充必要的事件参数
如果坚持使用fireEvent,需要为拖拽事件传递dataTransfer对象(@dnd-kit内部依赖该对象处理拖拽状态),且要保证事件顺序和参数正确。
修正后的fireEvent示例:
import { fireEvent } from '@testing-library/react'; // 初始化mock的dataTransfer const mockDataTransfer = { setData: jest.fn(), getData: jest.fn(), dropEffect: 'move', effectAllowed: 'move', }; const firstItem = screen.getByTestId('drag-item-0'); const lastItem = screen.getByTestId('drag-item-2'); // 按顺序触发事件,每个事件都传递dataTransfer fireEvent.dragStart(firstItem, { dataTransfer: mockDataTransfer }); fireEvent.dragEnter(lastItem, { dataTransfer: mockDataTransfer }); fireEvent.dragOver(lastItem, { dataTransfer: mockDataTransfer }); fireEvent.drop(lastItem, { dataTransfer: mockDataTransfer }); fireEvent.dragEnd(firstItem, { dataTransfer: mockDataTransfer });
4. 检查组件的拖拽触发条件
- 确认
Draggable组件已正确设置id属性,且未被设置disabled状态; - 部分场景下,拖拽元素需要先获得焦点,可在测试前添加
await user.click(dragSource)确保元素处于可交互状态。
内容的提问来源于stack exchange,提问作者ThiwankaB
相关产品推荐
相关产品推荐

