How to simulate HTML5 Drag and Drop in Selenium Webdriver?
Question:
I am using Python 2.7 and Selenium 2.44.
I want to automate drag and drop action in Selenium WD but according to other related posts Actions in HTML5 are not supported by Selenium yet. Is there any way to simulate drag and drop in Python?
Here is the code I tried:
driver = webdriver.Firefox()
driver.get("http://html5demos.com/drag")
target = driver.find_element_by_id("one")
source = driver.find_element_by_id("bin")
actionChains = ActionChains(driver)
actionChains.drag_and_drop(target, source).perform()
and it did not work.
Answers:
Yes, HTML5 “drag&drop” is not currently supported by Selenium:
One of the suggested workarounds is to simulate HTML5 drag and drop via JavaScript:
- download
drag_and_drop_helper.js
- execute the script via
execute_script()
calling simulateDragDrop()
function on a source
element passing the target
element as a dropTarget
Sample code:
with open("drag_and_drop_helper.js") as f:
js = f.read()
driver.execute_script(js + "$('#one').simulateDragDrop({ dropTarget: '#bin'});")
The problem is that it won’t work in your case “as is” since it requires jQuery
.
Now we need to figure out how to dynamically load jQuery. Thankfully, there is a solution.
Complete working example in Python:
from selenium import webdriver
jquery_url = "http://code.jquery.com/jquery-1.11.2.min.js"
driver = webdriver.Firefox()
driver.get("http://html5demos.com/drag")
driver.set_script_timeout(30)
# load jQuery helper
with open("jquery_load_helper.js") as f:
load_jquery_js = f.read()
# load drag and drop helper
with open("drag_and_drop_helper.js") as f:
drag_and_drop_js = f.read()
# load jQuery
driver.execute_async_script(load_jquery_js, jquery_url)
# perform drag&drop
driver.execute_script(drag_and_drop_js + "$('#one').simulateDragDrop({ dropTarget: '#bin'});")
where jquery_load_helper.js
contains:
/** dynamically load jQuery */
(function(jqueryUrl, callback) {
if (typeof jqueryUrl != 'string') {
jqueryUrl = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js';
}
if (typeof jQuery == 'undefined') {
var script = document.createElement('script');
var head = document.getElementsByTagName('head')[0];
var done = false;
script.onload = script.onreadystatechange = (function() {
if (!done && (!this.readyState || this.readyState == 'loaded'
|| this.readyState == 'complete')) {
done = true;
script.onload = script.onreadystatechange = null;
head.removeChild(script);
callback();
}
});
script.src = jqueryUrl;
head.appendChild(script);
}
else {
callback();
}
})(arguments[0], arguments[arguments.length - 1]);
Before/after result:
Found working example in python (without using jquery_load_helper.js) – https://gist.github.com/rcorreia/2362544#gistcomment-2708388
Credits: Kelanmomo
As alecxe mentioned: download drag_and_drop_helper.js
# coding = utf-8
from selenium import webdriver
import os
from time import sleep
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('http://the-internet.herokuapp.com/drag_and_drop')
with open(os.path.abspath('drag_and_drop_helper.js'), 'r') as js_file:
line = js_file.readline()
script = ''
while line:
script += line
line = js_file.readline()
driver.execute_script(script + "$('#column-a').simulateDragDrop({ dropTarget: '#column-b'});")
sleep(2)
driver.quit()
I am using Python 2.7 and Selenium 2.44.
I want to automate drag and drop action in Selenium WD but according to other related posts Actions in HTML5 are not supported by Selenium yet. Is there any way to simulate drag and drop in Python?
Here is the code I tried:
driver = webdriver.Firefox()
driver.get("http://html5demos.com/drag")
target = driver.find_element_by_id("one")
source = driver.find_element_by_id("bin")
actionChains = ActionChains(driver)
actionChains.drag_and_drop(target, source).perform()
and it did not work.
Yes, HTML5 “drag&drop” is not currently supported by Selenium:
One of the suggested workarounds is to simulate HTML5 drag and drop via JavaScript:
- download
drag_and_drop_helper.js
- execute the script via
execute_script()
callingsimulateDragDrop()
function on asource
element passing thetarget
element as adropTarget
Sample code:
with open("drag_and_drop_helper.js") as f:
js = f.read()
driver.execute_script(js + "$('#one').simulateDragDrop({ dropTarget: '#bin'});")
The problem is that it won’t work in your case “as is” since it requires jQuery
.
Now we need to figure out how to dynamically load jQuery. Thankfully, there is a solution.
Complete working example in Python:
from selenium import webdriver
jquery_url = "http://code.jquery.com/jquery-1.11.2.min.js"
driver = webdriver.Firefox()
driver.get("http://html5demos.com/drag")
driver.set_script_timeout(30)
# load jQuery helper
with open("jquery_load_helper.js") as f:
load_jquery_js = f.read()
# load drag and drop helper
with open("drag_and_drop_helper.js") as f:
drag_and_drop_js = f.read()
# load jQuery
driver.execute_async_script(load_jquery_js, jquery_url)
# perform drag&drop
driver.execute_script(drag_and_drop_js + "$('#one').simulateDragDrop({ dropTarget: '#bin'});")
where jquery_load_helper.js
contains:
/** dynamically load jQuery */
(function(jqueryUrl, callback) {
if (typeof jqueryUrl != 'string') {
jqueryUrl = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js';
}
if (typeof jQuery == 'undefined') {
var script = document.createElement('script');
var head = document.getElementsByTagName('head')[0];
var done = false;
script.onload = script.onreadystatechange = (function() {
if (!done && (!this.readyState || this.readyState == 'loaded'
|| this.readyState == 'complete')) {
done = true;
script.onload = script.onreadystatechange = null;
head.removeChild(script);
callback();
}
});
script.src = jqueryUrl;
head.appendChild(script);
}
else {
callback();
}
})(arguments[0], arguments[arguments.length - 1]);
Before/after result:
Found working example in python (without using jquery_load_helper.js) – https://gist.github.com/rcorreia/2362544#gistcomment-2708388
Credits: Kelanmomo
As alecxe mentioned: download drag_and_drop_helper.js
# coding = utf-8
from selenium import webdriver
import os
from time import sleep
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('http://the-internet.herokuapp.com/drag_and_drop')
with open(os.path.abspath('drag_and_drop_helper.js'), 'r') as js_file:
line = js_file.readline()
script = ''
while line:
script += line
line = js_file.readline()
driver.execute_script(script + "$('#column-a').simulateDragDrop({ dropTarget: '#column-b'});")
sleep(2)
driver.quit()