17

I am trying to drag an element into another element using Selenium WebDriver but it's not working. I tried all the solutions which I can find on the internet but none of the solutions seems to be working for me.

WebElement sourceelement = driver.findElement(By.cssSelector("XXX"));
WebElement destelement = driver.findElement(By.cssSelector("YYY"));

Code1:-

Actions builder = new Actions( _controls.getDriver());
builder.dragAndDrop(sourceelement, destelement);

Code2:-

Actions builder = new Actions(_controls.getDriver());
Action dragAndDrop =
builder.clickAndHold(sourceelement).moveToElement(destelement).release(destelement).build();
Thread.sleep(2000);
dragAndDrop.perform()

Code3:-

Point coordinates1 = sourceelement.getLocation();
Point coordinates2 = destelement.getLocation();  
Robot robot = new Robot();           
robot.mouseMove(coordinates1.getX(), coordinates1.getY());
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseMove(coordinates2.getX(), coordinates2.getY());
robot.mouseRelease(InputEvent.BUTTON1_MASK);
Thread.sleep(2000);

Code4:-

final String java_script =
"var src=arguments[0],tgt=arguments[1];var dataTransfer={dropEffe" +
                "ct:'',effectAllowed:'all',files:[],items:{},types:[],setData:fun" +
                "ction(format,data){this.items[format]=data;this.types.append(for" +
                "mat);},getData:function(format){return this.items[format];},clea" +
                "rData:function(format){}};var emit=function(event,target){var ev" +
                "t=document.createEvent('Event');evt.initEvent(event,true,false);" +
                "evt.dataTransfer=dataTransfer;target.dispatchEvent(evt);};emit('" +
                "dragstart',src);emit('dragenter',tgt);emit('dragover',tgt);emit(" +
                "'drop',tgt);emit('dragend',src);";
        
        ((JavascriptExecutor)_controls.getDriver()).executeScript(java_script, sourceelement, destelement);
        Thread.sleep(2000);

None of the above codes is working for me. All the above runs without any error but drag and drop is not happening in the application. Does anyone have any other solution? Thanks.

Norayr Sargsyan
  • 1,737
  • 1
  • 12
  • 26
Naseem
  • 911
  • 5
  • 18
  • 48
  • 1
    Are you trying this for HTML5? – Grasshopper Sep 13 '16 at 17:51
  • It starts with in View source page. So yes it is html5 page. – Naseem Sep 14 '16 at 05:20
  • 2
    Have a look at this - http://stackoverflow.com/questions/29381233/how-to-simulate-html5-drag-and-drop-in-selenium-webdriver. Somebody has even created a github with corresponding java code. – Grasshopper Sep 14 '16 at 06:58
  • Yeah, I saw the same question earlier as well and tried with the js file mentioned in the github site but it didn't work in my case :( – Naseem Sep 14 '16 at 09:37
  • We need to know the HTML, however if it's a standard HTML5 page it won't work in selenium without some additional work to trigger specific JS callbacks – Ardesco Mar 19 '19 at 10:29

13 Answers13

13

Can you try Java Script Executor for this

JavascriptExecutor js = (JavascriptExecutor)driver
js.executeScript("function createEvent(typeOfEvent) {\n" + "var event =document.createEvent(\"CustomEvent\");\n"
                    + "event.initCustomEvent(typeOfEvent,true, true, null);\n" + "event.dataTransfer = {\n" + "data: {},\n"
                    + "setData: function (key, value) {\n" + "this.data[key] = value;\n" + "},\n"
                    + "getData: function (key) {\n" + "return this.data[key];\n" + "}\n" + "};\n" + "return event;\n"
                    + "}\n" + "\n" + "function dispatchEvent(element, event,transferData) {\n"
                    + "if (transferData !== undefined) {\n" + "event.dataTransfer = transferData;\n" + "}\n"
                    + "if (element.dispatchEvent) {\n" + "element.dispatchEvent(event);\n"
                    + "} else if (element.fireEvent) {\n" + "element.fireEvent(\"on\" + event.type, event);\n" + "}\n"
                    + "}\n" + "\n" + "function simulateHTML5DragAndDrop(element, destination) {\n"
                    + "var dragStartEvent =createEvent('dragstart');\n" + "dispatchEvent(element, dragStartEvent);\n"
                    + "var dropEvent = createEvent('drop');\n"
                    + "dispatchEvent(destination, dropEvent,dragStartEvent.dataTransfer);\n"
                    + "var dragEndEvent = createEvent('dragend');\n"
                    + "dispatchEvent(element, dragEndEvent,dropEvent.dataTransfer);\n" + "}\n" + "\n"
                    + "var source = arguments[0];\n" + "var destination = arguments[1];\n"
                    + "simulateHTML5DragAndDrop(source,destination);", ElementFrom, ElementTo);

Refrence: https://www.linkedin.com/pulse/javascriptexecutor-selenium-gaurav-gupta/

It works for me on web application which are angular based.

SiKing
  • 10,003
  • 10
  • 39
  • 90
Gaurav_QA
  • 131
  • 1
  • 7
6

If the known cases do not work, you can try this solution

        WebElement a = driver.findElement(By.cssSelector("your_selector"));
        WebElement b = driver.findElement(By.cssSelector("your_selector"));

        int x = b.getLocation().x;
        int y = b.getLocation().y;

        Actions actions = new Actions(driver);
        actions.moveToElement(a)
                .pause(Duration.ofSeconds(1))
                .clickAndHold(a)
                .pause(Duration.ofSeconds(1))
                .moveByOffset(x, y)
                .moveToElement(b)
                .moveByOffset(x,y)
                .pause(Duration.ofSeconds(1))
                .release().build().perform();

If you want to drag the element in a different area(not to drag the element to another one) you can use this scenario for that:

WebElement source = driver.findElement(By.cssSelector("your_selector"));

Actions actions = new Actions(driver);
actions.moveToElement(source)
            .pause(Duration.ofSeconds(1))
            .clickAndHold(source)
            .pause(Duration.ofSeconds(1))
            .moveByOffset(0,50) //change the x, y values to be applicable for your cases
            .moveByOffset(0,50)
            .pause(Duration.ofSeconds(1))
            .release().build().perform();
}
Norayr Sargsyan
  • 1,737
  • 1
  • 12
  • 26
  • 2
    Tried so many solutions but this worked perfectly in my react application. Thanks – Lakshmipathi G Oct 15 '20 at 11:19
  • @Norayr Sargsyan It does not work for me at all! the 'from' is not moving to 'to', but move to my mouse's position where ever i put in my desktop screen (and therefore in browser screen). And who can explain the use of moveByOffset(x, y) TWICE in the code? It makes no sense. Also x and y is the location of 'to', it's not the offset between 'from' and 'to' either. – user1559625 Apr 08 '23 at 08:20
2

I have also faced the same issue. Please find below custom java-script function for drag & drop.

1) Create DragDrop.js file and paste below code in it

    function customEvent(typeOfEvent) {
    var event = document.createEvent("CustomEvent");
    event.initCustomEvent(typeOfEvent, true, true, null);
    event.dataTransfer = {
        data: {},
        setData: function (key, value) {
            this.data[key] = value;
        },
        getData: function (key) {
            return this.data[key];
        }
    };
    return event;
}
function dispatchEvent(element, event, transferData) {
    if (transferData !== undefined) {
        event.dataTransfer = transferData;
    }
    if (element.dispatchEvent) {
        element.dispatchEvent(event);
    } else if (element.fireEvent) {
        element.fireEvent("on" + event.type, event);
    }
}
function executeDrageAndDrop(element, target) {
    var dragStartEvent = customEvent('dragstart');
    dispatchEvent(element, dragStartEvent);
    var dropEvent = customEvent('drop');
    dispatchEvent(target, dropEvent, dragStartEvent.dataTransfer);
    var dragEndEvent = customEvent('dragend');
    dispatchEvent(element, dragEndEvent, dropEvent.dataTransfer);
}

2) Using below code we can call above custom function(Below is C# code)

string script = System.IO.File.ReadAllText(@"{filepath of DragDrop.js file}");
script = script + "executeDrageAndDrop(arguments[0], arguments[1])";
IJavaScriptExecutor executor = (IJavaScriptExecutor)driver;

IWebElement source = driver.findElement(By......);
IWebElement target = driver.findElement(By......);

executor.ExecuteScript(script, source, target);
atul parate
  • 760
  • 5
  • 5
1

I would suggest you try the following solution:

WebElement sourceelement  = driver.findElement(By.cssSelector("XXX"));
Locatable element = (Locatable)sourceelement ;
Point p= element.getCoordinates().inViewPort();
int sourceX=p.getX();
int sourceY=p.getY();

WebElement destelement = driver.findElement(By.cssSelector("YYY"));
Locatable elementTarget = (Locatable)destelement;
Point Target= elementTarget.getCoordinates().inViewPort();
int targetX=Target.getX();
int targetY=Target.getY();

You may then use Robot to drag and drop the element

BountyHunter
  • 1,413
  • 21
  • 35
1

Please refer this Java Script based solution with sample web application given By Dmitrii Bormotov in Medium. It's in python (With little tweak you can use it in java)

I tried using plain selenium Actions DragAndDrop method, with different combinations and it was not at all working for me.

Anver Sadhat
  • 3,074
  • 1
  • 25
  • 26
0

In your code 1: Not calling perform() method, it should be

 Actions builder = new Actions( _controls.getDriver());

 builder.dragAndDrop(sourceelement, destelement).perform();

In your code 2: I don't think you need to call release()

Please search for similar questions before posting.

Norayr Sargsyan
  • 1,737
  • 1
  • 12
  • 26
FayazMd
  • 386
  • 2
  • 22
  • After making the required changes in Code 1 and Code 2, it is still not working. Also I did researched a lot regarding drag and drop functionality and that's how I was able to find so many codes. When none of them worked then only I posted my question. Thanks :) – Naseem Sep 12 '16 at 03:38
0

You might want to check if webelement is enabled or displayed prior performing desired action over it. You may give it a try with below code

public void dragAndDrop(WebElement sourceElement, WebElement destinationElement) {
    try {
        if (sourceElement.isDisplayed() && destinationElement.isDisplayed()) {
            Actions action = new Actions(driver);
            action.dragAndDrop(sourceElement, destinationElement).build().perform();
        } else {
            System.out.println("Element was not displayed to drag");
        }
    } catch (StaleElementReferenceException e) {
        System.out.println("Element with " + sourceElement + "or" + destinationElement + "is not attached to the page document "
                + e.getStackTrace());
    } catch (NoSuchElementException e) {
        System.out.println("Element " + sourceElement + "or" + destinationElement + " was not found in DOM "+ e.getStackTrace());
    } catch (Exception e) {
        System.out.println("Error occurred while performing drag and drop operation "+ e.getStackTrace());
    }
}


public void dragAndDrop(WebElement sourceElement, WebElement destinationElement)
    {
        (new Actions(driver)).dragAndDrop(sourceElement, destinationElement).perform();
    }
}
nandesh kalyankar
  • 302
  • 1
  • 5
  • 23
  • Thanks Nandesh but the elements are enabled. Tried with the above code and it runs without any error but no drag and drop – Naseem Sep 14 '16 at 14:12
  • @Naseem would you mind sharing version of Selenium webdriver, page source, browser? Assuming that webelement your interacting with supports drag and drop actions. – nandesh kalyankar Sep 14 '16 at 16:53
  • I am using Seleniun version as 2.53.0 and browser as IE. Unfortunately won't be able to share the page source here . – Naseem Sep 15 '16 at 08:36
0

I would suggest you to use Touch Action to perform drag and drop.

Point coordinates1 = sourceelement.getLocation();
Point coordinates2 = destelement.getLocation();  
TouchActions builder = new TouchActions(driver);
builder.longPress(coordinates1)
       .move(coordinates2).release(coordinates2).perform();
badal16
  • 499
  • 1
  • 5
  • 18
0

I have face similar problem way back, I have used dragAndDropBy to move slider but it didn't worked for me but later I found help and below the snippet for my working code:

public static void slider(){
x=10;
WebElement slider = driver.findElement(By.id("slider"));
int width=slider.getSize().getWidth();
Actions move = new Actions(driver);
move.moveToElement(slider, ((width*x)/100), 0).click();
move.build().perform();
System.out.println("Slider moved");
}

You can refer the link here

Karim Narsindani
  • 434
  • 3
  • 14
  • 38
0

You may try executing the following javascript to perform drag and drop

WebDriver _driver;
WebElement _sourceElement = _driver.findElement(<source>);
WebElement _targetElement = _driver.findElement(<source>);
JavascriptExecutor _js = (JavascriptExecutor) _driver;
_js.executeScript("$(arguments[0]).simulate('drag-n-drop',{dragTarget:arguments[1],interpolation:{stepWidth:100,stepDelay:50}});", _sourceElement, _targetElement);

Please find more details here.

It works perfectly for all the browsers and devices.

Kenil Fadia
  • 234
  • 3
  • 7
0

This is working for me :

Actions act = new Actions(driver);
act.moveToElement(element, (elementWidth / 2), elementHeight / 2).clickAndHold().build().perform();
act.moveToElement(dest, (destWidth / 2) , (destHeight / 2)).release().build().perform();

There are sometimes bugs in some version of selenium. Make sure you use the lastest one and play around with clicking. Would be easier of you can send a link of what you are trying to drag/drop

mosaad
  • 2,276
  • 5
  • 27
  • 49
0

I've tried a bunch of workarounds, this one seems to work for me using macOS and chromedriver

public void dragAndDrop(WebElement source, WebElement target) throws AWTException {
    new Actions(driver).dragAndDrop(source, target).release().build().perform();
    Robot robot = new Robot();
    robot.keyPress(KeyEvent.VK_ESCAPE);
    robot.keyRelease(KeyEvent.VK_ESCAPE);
}
-1
Actions act = new Actions(driver);
WebElement source = driver.findElement(By.id("XXX"));
WebElement destination = driver.findElement(By.id("XXX"));

Action dragAndDrop =act.moveToElement(source,destination).build().perform();
JJJ
  • 32,902
  • 20
  • 89
  • 102
gautam
  • 1