上一篇 - Macaca 录制器实现原理

在处理 Native 物理事件模拟的场景时,我们直接使用 keys 发送响应的 keyCode,如 macaca-sample 中的一些示例,当我们遇到网页测试场景中,应该如何触发键盘事件呢?

创建 UIEvents 对象

通过创建 UIEvents 对象,可以自定义键盘事件的触发。

wd.addPromiseChainMethod('keyboardEvent', function(cssSelector, eventType = 'keydown', keyCode = 13) {
  // TODO
  // HTMLEvents
  eventType = eventType.toLowerCase();
  const uuid = Date.now();
  const element = `document.querySelector('${cssSelector}')`;
  const script = `
    var _element_${uuid} = ${element};
    var event_${uuid} = document.createEvent('UIEvents');
    event_${uuid}.initUIEvent('${eventType}', true, true, window, 0);
    event_${uuid}.keyCode = ${keyCode};
    _element_${uuid}.dispatchEvent(event_${uuid});
  `;
  return this
    .execute(script)
    .sleep(100);
});

模拟输入行为

wd.addPromiseChainMethod('formatInput', function(cssSelector, string) {
  const uuid = Date.now();
  const input = `document.querySelector('${cssSelector}')`;
  const eventHandle = `
    var event_${uuid} = document.createEvent('Event');
    event_${uuid}.initEvent('input', true, true);
    _element_${uuid}.dispatchEvent(event_${uuid});
  `;
  const list = Array.prototype.slice.call(string);

  if (!list.length) {
    return this;
  }
  let value = list[0];

  if (list.length === 1) {
    const script = `
      var _element_${uuid} = ${input};
      _element_${uuid}.value='${value}';
      ${eventHandle}
    `;
    return this
      .execute(script)
      .sleep(100);
  }

  return Promise.reduce(list, (i, item) => {
    value += item;
    const script = `
      var _element_${uuid} = ${input};
      _element_${uuid}.value='${value}';
      ${eventHandle}
    `;
    return this
      .execute(script)
      .sleep(100);
  });
});

举个实例

我们以一个实例项目 TODO List 来说明下用法:

  1. 当用户点击输入框,输入框处于聚焦状态,可以接收内容输入
  2. 使用 setValue 或 formatInput 可以对当前输入框输入文字
  3. 当输入完成之后,按下 ENTER 键执行添加操作
  4. ENTER 的 Keycode 为 13,更多映射见 KeyboardEvent/keyCode
  5. 以上为 Javascript 语言的实现,Java 与 Python 语言请参照如上的模板 通过 execute 执行

那么用例的写法为:

it('setValue vs formatInput', () => {
  return driver
    .formatInput('#new-todo', `input by formatInput ${Date.now()}`)
    .keyboardEvent('#new-todo', 'keyUp', 13)
    .sleep(3000)
    .elementByCss('#new-todo')
    .clear()
    .sendKeys(`input by sendKeys ${Date.now()}`)
    .keyboardEvent('#new-todo', 'keyUp', 13)
    .sleep(3000);
});

注意

试试截图上的示例?

$ git clone https://github.com/enoughjs/dataflow-sample.git --depth=1
$ cd dataflow-sample
$ npm i
$ npm run dev:test
# 此时新开启一个terminal运行下面的命令
$ npm run test:vuex

欢迎讨论,互相学习。

微博: http://weibo.com/xudafeng
Github: https://github.com/xudafeng

下一篇 - Macaca 处理网页手势事件


↙↙↙阅读原文可查看相关链接,并与作者交流