Electron应用使用Webdriver测试react-beautiful-dnd拖拽功能失效问题
拖拽测试失效的核心原因
- react-beautiful-dnd(以下简称rbd)基于HTML5拖拽事件流实现,内置了拖拽事件合法性校验逻辑,webdriver原生
dragAndDrop方法、默认的指针事件模拟序列不符合真实用户操作特征,会被rbd直接拦截,不会触发拖拽响应。 - 现有
performActions代码存在参数错误:button: 1代表鼠标中键,而rbd仅响应鼠标左键(button: 0)的拖拽操作。 - 代码存在笔误:未定义
searchInput变量,直接调用searchInput.getValue()会抛出未定义错误,应该替换为你之前声明的target变量。 - 依赖版本不兼容:你使用的spectron 11、electron-chromedriver 11对应支持的electron版本为11.x,而你实际使用的electron版本是9.4.3,版本不匹配导致指针事件传递存在异常。
- 事件序列不符合rbd要求:拖拽移动直接从源位置跳转到目标位置,没有中间过渡的移动步骤,rbd会判定为非用户真实操作,忽略拖拽请求。
修复方案
1. 优先修复代码错误
首先将performActions配置中的button: 1修改为button: 0,将searchInput.getValue()修改为target.getValue()。
2. 调整事件模拟序列匹配rbd校验规则
修改performActions的事件配置,增加中间移动步骤、合理设置延迟,模拟真实用户拖拽轨迹,参考修正后的代码:
it('should display the correct string when the rows are dragged and dropped in a different order', async () => { const correctString = '"Field3": Value3^4 & "Field1": Value1^2 & "Field2": Value2^3' const target = await app.client.$('[id="search_input"]'); const sourceElement = await app.client.$('[id="row_1"]'); const getCoordsForElement = async (elementId) => { const rect = await app.client.getElementRect(elementId); const X = parseInt(rect.x + (rect.width / 2), 10); const Y = parseInt(rect.y + (rect.height / 2), 10); return [X, Y]; }; const [sourceX, sourceY] = await getCoordsForElement(sourceElement.elementId) const [targetX, targetY] = await getCoordsForElement(target.elementId) const [diffX, diffY] = [targetX - sourceX, targetY - sourceY] await app.client.performActions([{ type: 'pointer', id: 'finger1', parameters: { pointerType: 'mouse' }, actions: [ // 移动到源元素中心 { type: 'pointerMove', duration: 100, x: sourceX, y: sourceY }, // 按下鼠标左键 { type: 'pointerDown', button: 0 }, // 等待rbd识别拖拽启动 { type: 'pause', duration: 200 }, // 先移动一小段距离,触发拖拽识别 { type: 'pointerMove', duration: 200, origin: "pointer", x: 10, y: 10 }, // 移动到目标位置附近 { type: 'pointerMove', duration: 500, origin: "pointer", x: diffX - 10, y: diffY - 10 }, // 最后移动到目标位置 { type: 'pointerMove', duration: 200, origin: "pointer", x: 10, y: 10 }, // 等待drop事件触发 { type: 'pause', duration: 200 }, // 松开鼠标左键 { type: 'pointerUp', button: 0 } ] }]); await app.client.pause(1000) const text = await target.getValue() console.log("TEXT: ", text) assert.strictEqual(text, correctString, `Expected the correct string to be "${correctString}". Instead it was "${text}".`) })
3. 修复依赖版本兼容性
要么将electron版本升级到11.x匹配现有spectron、electron-chromedriver版本,要么将spectron降级到10.x、electron-chromedriver降级到9.x,匹配你当前使用的electron 9.4.3版本。
4. 兜底方案:直接在前端上下文触发拖拽事件
如果上述方案仍然失效,可以跳过webdriver的事件模拟层,直接在页面执行JS代码触发rbd要求的完整事件流,适配性最高,参考代码:
it('should display the correct string when the rows are dragged and dropped in a different order', async () => { const correctString = '"Field3": Value3^4 & "Field1": Value1^2 & "Field2": Value2^3' const target = await app.client.$('[id="search_input"]'); const sourceElement = await app.client.$('[id="row_1"]'); // 直接在前端执行拖拽事件模拟 await app.client.execute((sourceId, targetId) => { const source = document.getElementById(sourceId); const target = document.getElementById(targetId); const sourceRect = source.getBoundingClientRect(); const targetRect = target.getBoundingClientRect(); // 触发mousedown启动拖拽 source.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true, clientX: sourceRect.x + 10, clientY: sourceRect.y + 10, button: 0 })); // 小幅度移动触发rbd拖拽识别 document.dispatchEvent(new MouseEvent('mousemove', { bubbles: true, cancelable: true, clientX: sourceRect.x + 15, clientY: sourceRect.y + 15 })); // 移动到目标位置 document.dispatchEvent(new MouseEvent('mousemove', { bubbles: true, cancelable: true, clientX: targetRect.x + 10, clientY: targetRect.y + 10 })); // 松开鼠标完成拖拽 document.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true })); }, 'row_1', 'search_input'); await app.client.pause(1000) const text = await target.getValue() console.log("TEXT: ", text) assert.strictEqual(text, correctString, `Expected the correct string to be "${correctString}". Instead it was "${text}".`) })
内容的提问来源于stack exchange,提问作者JMArmbruster
相关产品推荐
相关产品推荐

