使用Jest测试dnd-kit/sortable组件:排序功能测试失败
使用dnd-kit的拖拽排序组件测试问题
我正在为基于dnd-kit的拖拽排序组件编写测试用例,目前能成功触发dragStart和dragEnd行为,但尝试重新排序列表时,列表始终保持原有顺序。
触发拖拽行为的代码(需添加MouseSensor才能正常运行)
// mouse over dragged element and mousedown act(() => { fireMouseEvent("mousemove", elemDrag, center1X, center1Y); sleep(1); fireMouseEvent("mouseenter", elemDrag, center1X, center1Y); sleep(1); fireMouseEvent("mouseover", elemDrag, center1X, center1Y); sleep(1); fireMouseEvent("mousedown", elemDrag, center1X, center1Y); sleep(1); }); // start dragging process over to drop target act(() => { const dragStarted = fireMouseEvent( "dragstart", elemDrag, center1X, center1Y ); if (!dragStarted) { return; } }); act(() => { fireMouseEvent("drag", elemDrag, center1X, center1Y); sleep(1); fireMouseEvent("mousemove", elemDrag, center1X, center1Y); sleep(1); fireMouseEvent("drag", elemDrag, center2X, center2Y); sleep(1); fireMouseEvent("mousemove", elemDrop, center2X, center2Y); // trigger dragging process on top of drop target fireMouseEvent("mouseenter", elemDrop, center2X, center2Y); sleep(1); fireMouseEvent("dragenter", elemDrop, center2X, center2Y); sleep(1); fireMouseEvent("mouseover", elemDrop, center2X, center2Y); sleep(1); fireMouseEvent("dragover", elemDrop, center2X, center2Y); sleep(1); // release dragged element on top of drop target fireMouseEvent("drop", elemDrop, center2X, center2Y); sleep(1); fireMouseEvent("dragend", elemDrag, center2X, center2Y); sleep(1); // fireMouseEvent("mouseup", elemDrag, center2X, center2Y); // sleep(1); });
异常现象
注释掉最后一行的mouseup事件时,dnd-kit的辅助功能提示显示:Draggable item item-0 was moved over droppable area item-1.,且用jest-preview能预览到重新排序后的列表。但取消注释该行后,辅助功能提示变为:Draggable item item-0 was dropped over droppable area item-0,列表也不会排序。
获取元素及模拟矩形区域的代码
const draggables = container.querySelectorAll( '[aria-roledescription="sortable"]' ); Object.setPrototypeOf(window, Window.prototype); draggables.forEach((draggable, index) => { mockGetBoundingClientRect(draggable, index); }); const elemDrag = draggables[0]; const elemDrop = draggables[1]; let pos = elemDrag.getBoundingClientRect(); const center1X = Math.floor((pos.left + pos.right) / 2); const center1Y = Math.floor((pos.top + pos.bottom) / 2); pos = elemDrop.getBoundingClientRect(); const center2X = Math.floor((pos.left + pos.right) / 2); const center2Y = Math.floor((pos.top + pos.bottom) / 2) + 50;
jest.spyOn(element, "getBoundingClientRect").mockImplementation(() => ({ bottom: 88 + index * (177 - 88), height: 48, left: 68, right: 282.078125, top: 40 + index * 89, width: 214.078125, x: 68, y: 40 + index * 89, }));
可能的解决方向
- 调整
mouseup的触发目标:当前mouseup绑定在原拖拽元素elemDrag上,但拖拽过程中元素的逻辑落点应该是目标区域,试试把mouseup的触发目标改成elemDrop。 - 修正事件执行顺序:dnd-kit的MouseSensor依赖严格的事件序列,正确顺序应为
mousedown→ 拖拽移动 →dragover目标 →drop→mouseup→dragend,你当前的dragend在mouseup之前,可能打乱了内部状态,调换两者顺序试试。 - 检查坐标模拟:给
center2Y额外加50可能导致拖拽元素未完全落在目标区域的有效范围内,尝试直接使用目标元素的中心坐标(去掉+50),或调整偏移值确保覆盖有效交互区域。 - 简化事件序列:dnd-kit的MouseSensor核心依赖原生鼠标事件序列(
mousedown/mousemove/mouseup),你添加的HTML原生拖拽事件(dragstart/drag/dragenter等)可能干扰自定义传感器逻辑,尝试移除这些多余事件,只保留鼠标事件序列。
内容的提问来源于stack exchange,提问作者pegasystem
相关产品推荐
相关产品推荐

