You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 09:15:03