Selenium WebDriver:dragAndDrop方法在IE11和IE10中失败

我们一直在使用SauceLabs来进行我们每晚的Jenkins CItesting。 我们已经在Windows 8下运行了testing,没有任何问题。 现在我们要扩展testing并在更多的平台和浏览器上运行它们。 我们的目标是在Windows和OSX以及IE11,10和9下的最新Firefox和Chrome浏览器中运行testing。

testing是使用node.js客户端为webdriver / selenium2编写的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,只是不是我们的testing。 这是一个图像裁剪工具和使用拖放function的input滑块。 我们觉得在IE浏览器中脚本有最大的破坏风险,所以最好让testing工作。

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

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

但没有任何运气。 我不知道Selenium是否有bug,或者是什么问题。 我在谷歌上花费的时间使我不明智。 任何帮助将不胜感激。

更新

到目前为止,我已经尝试将document.body.focus()焦点设置为body。 我已经尝试使用不同的目标模拟JavaScript鼠标点击和本机WebDriver点击。 尝试复制在SauceLabs中控制VM时发生的事情。 没有任何工作,我甚至不知道它会解决问题,如果它的工作。

我也应该澄清,这不是页面上的第一个动作。 在初始导航之后,两个input字段被填充,然后testing等待AJAX​​调用完成。 然后当适当的元素可以被发现这个方法运行。

下面是pstenstrm解决scheme的一个改进版本,用于说明元素在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); } 

我发现这个问题的解决scheme是在JavaScript中执行该function。 这不是一个完美的解决scheme,但它对我们有效。

该脚本不适用于IE9,并且在Chrome / Firefox中导致了一些断言错误。 这是奇怪的,但完全除了重点; 它在IE10和IE11中完美工作。 最坏的情况下,我必须使用这个解决scheme的IE10 / 11和其他在IE9 / Firefox /铬。

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

 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中不能有linebreak。 清理它看起来像这样:

 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评论,最终使我的答案。

Interesting Posts