自动化 End-End 测试 Nightwatch.js 之踩雷笔记:点击物件 III

点击物件是蛮基本的操作,不过还是有很多地方需要注意。

回顾

第一天提到了如果该物件是 div,例如这个问号 Icon,在 Safari 会无法成功点击,可以利用之前客制化的 clickDiv() 来完成
https://ithelp.ithome.com.tw/upload/images/20210923/20120250LV0LGwsrds.png

第二天则提到如果物件被遮蔽,则一样可以使用 clickDiv()setValue() 送出空白键或先 scollIntoView() 滚动至画面中间位置再进行点击
https://imgur.com/G5W6nDk.gif

因此点击一个物件需要注意:

  • 所设定的 selector 是否正确,也可以搭配以下属性
    • :n-child()
    • :first-child
    • :last-child
  • 物件是否为 <div>
  • 物件是否被遮蔽

不过还有一种情况是点击物件的特定位置,像是这样:
https://ithelp.ithome.com.tw/upload/images/20210923/20120250jnX4QiJ7Rc.png

单纯点击只会点击物件的 (0, 0) 位置,但如果想要调成特定的数值,就必须加入 offset

moveToElement() & mouseButtonClick()

这个指令可以移动滑鼠到物件的特定位置,如果没有给 offset 也可以移到物件正中间,也具备 scroll into view 的特性。

browser.moveToElement(using, selector, xoffset, yoffset, [callback])

不过移动位置还不够,还必须点击才行,这时不能使用 click(),而是需要使用 mouseButtonClick()

browser.mouseButtonClick(button)

button 为点击滑鼠的哪一个按钮,分别可以是:(0, 1, 2) 或 ('left', 'middle', 'right')

clickOnElement()

不过可惜的是,上面 moveToElement()mouseButtonClick() 在 Firefox/Safari 同样因 W3C/WebDriver protocol 而无法使用。

因此同样依照之前写 clickDiv() 的想法,利用 Javascript 去触发。

大概的想法是这样:

  • getBoundingClientRect() 用於取的该物件的长宽高及 x, y 座标
  • 计算 offset
  • 加入 MouseEvent()
  • 最後 dispatchEvent()

取得座标

let elem = document.querySelector(selector);
let rect = elem.getBoundingClientRect(),
    posX = rect.left,
    posY = rect.top;

计算点击的 offset

if (typeof offsetX == 'number') posX += offsetX;
else if (offsetX == 'center') {
posX += rect.width / 2;
if (offsetY == null) posY += rect.height / 2;
}
if (typeof offsetY == 'number') posY += offsetY;

加入 click 的 MouseEvent

var evt = new MouseEvent('click', {
        bubbles: true,
        clientX: posX,
        clientY: posY,
      });

dispatchEvent

elem.dispatchEvent(evt);

command 形式

exports.command = function(selector, offsetX, offsetY, callback) {
  callback = callback || function() {};
  this.execute(
    function clickOnElement(selector, offsetX, offsetY) {
      let elem = document.querySelector(selector);
      let rect = elem.getBoundingClientRect(),
        posX = rect.left,
        posY = rect.top;
      if (typeof offsetX == 'number') posX += offsetX;
      else if (offsetX == 'center') {
        posX += rect.width / 2;
        if (offsetY == null) posY += rect.height / 2;
      }
      if (typeof offsetY == 'number') posY += offsetY;
      var evt = new MouseEvent('click', {
        bubbles: true,
        clientX: posX,
        clientY: posY,
      });
      elem.dispatchEvent(evt);
    },
    [selector, offsetX, offsetY],
    function(result) {
      callback.call(this, result);
    },
  );
  return this;
};

总结

这三天完成了点击几个比较特别的情况,大致上把会遇到的问题都写完了。接下来会介绍透过客制化指令,达成一些组合技的测试,使测试档案简洁好看~


<<:  [Day09]程序菜鸟自学C++资料结构演算法 – 堆叠Stack介绍与建立

>>:  Day 11 - 成长曲线N+1 : 商业分析师

[Day 8] 第一主餐-django说明及环境安装

昨天我们终於把BeautifulSoup这碗汤给喝的乾乾净净,一滴不剩 现在终於要来上我们的主餐啦,...

Day14:全端工程师的工作内容?(上)

一、前言   因为我待的是较小型的接案公司,基本上全端工程师的工作几乎全包,从投标、接案、访谈客户需...

[Day30] - 完赛、感想、心得

Day30 - 完赛、感想、心得 心得 坚持 - 坚持阿,哪次不坚持 当初觉得30天应该不难吧,就每...

Day 6 轻松了解欧洲个资隐私保护

在完整完善的隐私保护设计之下,也需有个健全的隐私保护法规在背後做支撑,藉由完善法规制度的保护之下,视...

网页储存区 - localStorage & sessionStorage

网页可以储存使用者偏好,可以在关掉网页後重新访问时纪录使用者上次浏览的状态,能做到这些神奇的事是因为...