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

如何使用browser.performActions在Firefox中正确模拟Ctrl/Meta按键按下

问题根因

Firefox搭配geckodriver时严格遵循W3C WebDriver标准动作规范,和Chrome的兼容实现逻辑存在差异:

  • 单独调用的item.click()属于WebDriver封装的独立原子操作,执行时会重置输入源状态,不会继承之前通过performActions触发的Ctrl按下状态,因此只会触发普通点击。
  • 拆分多次调用performActions提交动作时,geckodriver会自动释放处于按下状态的修饰键,不会跨请求保留按键状态。
代码调整方案

需要把Ctrl按下、多元素点击、Ctrl释放的所有逻辑整合到同一次performActions调用中,不要在动作流程中插入独立的click()原子操作,通过指针类型的动作序列完成点击,具体修正代码如下:

const ctlKey = '\uE009';
// 构建完整的多输入源动作序列
const actionList = [
  // 键盘输入源:全程按住Ctrl直到所有点击完成
  {
    type: 'key',
    id: 'keyboard',
    actions: [
      { type: 'keyDown', value: ctlKey },
      // 插入和点击动作等长的暂停,保证Ctrl按住状态覆盖所有点击周期
      ...items.map(() => ({ type: 'pause', duration: 100 })),
      { type: 'keyUp', value: ctlKey }
    ]
  },
  // 鼠标指针输入源:依次完成所有元素点击
  {
    type: 'pointer',
    id: 'mouse',
    parameters: { pointerType: 'mouse' },
    actions: items.flatMap(item => {
      const location = item.getLocation();
      const size = item.getSize();
      return [
        // 移动到元素中心位置
        {
          type: 'pointerMove',
          x: Math.round(location.x + size.width / 2),
          y: Math.round(location.y + size.height / 2),
          origin: 'viewport'
        },
        { type: 'pointerDown', button: 0 },
        { type: 'pause', duration: 50 },
        { type: 'pointerUp', button: 0 },
        { type: 'pause', duration: 50 }
      ]
    })
  }
];
// 一次性提交完整动作序列
browser.performActions(actionList);
// 执行完成后释放所有输入源残留状态,避免影响后续测试
browser.releaseActions();
额外注意事项
  • 动作序列执行过程中不要插入scrollIntoView、click、setValue这类独立的WebDriver原子命令,否则会重置geckodriver的输入源状态,导致修饰键失效。
  • 如果测试环境是macOS,需要将Ctrl键替换为Command键(对应Unicode编码为\uE03D),Windows、Linux环境使用现有\uE009编码即可。
  • geckodriver v0.30.0版本存在已知的修饰键状态残留问题,每次执行完组合键动作后必须调用releaseActions()清空状态,避免后续用例出现按键粘连。

内容的提问来源于stack exchange,提问作者Kenneth

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:48:20