On a web page I'm trying to test, we implemented drag and drop file upload. I've looked at the drag and drop API for selenium action chain API. It looks like it supports only dragging and dropping between 2 elements on a page. How to emulate dragging from a file manager?
4 Answers
To perform an HTML5 file drop with Selenium:
static final String JS_DROP_FILE =
"var tgt=arguments[0],e=document.createElement('input');e.type='" +
"file';e.addEventListener('change',function(event){var dataTrans" +
"fer={dropEffect:'',effectAllowed:'all',files:e.files,items:{},t" +
"ypes:[],setData:function(format,data){},getData:function(format" +
"){}};var emit=function(event,target){var evt=document.createEve" +
"nt('Event');evt.initEvent(event,true,false);evt.dataTransfer=da" +
"taTransfer;target.dispatchEvent(evt);};emit('dragenter',tgt);em" +
"it('dragover',tgt);emit('drop',tgt);document.body.removeChild(e" +
");},false);document.body.appendChild(e);return e;";
WebDriver driver = new FirefoxDriver();
driver.get("http://html5demos.com/file-api");
WebElement drop_area = driver.findElement(By.id("holder"));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript(JS_DROP_FILE, new Object[] {
drop_area
}).sendKeys("C:\\image.png");
2 Comments
Andrea Borgogelli Avveduti
Please, could you tell us what is the source of your solution ?
Florent B.
@Andrea Borgogelli Avveduti, I wrote the solution. Have a look here for the api: developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API
Drop file using jsExecutor
public void dropFile(File filePath, WebElement target) {
if (!filePath.exists())
throw new WebDriverException("File not found: " + filePath.toString());
JavascriptExecutor jse = (JavascriptExecutor) getDriver();
String JS_DROP_FILE =
"var target = arguments[0]," +
" offsetX = arguments[1]," +
" offsetY = arguments[2]," +
" document = target.ownerDocument || document," +
" window = document.defaultView || window;" +
"" +
"var input = document.createElement('INPUT');" +
"input.type = 'file';" +
"input.style.display = 'none';" +
"input.onchange = function () {" +
" var rect = target.getBoundingClientRect()," +
" x = rect.left + (offsetX || (rect.width >> 1))," +
" y = rect.top + (offsetY || (rect.height >> 1))," +
" dataTransfer = { files: this.files };" +
"" +
" ['dragenter', 'dragover', 'drop'].forEach(function (name) {" +
" var evt = document.createEvent('MouseEvent');" +
" evt.initMouseEvent(name, !0, !0, window, 0, 0, 0, x, y, !1, !1, !1, !1, 0, null);" +
" evt.dataTransfer = dataTransfer;" +
" target.dispatchEvent(evt);" +
" });" +
"" +
" setTimeout(function () { document.body.removeChild(input); }, 25);" +
"};" +
"document.body.appendChild(input);" +
"return input;";
WebElement input = (WebElement) jse.executeScript(JS_DROP_FILE, target, 0, 0);
input.sendKeys(filePath.getAbsoluteFile().toString());
waitFor(ExpectedConditions.stalenessOf(input));
}
Comments
Use AWT Robot class for performing drag and drop:
Robot robot=new Robot();
// drag
robot.mouseMove(x1, y1);
robot.mousePress(InputEvent.BUTTON1_MASK);
// drop
robot.mouseMove(x2, y2);
robot.mouseRelease(InputEvent.BUTTON1_MASK);