如何使用Cypress测试Cytoscape.js 2.7.10的节点/边拖拽功能?
如何用Cypress测试Cytoscape.js的节点与边拖拽操作
我太懂这种踩坑的感觉了——Cytoscape.js的拖拽逻辑是基于自定义鼠标事件实现的,根本不是原生HTML5的拖拽API,所以Cypress官方教程里那套方法自然就不管用了。下面给你一套亲测有效的方案,专门适配2.7.10版本的Cytoscape。
一、测试节点拖拽操作
Cytoscape的节点拖拽核心是**连续触发mousedown(在节点上)、mousemove(移动到目标位置)、mouseup**三个事件,我们用Cypress的trigger命令就能模拟这个完整流程。
实战代码示例
// 假设你的Cytoscape容器ID是"cy",要拖拽的节点ID是"node-1",目标位置是(300, 200) cy.get('#cy').within(() => { const targetNode = cy.get('[data-id="node-1"]'); // 先获取节点初始位置(可选,用来验证拖拽效果) targetNode.invoke('position').then(initialPos => { // 模拟鼠标按下节点中心(用节点宽高的一半取中心坐标) targetNode.trigger('mousedown', { clientX: initialPos.x + 50, // 假设节点宽100,根据实际大小调整 clientY: initialPos.y + 50, // 假设节点高100,根据实际大小调整 force: true // 强制触发事件,避开Cypress的交互检查限制 }); // 分两步模拟鼠标移动,更贴近真实用户操作 cy.window().trigger('mousemove', { clientX: 250, clientY: 150, force: true }); cy.window().trigger('mousemove', { clientX: 300, clientY: 200, force: true }); // 松开鼠标完成拖拽 cy.window().trigger('mouseup', { force: true }); // 验证节点位置是否符合预期(允许小误差,因为Cytoscape可能有吸附逻辑) targetNode.invoke('position').then(finalPos => { expect(finalPos.x).to.be.closeTo(300, 10); expect(finalPos.y).to.be.closeTo(200, 10); }); }); });
关键说明
within('#cy'):限定操作范围在Cytoscape容器内,避免选中页面上其他元素invoke('position'):调用Cytoscape节点的原生API获取坐标,比用DOM元素的getBoundingClientRect更准确force: true:解决Cytoscape节点可能因层级问题被判定为“不可交互”的问题,强制触发事件
二、测试边的拖拽操作
边的拖拽分两种场景:拖拽边的中间段调整路径、拖拽边的端点重新连接节点。这里重点讲最常用的端点拖拽重连测试。
实战代码示例(拖拽边端点到新节点)
cy.get('#cy').within(() => { // 获取要拖拽的边的源端点(类名根据你的Cytoscape样式调整,默认是cy-edge-handle) const edgeSourceHandle = cy.get('.cy-edge-handle-source'); // 获取目标节点 const newTargetNode = cy.get('[data-id="node-2"]'); // 获取目标节点的中心位置 newTargetNode.invoke('position').then(targetPos => { // 鼠标按下边的端点 edgeSourceHandle.trigger('mousedown', { clientX: edgeSourceHandle[0].getBoundingClientRect().x + 3, clientY: edgeSourceHandle[0].getBoundingClientRect().y + 3, force: true }); // 拖拽到目标节点中心 cy.window().trigger('mousemove', { clientX: targetPos.x + 50, clientY: targetPos.y + 50, force: true }); // 松开鼠标完成重连 cy.window().trigger('mouseup', { force: true }); // 验证边的连接关系是否更新(直接调用Cytoscape API检查) cy.window().then(win => { const cyInstance = win.cy; // 假设全局有Cytoscape实例对象cy const targetEdge = cyInstance.$('#edge-1'); // 获取对应的边 expect(targetEdge.source().id()).to.equal('node-2'); // 验证源节点已更新为node-2 }); }); });
关键说明
- 边端点的选择器:可以通过浏览器开发者工具查看Cytoscape生成的边手柄元素类名,默认是
cy-edge-handle,源端会加cy-edge-handle-source,目标端加cy-edge-handle-target - 验证逻辑:直接访问全局的Cytoscape实例,调用它的API检查边的连接关系,这是最可靠的验证方式,比检查DOM元素更准确
三、避坑小贴士
- 等待Cytoscape初始化完成:可以加
cy.window().should('have.property', 'cy')确保Cytoscape实例已经加载好再执行测试 - 动态计算坐标:如果节点大小不固定,用
getBoundingClientRect()动态计算中心坐标,比如node[0].getBoundingClientRect().left + node[0].getBoundingClientRect().width / 2 - 增加操作延迟:如果拖拽不生效,在
mousedown和mousemove之间加cy.wait(100),模拟真实用户的操作间隔
内容的提问来源于stack exchange,提问作者Americo Savinon
相关产品推荐
相关产品推荐

