Skip to content

Commit 3c19284

Browse files
committed
Add support for Drag&Drop files into browser.
Fixes #47
1 parent ae55622 commit 3c19284

File tree

3 files changed

+79
-4
lines changed

3 files changed

+79
-4
lines changed

atest/draganddropfile.robot

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
*** Settings ***
2+
Documentation Verifies that files can be dragged into browser
3+
Test Teardown Close All Browsers
4+
Test Template Dropzone Test
5+
Library SeleniumLibrary plugins=${CURDIR}/../src/SeleniumTestability;False;29 seconds;False
6+
Resource resources.robot
7+
8+
*** Variables ***
9+
${URL} https://www.dropzonejs.com
10+
${FILENAME} resources.robot
11+
12+
13+
*** Test Cases ***
14+
Drag And Drop File in Firefox
15+
${FF} ${URL}
16+
17+
Drag And Drop File in Chrome
18+
${GC} ${URL}
19+
20+
*** Keywords ***
21+
Dropzone Test
22+
[Arguments] ${BROWSER} ${URL}
23+
[Documentation] Drags and drops image from element to another
24+
Setup Web Environment ${BROWSER} ${URL}
25+
Element Should Not Contain xpath://div[@class="dz-filename"] ${FILENAME}
26+
Drag And Drop file:${CURDIR}${/}${FILENAME} id:demo-upload
27+
Element Should Contain xpath://div[@class="dz-filename"] ${FILENAME}

src/SeleniumTestability/javascript.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,32 @@
6767
"testability_config": """
6868
window.testability_config = arguments[0]
6969
""",
70+
"drag_and_drop_file": """
71+
var target = arguments[0],
72+
parentElement = target.parentElement
73+
offsetX = arguments[1],
74+
offsetY = arguments[2],
75+
document = target.ownerDocument || document,
76+
window = document.defaultView || window;
77+
78+
var input = document.createElement('INPUT');
79+
input.type = 'file';
80+
input.onchange = function () {
81+
var rect = target.getBoundingClientRect(),
82+
x = rect.left + (offsetX || (rect.width >> 1)),
83+
y = rect.top + (offsetY || (rect.height >> 1)),
84+
dataTransfer = { files: this.files };
85+
86+
['dragenter', 'dragover', 'drop'].forEach(function (name) {
87+
var evt = document.createEvent('MouseEvent');
88+
evt.initMouseEvent(name, !0, !0, window, 0, 0, 0, x, y, !1, !1, !1, !1, 0, null);
89+
evt.dataTransfer = dataTransfer;
90+
target.dispatchEvent(evt);
91+
});
92+
93+
setTimeout(function () { parentElement.removeChild(input); }, 25);
94+
};
95+
parentElement.appendChild(input);
96+
return input;
97+
""",
7098
}

src/SeleniumTestability/plugin.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import re
3030
import json
3131
from time import time
32+
from pathlib import Path
3233

3334

3435
@wrapt.decorator
@@ -509,20 +510,39 @@ def drag_and_drop(self: "SeleniumTestability", locator: LocatorType, target: Loc
509510
and the ``target`` is the locator of the target. See the
510511
`Locating elements` section for details about the locator syntax.
511512
513+
If you wish to drag and drop a file from a local filesystem, you can specify the locator as `file:/full/path/to/filename`
514+
and SeleniumTestability will generate a drag'n'drop events to upload a file into a given `target` element.
515+
512516
``html5`` parameter is optional and if provided, `drag_and_drop`will utilize
513517
javascript to trigger the suitable events ensuring that html5 applications
514-
receive the right events
518+
receive the right events. If `locator` starts with file: prefix, html5 defaults to True.
515519
516520
Example:
517-
| `Drag And Drop` | css:div#element | css:div.target | True |
521+
| `Drag And Drop` | css:div#element | css:div.target | html5=True |
522+
| `Drag And Drop` | file:/home/rasjani/testfile.txt | id:demo-upload |
518523
"""
524+
file_prefix = "file:"
519525
html5 = is_truthy(html5)
526+
if file_prefix in locator:
527+
html5 = True
528+
520529
if not html5:
521530
self.el.drag_and_drop(locator, target)
522531
else:
523-
from_element = self.el.find_element(locator)
524532
to_element = self.el.find_element(target)
525-
self.ctx.driver.execute_script(JS_LOOKUP["dragdrop"], from_element, to_element)
533+
filename = None
534+
if type(locator) == str and file_prefix in locator:
535+
filename = locator[locator.startswith(file_prefix) and len(file_prefix):]
536+
537+
if filename is not None:
538+
if Path(filename).exists():
539+
file_input = self.driver.execute_script(JS_LOOKUP["drag_and_drop_file"], to_element, 0, 0)
540+
file_input.send_keys(filename)
541+
else:
542+
raise RuntimeError(f"Unable to upload {filename} - its missing")
543+
else:
544+
from_element = self.el.find_element(locator)
545+
self.ctx.driver.execute_script(JS_LOOKUP["dragdrop"], from_element, to_element)
526546

527547
@log_wrapper
528548
@keyword

0 commit comments

Comments
 (0)