Skip to content

Instantly share code, notes, and snippets.

@florentbr
Last active April 7, 2024 02:56
Show Gist options
  • Star 43 You must be signed in to star a gist
  • Fork 14 You must be signed in to fork a gist
  • Save florentbr/349b1ab024ca9f3de56e6bf8af2ac69e to your computer and use it in GitHub Desktop.
Save florentbr/349b1ab024ca9f3de56e6bf8af2ac69e to your computer and use it in GitHub Desktop.
Selenium - Drop a file from the desktop on a drop area
from selenium import webdriver
from selenium.webdriver.remote.webelement import WebElement
import os.path
# JavaScript: HTML5 File drop
# source : https://gist.github.com/florentbr/0eff8b785e85e93ecc3ce500169bd676
# param1 WebElement : Drop area element
# param2 Double : Optional - Drop offset x relative to the top/left corner of the drop area. Center if 0.
# param3 Double : Optional - Drop offset y relative to the top/left corner of the drop area. Center if 0.
# return WebElement : File input
JS_DROP_FILES = "var k=arguments,d=k[0],g=k[1],c=k[2],m=d.ownerDocument||document;for(var e=0;;){var f=d.getBoundingClientRect(),b=f.left+(g||(f.width/2)),a=f.top+(c||(f.height/2)),h=m.elementFromPoint(b,a);if(h&&d.contains(h)){break}if(++e>1){var j=new Error('Element not interactable');j.code=15;throw j}d.scrollIntoView({behavior:'instant',block:'center',inline:'center'})}var l=m.createElement('INPUT');l.setAttribute('type','file');l.setAttribute('multiple','');l.setAttribute('style','position:fixed;z-index:2147483647;left:0;top:0;');l.onchange=function(q){l.parentElement.removeChild(l);q.stopPropagation();var r={constructor:DataTransfer,effectAllowed:'all',dropEffect:'none',types:['Files'],files:l.files,setData:function u(){},getData:function o(){},clearData:function s(){},setDragImage:function i(){}};if(window.DataTransferItemList){r.items=Object.setPrototypeOf(Array.prototype.map.call(l.files,function(x){return{constructor:DataTransferItem,kind:'file',type:x.type,getAsFile:function v(){return x},getAsString:function y(A){var z=new FileReader();z.onload=function(B){A(B.target.result)};z.readAsText(x)},webkitGetAsEntry:function w(){return{constructor:FileSystemFileEntry,name:x.name,fullPath:'/'+x.name,isFile:true,isDirectory:false,file:function z(A){A(x)}}}}}),{constructor:DataTransferItemList,add:function t(){},clear:function p(){},remove:function n(){}})}['dragenter','dragover','drop'].forEach(function(v){var w=m.createEvent('DragEvent');w.initMouseEvent(v,true,true,m.defaultView,0,0,0,b,a,false,false,false,false,0,null);Object.setPrototypeOf(w,null);w.dataTransfer=r;Object.setPrototypeOf(w,DragEvent.prototype);h.dispatchEvent(w)})};m.documentElement.appendChild(l);l.getBoundingClientRect();return l"
def drop_files(element, files, offsetX=0, offsetY=0):
driver = element.parent
isLocal = not driver._is_remote or '127.0.0.1' in driver.command_executor._url
paths = []
# ensure files are present, and upload to the remote server if session is remote
for file in (files if isinstance(files, list) else [files]) :
if not os.path.isfile(file) :
raise FileNotFoundError(file)
paths.append(file if isLocal else element._upload(file))
value = '\n'.join(paths)
elm_input = driver.execute_script(JS_DROP_FILES, element, offsetX, offsetY)
elm_input._execute('sendKeysToElement', {'value': [value], 'text': value})
WebElement.drop_files = drop_files
############################# USAGE EXAMPLE #############################
driver = webdriver.Chrome()
driver.get("https://react-dropzone.js.org/")
dropzone = driver.find_element_by_css_selector("[data-preview='Basic example'] [style]")
# drop a single file
dropzone.drop_files("C:\\temp\\image1.png")
# drop two files
dropzone.drop_files(["C:\\temp\\image1.png", "C:\\temp\\image2.png"])
# drop a file by offset
dropzone.drop_files("C:\\temp\\image1.png", offsetX=25, offsetY=25)
var args = arguments,
element = args[0],
offsetX = args[1],
offsetY = args[2],
doc = element.ownerDocument || document;
for (var i = 0; ;) {
var box = element.getBoundingClientRect(),
clientX = box.left + (offsetX || (box.width / 2)),
clientY = box.top + (offsetY || (box.height / 2)),
target = doc.elementFromPoint(clientX, clientY);
if (target && element.contains(target))
break;
if (++i > 1) {
var ex = new Error('Element not interactable');
ex.code = 15;
throw ex;
}
element.scrollIntoView({behavior: 'instant', block: 'center', inline: 'center'});
}
var input = doc.createElement('INPUT');
input.setAttribute('type', 'file');
input.setAttribute('multiple', '');
input.setAttribute('style', 'position:fixed;z-index:2147483647;left:0;top:0;');
input.onchange = function (ev) {
input.parentElement.removeChild(input);
ev.stopPropagation();
var dataTransfer = {
constructor : DataTransfer,
effectAllowed : 'all',
dropEffect : 'none',
types : [ 'Files' ],
files : input.files,
setData : function setData(){},
getData : function getData(){},
clearData : function clearData(){},
setDragImage : function setDragImage(){}
};
if (window.DataTransferItemList) {
dataTransfer.items = Object.setPrototypeOf(Array.prototype.map.call(input.files, function(f) {
return {
constructor : DataTransferItem,
kind : 'file',
type : f.type,
getAsFile : function getAsFile () { return f },
getAsString : function getAsString (callback) {
var reader = new FileReader();
reader.onload = function(ev) { callback(ev.target.result) };
reader.readAsText(f);
},
webkitGetAsEntry : function webkitGetAsEntry () {
return {
constructor : FileSystemFileEntry,
name : f.name,
fullPath : '/' + f.name,
isFile : true,
isDirectory : false,
file : function file (callback) { callback(f) }
}
}
}
}), {
constructor : DataTransferItemList,
add : function add(){},
clear : function clear(){},
remove : function remove(){}
});
}
['dragenter', 'dragover', 'drop'].forEach(function (type) {
var event = doc.createEvent('DragEvent');
event.initMouseEvent(type, true, true, doc.defaultView, 0, 0, 0, clientX, clientY, false, false, false, false, 0, null);
Object.setPrototypeOf(event, null);
event.dataTransfer = dataTransfer;
Object.setPrototypeOf(event, DragEvent.prototype);
target.dispatchEvent(event);
});
};
doc.documentElement.appendChild(input);
input.getBoundingClientRect(); /* force reflow for Firefox */
return input;
var k=arguments,d=k[0],g=k[1],c=k[2],m=d.ownerDocument||document;for(var e=0;;){var f=d.getBoundingClientRect(),b=f.left+(g||(f.width/2)),a=f.top+(c||(f.height/2)),h=m.elementFromPoint(b,a);if(h&&d.contains(h)){break}if(++e>1){var j=new Error('Element not interactable');j.code=15;throw j}d.scrollIntoView({behavior:'instant',block:'center',inline:'center'})}var l=m.createElement('INPUT');l.setAttribute('type','file');l.setAttribute('multiple','');l.setAttribute('style','position:fixed;z-index:2147483647;left:0;top:0;');l.onchange=function(q){l.parentElement.removeChild(l);q.stopPropagation();var r={constructor:DataTransfer,effectAllowed:'all',dropEffect:'none',types:['Files'],files:l.files,setData:function u(){},getData:function o(){},clearData:function s(){},setDragImage:function i(){}};if(window.DataTransferItemList){r.items=Object.setPrototypeOf(Array.prototype.map.call(l.files,function(x){return{constructor:DataTransferItem,kind:'file',type:x.type,getAsFile:function v(){return x},getAsString:function y(A){var z=new FileReader();z.onload=function(B){A(B.target.result)};z.readAsText(x)},webkitGetAsEntry:function w(){return{constructor:FileSystemFileEntry,name:x.name,fullPath:'/'+x.name,isFile:true,isDirectory:false,file:function z(A){A(x)}}}}}),{constructor:DataTransferItemList,add:function t(){},clear:function p(){},remove:function n(){}})}['dragenter','dragover','drop'].forEach(function(v){var w=m.createEvent('DragEvent');w.initMouseEvent(v,true,true,m.defaultView,0,0,0,b,a,false,false,false,false,0,null);Object.setPrototypeOf(w,null);w.dataTransfer=r;Object.setPrototypeOf(w,DragEvent.prototype);h.dispatchEvent(w)})};m.documentElement.appendChild(l);l.getBoundingClientRect();return l
@semisenioritis
Copy link

worked straight out of the box!! o7
the only solution on the internet that actually solves the problem without beating around the bush.

@hieult37
Copy link

hieult37 commented Mar 7, 2024

Hi guys,
I tried to test it and get the error message.

selenium.common.exceptions.WebDriverException: Message: <unknown>: Element not interactable

Can any one can help me resolve it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment