Trigger a Javascript file drop event with Python and Selenium
I needed unit testing for a page which allows to upload files by dragging and dropping them from the desktop.
Notes
- The target element is identified by
#drag_and_drop
. driver
is an instance of the Firefox Selenium webdriver.filepath
is a string, the path to a jpeg image.- jQuery is defined in the tested web page.
- Tested with Firefox only.
Code example
import base64
import os
from selenium import webdriver
def drop_file(driver, filepath):
with open(filepath, "rb") as f:
b64 = base64.b64encode(f.read()).decode()
filename = os.path.basename(filepath)
mtime = str(int(os.path.getmtime(filepath)*1000))
driver.execute_script(
"var byte_characters = atob('"+b64+"');"
"var byte_numbers = new Array(byte_characters.length);"
"for (var i = 0; i < byte_characters.length; i++)"
"byte_numbers[i] = byte_characters.charCodeAt(i);"
"var byte_array = new Uint8Array(byte_numbers);"
"var file = new File([byte_array],'"+filename+"', {"
"type: 'image/jpg',"
"lastModified: new Date("+mtime+")"
"});"
"var e = $.Event('drop');"
"e.originalEvent = {dataTransfer: {files: [file]}};"
"$('#drag_and_drop').trigger(e);"
)
We start by encoding the file in base64 and we insert it in the script. The Javascript code will then decode the base64 string. atob()
returns a string, so we must convert it first to an array of integers, then to a byte array, which we pass as a parameter to the File constructor.
Bytes → base 64 encoded string → string → array of integers → byte array.