自从我发布这个问题以来,我已经找到了一些不同的解决方案来解决这个问题。我将它们发布在这里以供参考,以便这个问题对其他人有用:
当 Selenium 中的拖放无法用于 HTML5 时,针对 Selenium 输入了一个缺陷,一些人用建议的 Javascript 解决方案评论了该缺陷:
jQuery/HTML5 解决方案
http://code.google.com/p/selenium/issues/detail?id=3604#c9
这是一个基于 ruby 的解决方案,可以翻译成 Java、C# 或 Selenium 支持的任何其他语言。它需要 JQuery 出现在页面上,从其他尝试使用此解决方案的用户的许多评论中可以清楚地看出,这似乎仅适用于 HTML5 页面:
我们制定的解决方法对我们有用。它是测试我们的 Ember.js 应用程序的救命稻草。
附件是我们正在使用的最新版本...
这就是我们在 test_helper 中的内容:
def drag_and_drop(source,target)
js_filepath=File.dirname(__FILE__)+"/drag_and_drop_helper.js"
js_file= File.new(js_filepath,"r")
java_script=""
while (line=js_file.gets)
java_script+=line
end
js_file.close
@driver.execute_script(java_script+"$('#{source}').simulateDragDrop({ dropTarget: '#{target}'});")
rescue Exception => e
puts "ERROR :" + e.to_s
end
引用的 Javascript 拖放模拟的源代码发布在此处:
https://gist.github.com/rcorreia/2362544
(function( $ ) {
$.fn.simulateDragDrop = function(options) {
return this.each(function() {
new $.simulateDragDrop(this, options);
});
};
$.simulateDragDrop = function(elem, options) {
this.options = options;
this.simulateEvent(elem, options);
};
$.extend($.simulateDragDrop.prototype, {
simulateEvent: function(elem, options) {
/*Simulating drag start*/
var type = 'dragstart';
var event = this.createEvent(type);
this.dispatchEvent(elem, type, event);
/*Simulating drop*/
type = 'drop';
var dropEvent = this.createEvent(type, {});
dropEvent.dataTransfer = event.dataTransfer;
this.dispatchEvent($(options.dropTarget)[0], type, dropEvent);
/*Simulating drag end*/
type = 'dragend';
var dragEndEvent = this.createEvent(type, {});
dragEndEvent.dataTransfer = event.dataTransfer;
this.dispatchEvent(elem, type, dragEndEvent);
},
createEvent: function(type) {
var event = document.createEvent("CustomEvent");
event.initCustomEvent(type, true, true, null);
event.dataTransfer = {
data: {
},
setData: function(type, val){
this.data[type] = val;
},
getData: function(type){
return this.data[type];
}
};
return event;
},
dispatchEvent: function(elem, type, event) {
if(elem.dispatchEvent) {
elem.dispatchEvent(event);
}else if( elem.fireEvent ) {
elem.fireEvent("on"+type, event);
}
}
});
})(jQuery);
另一位用户在对他完全不适用时发布了附加代码,以及一些将 JQuery 注入页面的说明:
http://code.google.com/p/selenium/issues/detail?id=3604#c25
我们在发布作为解决此问题的解决方法的原始 drag_and_drop_helper.js 时遇到了问题。解决方法是 99% 正确,但我需要修改解决方法以将 dropTarget 包含在通过模拟拖动中的“坐标”对象传播的选项中。
即我需要改变:
coord = { clientX: x, clientY: y }
至:
coord = { clientX: x, clientY: y , dropTarget: options.dropTarget || undefined }
另外,对于那些遵循示例用法的人的注意事项,如果被测应用程序尚未将 jQuery 函数别名为 $,则需要拼写 jQuery:
即,在将拖放助手注入页面后,我们有一个接受 jQuery 选择器的方法来使用模拟的拖放功能(Java):
/**
* Drag and drop via the JQuery-based drag and drop helper -- the helper
* must have been injected onto the page prior to calling this method.
*
* @param dragSourceJQuerySelector a JQuery-style selector that identifies the source element to drag;
* <em>will be passed directly to jQuery(), perform all quoting yourself</em>
* @param dropTargetJQuerySelector a JQuery-style selector that identifies the target element to drop the source onto;
* <em>will be passed directly to jQuery(), perform all quoting yourself</em>
*/
protected void dragAndDropViaJQueryHelper(String dragSourceJQuerySelector, String dropTargetJQuerySelector) {
String javascript =
"var dropTarget = jQuery(" + dropTargetJQuerySelector + ");" +
"\n" +
"jQuery("+ dragSourceJQuerySelector + ").simulate('drag', { dropTarget: dropTarget });";
getLogger().info("executing javascript:\n" + javascript);
this.executeScript(javascript);
getLogger().info("executed drag-n-drop action via javascript");
}
另一个非 jQuery 解决方案
http://ynot408.wordpress.com/2011/09/22/drag-and-drop-using-selenium-webdriver/
基于 Javascript 的拖放,可跨浏览器工作。
在 selenium 中使用 RemoteWebDriver 时,鼠标移动在 2.3 版之后停止工作。下面的函数将元素 1 拖到元素 2 的位置并释放鼠标。
public void dragdrop(By ByFrom, By ByTo) {
WebElement LocatorFrom = driver.findElement(ByFrom);
WebElement LocatorTo = driver.findElement(ByTo);
String xto=Integer.toString(LocatorTo.getLocation().x);
String yto=Integer.toString(LocatorTo.getLocation().y);
((JavascriptExecutor)driver).executeScript("function simulate(f,c,d,e){var b,a=null;for(b in eventMatchers)if(eventMatchers[b].test(c)){a=b;break}if(!a)return!1;document.createEvent?(b=document.createEvent(a),a==\"HTMLEvents\"?b.initEvent(c,!0,!0):b.initMouseEvent(c,!0,!0,document.defaultView,0,d,e,d,e,!1,!1,!1,!1,0,null),f.dispatchEvent(b)):(a=document.createEventObject(),a.detail=0,a.screenX=d,a.screenY=e,a.clientX=d,a.clientY=e,a.ctrlKey=!1,a.altKey=!1,a.shiftKey=!1,a.metaKey=!1,a.button=1,f.fireEvent(\"on\"+c,a));return!0} var eventMatchers={HTMLEvents:/^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,MouseEvents:/^(?:click|dblclick|mouse(?:down|up|over|move|out))$/}; " +
"simulate(arguments[0],\"mousedown\",0,0); simulate(arguments[0],\"mousemove\",arguments[1],arguments[2]); simulate(arguments[0],\"mouseup\",arguments[1],arguments[2]); ",
LocatorFrom,xto,yto);
}