SeleniumHQ/selenium

Unable to perform drag and drop with Selenium (python)

Closed this issue ยท 8 comments

๐Ÿ› Bug Report

Hi there,

For test automation, I can't perform drag and drop or click and hold actions with Selenium in python on a private web app. No drag actions seems to be performed at all. I can't share the private app but I reproduce my bug on the following demo website :
http://the-internet.herokuapp.com/drag_and_drop

To Reproduce

Below is my basic piece of code for drag and drop / click and hold

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get('http://the-internet.herokuapp.com/drag_and_drop')
dragged = driver.find_element(By.ID, "column-a")
dropped = driver.find_element(By.ID, "column-b")

#Drag and drop

actions = ActionChains(driver)
actions.drag_and_drop(dragged, dropped).perform() 
#column A is selected but not dragged

#Click and hold
actions = ActionChains(driver)
actions.move_to_element(dragged).click_and_hold().move_to_element(dropped).release().perform()
#Same result : column a is selected but not dragged

Detailed steps to reproduce the behavior: Juste reuse the code with the provided demo website.

Expected behavior

Block A and Block B should be switched.

Test script or set of commands reproducing this issue

Please, see the code above

Environment

OS:
Browser:
Browser version:
Browser Driver version:
Language Bindings version:
Selenium :

Thanks for your help :)

Dupe of #7782 ?

Looking at this, all browsers don't seem to do the right thing yet all are passing the webdriver test
https://github.com/web-platform-tests/wpt/blob/master/webdriver/tests/perform_actions/pointer.py#L113-L143

It appears that we have a drag and drop test that is working properly... https://github.com/SeleniumHQ/selenium/blob/master/py/test/selenium/webdriver/common/interactions_tests.py so need to see what is different between this scenario and what we have in our tests

You can execute this script as the fast fix at the moment (works well for me on both Chrome and Firefox).
https://gist.github.com/druska/624501b7209a74040175#file-native_js_drag_and_drop_helper-js
What I did is just added simulateDragDrop(arguments[0], arguments[1]):

function simulateDragDrop(sourceNode, destinationNode) {
    var EVENT_TYPES = {
        DRAG_END: 'dragend',
        DRAG_START: 'dragstart',
        DROP: 'drop'
    }

    function createCustomEvent(type) {
        var event = new CustomEvent("CustomEvent")
        event.initCustomEvent(type, true, true, null)
        event.dataTransfer = {
            data: {
            },
            setData: function(type, val) {
                this.data[type] = val
            },
            getData: function(type) {
                return this.data[type]
            }
        }
        return event
    }

    function dispatchEvent(node, type, event) {
        if (node.dispatchEvent) {
            return node.dispatchEvent(event)
        }
        if (node.fireEvent) {
            return node.fireEvent("on" + type, event)
        }
    }

    var event = createCustomEvent(EVENT_TYPES.DRAG_START)
    dispatchEvent(sourceNode, EVENT_TYPES.DRAG_START, event)

    var dropEvent = createCustomEvent(EVENT_TYPES.DROP)
    dropEvent.dataTransfer = event.dataTransfer
    dispatchEvent(destinationNode, EVENT_TYPES.DROP, dropEvent)

    var dragEndEvent = createCustomEvent(EVENT_TYPES.DRAG_END)
    dragEndEvent.dataTransfer = event.dataTransfer
    dispatchEvent(sourceNode, EVENT_TYPES.DRAG_END, dragEndEvent)
}

simulateDragDrop(arguments[0], arguments[1]);

I saved this one as drag_and_drop.js file in scripts folder of my project's directory.
Then I used next code in my tests:

DRAGGABLE_SELECTOR = (By.CSS_SELECTOR, "div[draggable]")
DROPPABLE_SELECTOR = (By.CSS_SELECTOR, ".ReactCollapse--content > div > div > div > div > div > div[id]")
draggable = self.app.wd.find_element(*DRAGGABLE_SELECTOR)
droppable = self.app.wd.find_element(*DROPPABLE_SELECTOR)
f = open("scripts/drag_and_drop.js",  "r")
javascript = f.read()
f.close()
wd.execute_script(javascript, draggable, droppable)

One more thing: this script accepts elements found by CSS selectors only (because it's a JQuery script)!

A new test was added for the spec that highlights this issue. Hopefully Google and Mozilla will schedule this to be fixed

Closing as this issue as it needs to be fix in each of the drivers.

@AutomatedTester Hi, may I ask there's any update? Is this issued comfirmed an issued of the drivers not selenium (thus we have to wait for fixed from google and mozilla)?

You can try to use a workaround I've mentioned above at the moment.
I've also wrapped it up as a Python package, so it would be easy to use. You can install the package with pip install seletools
An example of usage is here.