How to simulate HTML5 Drag and Drop in Selenium Webdriver?

21,353

Solution 1

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:

Solution 2

Java version is in below commit

https://github.com/vikramvi/Selenium-Java/commit/a1354ca5854315fded8fc80ba24a4717927d08c7

Share:
21,353
Mahsa Mortazavi
Author by

Mahsa Mortazavi

Updated on August 13, 2020

Comments

  • Mahsa Mortazavi
    Mahsa Mortazavi almost 4 years

    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.

  • Duduman Bogdan Vlad
    Duduman Bogdan Vlad almost 9 years
    Your example is still working. I have managed to translate it and use it in C#. Thank you for your help!
  • Druska
    Druska over 8 years
    I converted this helper to native JS, removing the need for injecting jQuery: gist.github.com/druska/624501b7209a74040175
  • rahoolm
    rahoolm over 8 years
    @DudumanBogdanVlad could you please share the C# version or any link?
  • Duduman Bogdan Vlad
    Duduman Bogdan Vlad over 8 years
    @rahoolm I helped Raluca with this. She created a blog post. Here is the link ralucasuditu-softwaretesting.blogspot.ro/2015/08/…
  • rahoolm
    rahoolm over 8 years
    Thanks @DudumanBogdanVlad, I am looking into it. But in my case I want to drag and drop to XY. Say drag element one in x direction by 20 px. Please suggest.
  • Duduman Bogdan Vlad
    Duduman Bogdan Vlad over 8 years
    Why don't you add another div at X/Y with a specific ID and drop your element in your new div? It's pretty the same thing.
  • Steeven_b
    Steeven_b over 5 years
    Sorry for the late question, but I'm struggling here, when I copy the js snippet, it tells me that the last line (argument[0] etc) is out of a function, which is actually true so it does not work. I don't know much about JavaScript and can't understand what is the point of this last line, and how to fix it. Thanks for help !