Cypress无法拖拽Angular自定义cdkDragHandle组件的问题求解
问题原因解析
- 第一种方案报错是因为Cypress默认触发事件前会校验目标元素是否未被遮挡,拖拽过程中列表元素重排,原拖拽把手被其他列表项遮挡,触发了Cypress的交互校验拦截。
- 第二种方案无效果是因为派发的MouseEvent未开启冒泡,也没有指定鼠标左键参数,Angular CDK的拖拽事件监听需要事件冒泡到上层
cdkDrag节点,且默认仅响应左键触发的拖拽操作。
可用解决方案
方案1:修改原生Cypress trigger调用
给所有trigger操作添加{ force: true }跳过元素遮挡校验,同时指定鼠标左键参数即可正常触发:
describe("Drag and drop", () => { beforeEach(() => cy.visit("/")); it("should drag the first item to target position", () => { cy.get("[data-cy=custom-drag-handle-0]") .trigger("mousedown", { which: 1, force: true }) .trigger("mousemove", { x: 10, y: 10, force: true }) // y轴偏移量根据你的列表项实际高度调整即可 .trigger("mousemove", { x: 10, y: 230, force: true }) .trigger("mouseup", { force: true }); // 补充断言验证拖拽结果符合预期 cy.get(".example-box").eq(3).should("contain", "原第一个列表项的文本"); }); });
方案2:修正手动派发事件的参数
补全MouseEvent的冒泡、鼠标按键配置,同时先小范围移动触发CDK的拖拽启动逻辑:
describe("Drag and drop", () => { beforeEach(() => cy.visit("/")); it("should drag the first item to target position", () => { cy.get("[data-cy=custom-drag-handle-0]").then($handle => { const dragHandle = $handle[0]; const basePos = dragHandle.getBoundingClientRect(); const eventBaseOpts = { bubbles: true, cancelable: true, view: window, button: 0, clientX: basePos.x + 10, clientY: basePos.y + 10 }; // 触发鼠标按下 dragHandle.dispatchEvent(new MouseEvent("mousedown", {...eventBaseOpts})); // 小范围移动触发CDK拖拽启动 dragHandle.dispatchEvent(new MouseEvent("mousemove", { ...eventBaseOpts, clientY: eventBaseOpts.clientY + 15 })); // 拖动到目标位置 dragHandle.dispatchEvent(new MouseEvent("mousemove", { ...eventBaseOpts, clientY: eventBaseOpts.clientY + 230 })); // 释放鼠标完成拖拽 dragHandle.dispatchEvent(new MouseEvent("mouseup", {...eventBaseOpts})); }); }); });
如果需要更简洁的调用方式,可以使用社区维护的Cypress拖拽适配插件,支持直接指定自定义拖拽把手,无需手动处理事件参数。
内容的提问来源于stack exchange,提问作者Runtime Terror
相关产品推荐
相关产品推荐

