2

我们一直在使用 SauceLabs 进行夜间 Jenkins CI 测试。我们已经在 Windows 8 下的 Firefox 24 中运行测试,没有任何问题。现在我们想要扩展测试并在更多平台和浏览器上运行它们。我们的目标是在 Windows 和 OSX 以及 IE11、10 和 9 下的最新 Firefox 和 Chrome 浏览器中运行测试。

测试是使用 webdriver/selenium2 的 node.js 客户端编写的https://github.com/admc/wd

我现在遇到的问题是让我们的 dragAndDrop 方法在 IE11 和 IE10 中工作。它在最新的 Firefox 和 Chrome 以及 IE9 中运行良好。

编码:

dragAndDrop: function (elem, x, y) {
  var i      = 0,
      parent = elem.elementByXPath('..'),
      offsetX,
      offsetY,
      pos,
      offsetPos,
      size;

  offsetPos = this.getLocationInView(elem);
  pos = this.getLocationInView(parent);
  size = this.getSize(elem);

  offsetX = offsetPos.x - pos.x + ~~(size.width / 2);
  offsetY = offsetPos.y - pos.y + ~~(size.height / 2);

  this.moveTo(parent, offsetX, offsetY);

  this.buttonDown(0);

  if(typeof x !== 'undefined' && x) {
    for(; i <= x; i++) {
      this.moveTo(parent, offsetX + i, offsetY);
    }
  }

  if(typeof y !== 'undefined' && y) {
    i = 0;
    for(; i < y; i++) {
      this.moveTo(parent, offsetX, offsetY + i);
    }
  }

  this.buttonUp(0);
}

网站上的拖放脚本适用于 IE11 和 IE10,只是我们没有对其进行测试。它既是图像裁剪工具,又是使用拖放功能的输入滑块。我们认为在 IE 浏览器中脚本最有可能被破坏,因此让测试正常工作会很好。

当我在运行测试时控制 SauceLabs 中的浏览器时,有时单击页面主体实际上会帮助 dragAndDrop 方法工作。这几乎是我现在唯一的线索。我尝试使用 Seleniumsclick()方法来模拟它,甚至在 JavaScript 中执行它。

this.execute('var event=document.createEvent("MouseEvent");
    event.initEvent("click",true,true,window,0,50,120);
    document.body.dispatchEvent(event);');

但没有任何运气。我不知道 Selenium 中是否存在错误或问题所在。我花在谷歌上的时间让我一点也不聪明。任何帮助将不胜感激。

更新

到目前为止,我已经尝试document.body.focus()按照建议将焦点放在身体上。我尝试使用不同的目标来模拟 JavaScript 鼠标点击和原生 WebDriver 点击。试图复制我在 SauceLabs 中控制 VM 时发生的事情。没有任何效果,我什至不确定它是否可以解决问题。

我还应该澄清这不是页面上的第一个操作。初始导航后,填充了两个输入字段,然后测试等待 AJAX 调用完成。然后,当可以找到适当的元素时,运行此方法。

4

2 回答 2

1

下面是 pstenstrm 解决方案的改进版本,用于说明从元素在 X 和 Y 方向上的移动。

/*
    pageX
    pageY
    distanceX
    distanceY
    id
    className

    ###############
    The variables above were defined in the closure scope of function
    running the execute function.
*/
var mousedown = document.createEvent("MouseEvent"),
    mouseup   = document.createEvent("MouseEvent"),
    elem      = document.getElementById(id),
    result    = [],
    elems     = elem.getElementsByTagName("*"),
    k         = 0,
    j         = 0,
    i, interval;

for(i in elems){
    if((" " + elems[i].className + " ").indexOf(" " + className + " ") > -1){
        result.push(elems[i]);
    }
}

mousedown.initMouseEvent("mousedown", true, true, window, 0, 0, 0, pageX, pageY, 0, 0, 0, 0, 0, null);
result[0].dispatchEvent(mousedown);

interval = setInterval(function(){
    if(k !== distanceX){k++;}
    if(j !== distanceY){j++;}
    iter(k,j);
    if(k === distanceX + 1 && j === distanceY + 1){
        clearInterval(interval);
        mouseup.initMouseEvent("mouseup", true, true, window, 0, pageX + k, pageY + j, pageX + k, pageY + j, 0, 0, 0, 0, 0, null);
        result[0].dispatchEvent(mouseup);
    }
}, 100);

function iter(_x,_y){
    var mousemove = document.createEvent("MouseEvent");
    mousemove.initMouseEvent("mousemove", true, true, window, 0, 0, 0, pageX + _x, pageY + _y, 0, 0, 0, 0, 0, null);
    result[0].dispatchEvent(mousemove);
}

新的 dragAndDrop 看起来像:

dragAndDrop: function (elem, x, y, id, className) {
    var i = 0,
        offsetX,
        offsetY,
        pos, offsetPos,
        size;

    this.sleep(2000);

    offsetPos = this.getLocationInView(elem);
    size = this.getSize(elem);

    pageX = offsetPos.x + ~~(size.width / 2);
    pageY = offsetPos.y + ~~(size.height / 2);

    // No linebreaks
    this.execute('var mousedown=document.createEvent("MouseEvent"),mouseup=document.createEvent("MouseEvent"),elem=document.getElementById("' + id + '"),result=[],elems=elem.getElementsByTagName("*"),k=0,j=0,i,interval;for(i in elems){if((" "+elems[i].className+" ").indexOf(" ' + className + ' ")>-1){result.push(elems[i]);}}mousedown.initMouseEvent("mousedown",true,true,window,0,0,0,' + pageX + ',' + pageY +',0,0,0,0,0,null);result[0].dispatchEvent(mousedown);interval=setInterval(function(){if(k!==' + x + '){k++;};if(j!==' + y +'){j++;};iter(k,j);if(k===' + x + '+1&&j===' + y + '+1){clearInterval(interval);mouseup.initMouseEvent("mouseup",true,true,window,0,' + pageX + '+k,' + pageY +'+j,' + pageX + '+k,' + pageY +'+j,0,0,0,0,0,null);result[0].dispatchEvent(mouseup);}},100);function iter(_x,_y){var mousemove=document.createEvent("MouseEvent");mousemove.initMouseEvent("mousemove",true,true,window,0,0,0,' + pageX + '+_x,' + pageY + '+_y,0,0,0,0,0,null);result[0].dispatchEvent(mousemove);}');

    // Give the script time to execute and take a nap
    this.sleep(x*100+3000);
}
于 2014-03-26T22:12:19.230 回答
0

我发现这个问题的解决方案是在 JavaScript 中执行函数。这不是一个完美的解决方案,但它对我们有用。

该脚本不适用于 IE9,并且在 Chrome/Firefox 中导致了一些断言错误。这很奇怪,但完全无关紧要;它在 IE10 和 IE11 中完美运行。在最坏的情况下,我必须将此解决方案用于 IE10/11 和 IE9/Firefox/Chrome 中的其他解决方案。

我的拖放方法现在看起来像这样:

dragAndDrop: function (elem, x, y, id, className) {
  var i = 0,
    offsetX,
    offsetY,
    pos, offsetPos,
    size;

  this.sleep(2000);

  offsetPos = this.getLocationInView(elem);
  size = this.getSize(elem);

  pageX = offsetPos.x + ~~(size.width / 2);
  pageY = offsetPos.y + ~~(size.height / 2);

  // No linebreaks
  this.execute('var mousedown=document.createEvent("MouseEvent"),mouseup=document.createEvent("MouseEvent"),elem=document.getElementById("' + id + '"),result=[],elems=elem.getElementsByTagName("*"),k=0,i,interval;for(i in elems){if((" "+elems[i].className+" ").indexOf(" ' + className + ' ")>-1){result.push(elems[i]);}}mousedown.initMouseEvent("mousedown",true,true,window,0,0,0,' + pageX + ',' + pageY +',0,0,0,0,0,null);result[0].dispatchEvent(mousedown);interval=setInterval(function(){k++;iter(k);if(k===' + x + '+1){clearInterval(interval);mouseup.initMouseEvent("mouseup",true,true,window,0,' + pageX + '+k,' + pageY +',' + pageX + '+k,' + pageY +',0,0,0,0,0,null);result[0].dispatchEvent(mouseup);}},100);function iter(y){var mousemove=document.createEvent("MouseEvent");mousemove.initMouseEvent("mousemove",true,true,window,0,0,0,' + pageX + '+y,' + pageY +',0,0,0,0,0,null);result[0].dispatchEvent(mousemove);}');

  // Give the script time to execute and take a nap
  this.sleep(x*100+3000);
}

执行的 JS 中不能有换行符。清理后是这样的:

var mousedown = document.createEvent("MouseEvent"),
    mouseup   = document.createEvent("MouseEvent"),
    elem      = document.getElementById(id),
    result    = [],
    elems     = elem.getElementsByTagName("*"),
    k         = 0,
    i, interval;

for(i in elems){
    if((" " + elems[i].className + " ").indexOf(" " + className + " ") > -1){
        result.push(elems[i]);
    }
}

mousedown.initMouseEvent("mousedown", true, true, window, 0, 0, 0, clientX, clientY, 0, 0, 0, 0, 0, null);
result[0].dispatchEvent(mousedown);

interval = setInterval(function(){
    k++;
    iter(k);
    if(k === distance + 1){ 
        clearInterval(interval);
        mouseup.initMouseEvent("mouseup", true, true, window, 0, screenX + k, screenY, clientX + k, clientY, 0, 0, 0, 0, 0, null);
        result[0].dispatchEvent(mouseup);
    }
}, 100);

function iter(y){
    var mousemove = document.createEvent("MouseEvent");
    mousemove.initMouseEvent("mousemove", true, true, window, 0, 0, 0, clientX + y, clientY, 0, 0, 0, 0, 0, null);
    result[0].dispatchEvent(mousemove);
}

什么参数initMouseEvent()意味着你可以检查https://developer.mozilla.org/en-US/docs/Web/API/event.initMouseEvent

因为mouseup我必须设置screenX/Y,并且我假设客户端始终是屏幕的全尺寸。该代码包含很多关于它运行在什么环境中的假设,但为您的环境修改它应该不会太难。

是@JimEvans 的评论最终让我找到了答案。

于 2014-01-07T15:20:09.990 回答