Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to simulate HTML5 Drag and Drop in Selenium Webdriver?

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.

like image 852
Mahsa Mortazavi Avatar asked Apr 01 '15 01:04

Mahsa Mortazavi


People also ask

How do you simulate an action of dragAndDrop action with a selenium driver?

Click And Hold Action: dragAndDrop() method first performs click-and-hold at the location of the source element. Move Mouse Action: Then source element gets moved to the location of the target element. Button Release Action: Finally, it releases the mouse.

How do you dragAndDrop elements in selenium Python?

drag_and_drop(source, target) This method accepts two arguments: source & target. As the name goes, drag and drop ActionChains involves first locating the “source” element, then dragging it to the target location and dropping it. To select a source and target element, you may use XPath or CSS Selectors.


1 Answers

Yes, HTML5 "drag&drop" is not currently supported by Selenium:

  • Issue 3604: HTML5 Drag and Drop with Selenium Webdriver

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:

like image 108
alecxe Avatar answered Sep 21 '22 14:09

alecxe