Dhanush jha
Dhanush jha

Reputation: 27

Drag and Drop in selenium java

I try to drag and drop the content into search-textbox in selenium,but it perform drag operation but it not drop it into search-textbox.so my question is how to drop into textbox.

driver.get("http://stackoverflow.com/questions/42159265/drag-and-drop-content-into-textbox-by-using-selenium");                 
WebElement from = driver.findElement(By.xpath("//*[@id='qinfo']/tbody/tr[1]/td[2]/p/b"));
Actions builder = new Actions(driver);
        builder.doubleClick(from).perform();
        Thread.sleep(1000);

WebElement to = driver.findElement(By.name("q"));
Action dragAndDrop = builder.clickAndHold(from).moveToElement(to).release(to).build();
        dragAndDrop.perform();

Upvotes: 0

Views: 4499

Answers (4)

Sasha Kolsky
Sasha Kolsky

Reputation: 463

Apparently this applies in some cases (when HTML5 draggable attribute is used). Here is what I found: https://elementalselenium.com/tips/39-drag-and-drop

Here is my solution, I modified the javascript file a bit, so it will make use of executeScript optional args and not use string concatenation.

var source = arguments[0];
var target = arguments[1];
(function( $ ) {
    $.fn.simulateDragDrop = function(options) {
        return this.each(function() {
            new $.simulateDragDrop(this, options);
        });
    };
    $.simulateDragDrop = function(elem, options) {
        this.options = options;
        this.simulateEvent(elem, options);
    };
    $.extend($.simulateDragDrop.prototype, {
        simulateEvent: function(elem, options) {
            /*Simulating drag start*/
            var type = 'dragstart';
            var event = this.createEvent(type);
            this.dispatchEvent(elem, type, event);

            /*Simulating drop*/
            type = 'drop';
            var dropEvent = this.createEvent(type, {});
            dropEvent.dataTransfer = event.dataTransfer;
            this.dispatchEvent($(options.dropTarget)[0], type, dropEvent);

            /*Simulating drag end*/
            type = 'dragend';
            var dragEndEvent = this.createEvent(type, {});
            dragEndEvent.dataTransfer = event.dataTransfer;
            this.dispatchEvent(elem, type, dragEndEvent);
        },
        createEvent: function(type) {
            var event = document.createEvent("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;
        },
        dispatchEvent: function(elem, type, event) {
            if(elem.dispatchEvent) {
                elem.dispatchEvent(event);
            }else if( elem.fireEvent ) {
                elem.fireEvent("on"+type, event);
            }
        }
    });
})(jQuery);
$(source).simulateDragDrop({ dropTarget: target});

With this, you can simple call it with parameters now:

Excerpt from Java test method:

JavascriptExecutor js = (JavascriptExecutor) getDriver();
String script = Utils.readFileContents("/dragAndDrop.js");

// First Drag & Drop
js. executeScript(script, dndPage.getColumnA(), dndPage.getColumnB());
assertThat(dndPage.getColumnAHeaderText()).isEqualTo("B");
assertThat(dndPage.getColumnBHeaderText()).isEqualTo("A");

Hope this helps someone.

Upvotes: 0

Rester Test
Rester Test

Reputation: 227

So this thing made me crazy for a couple of days but I have found an answer.

Made a video about it

https://www.youtube.com/watch?v=hOprGzKBD9I&feature=youtu.be

To explain also in words/code what needs to be done

1 - You need to import an external JS file resources/drag_and_drop.js 2 - After you need to run make a function that will execute JS

Below is mine -

  • This method implement the drag and drop action use selenium webdriver

  • The strings need to be CSS Locations

      public void dragIT (String Fromlocator, String ToLocator) 
    
    
    
      String filePath = "resources/drag_and_drop.js";
      StringBuffer buffer = new StringBuffer();
    
      String line;
      BufferedReader br = new BufferedReader(new FileReader(filePath));
      while((line = br.readLine())!=null)
          buffer.append(line);
    
      String javaScript = buffer.toString();
      String commandToExecute =  "$('"+Fromlocator+"').simulateDragDrop({ dropTarget: '"+ToLocator+"'});";
    
      javaScript = javaScript + commandToExecute;
      ((JavascriptExecutor)driver).executeScript(javaScript)   }
    

Upvotes: 1

mancocapac
mancocapac

Reputation: 882

First WebDriver/Selenium DragAndDrop does not appear to work anymore, at best it goes between working and not working depending on release of drivers, browsers and selenium. I do not find that any of the java workarounds actually work.

clickAndHold() moveToElement() release()  // solutions don't work

I put together a working Java example after viewing the below mentioned sites. My solution is using rcorreia's javascript

Elemental Selenium Drag N Drop - example app for testing Drag N Drop rcorreia/drag_and_drop_helper.js - rcorreia's javascript helper code

RomanIsko/elemental-selenium-tips - a csharp implementation

I figured out how to integrate the javascript file by looking at romanisko csharp code.

JSDriver.ExecuteScript(dnd_javascript + "$('#column-a').simulateDragDrop({ dropTarget: '#column-b'});");

From the above I came up with the following Java Solution:

DragAndDropJsHelper.java

import java.io.BufferedReader;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Collectors;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class DragAndDropJsHelper {
    Logger log = LogManager.getLogger(DragAndDropJsHelper.class.getName());

    String dragndrop_js = null;

    public DragAndDropJsHelper(String jsFile) throws IOException {
        // the javascript file must be read into a single string no line breaks
        try (BufferedReader br = Files.newBufferedReader(Paths.get(getURIFromURL(jsFile)))) {
            dragndrop_js = br
                    .lines()
                    .collect(Collectors.joining(" "));
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }

    // helper method, I'm using maven my js file is in src/test/resources
    @SuppressWarnings("finally")
    private URI getURIFromURL(String fileName) {
        URI uri = null;
        try {
            URL url = this.getClass().getClassLoader().getResource(fileName);
            uri = url.toURI();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        } finally {
            return uri;
        }
    }

    /**
     * Solution from elemental-selenium-tips
     * https://github.com/tourdedave/elemental-selenium-tips/blob/master/39-drag-and-drop/csharp/DragAndDrop.cs
     * JSDriver.ExecuteScript(dnd_javascript + "$('#column-a').simulateDragDrop({
     * dropTarget: '#column-b'});");
     * 
     * NOTE: Seems fragile, not sure if this works for XPATH or other src/dst type strings
     * TODO: would be good if it worked with WebElement, or BY
     * 
     * @param driver
     * @param src
     *            - css string for source element
     * @param dst
     *            - css string for destination element
     */
    public void dragDrop(WebDriver driver, String src, String dst) {
        String js = String.format("$('%s').simulateDragDrop({ dropTarget: '%s'});",src,dst);
        JavascriptExecutor jse = (JavascriptExecutor) driver;
        jse.executeScript(dragndrop_js + js);
    }

}

Part of my DragAndDropTest.java

@Test
public void dragAtoBTest() {
    try {
        WebElement weA = driver.findElement(DragNDropPage.COLUMN_A);
        WebElement weB = driver.findElement(DragNDropPage.COLUMN_B);
        DragAndDropJsHelper ddh = new DragAndDropJsHelper("drag_and_drop_helper.js");

        ddh.dragDrop(driver, "#column-a", "#column-b");

        log.info("wait for opacity to change 1, indicating move complete");
        wait.until(ExpectedConditions.attributeToBe(weA, "opacity", "1"));
        assertThat(weA.findElement(page.columnHeader).getText(), containsString("B"));

    } catch (Exception e) {
        e.printStackTrace();
        log.error(e);
        Assert.fail("FAILED validLoginTest");
    }
}

NOTE: Using the drag_and_drop.js requires the src and dst to be css selector strings, I don't know if xpath would work. It would be nicer if it would handle WebElement and/or BY for input parameters. Unfortunately, my javascript is not deep enough to make that modification.

see also:

Selenium Actions drag and drop not working on chrome browser

Drag and drop support for an object via Gwen DSL

Upvotes: 2

Joy
Joy

Reputation: 1

You can try:

Actions dragAndDrop= new Actions(driver);
dragAndDrop.clickAndHold(DragFrom).moveToElement(DragTo).release().build().perform();

Upvotes: 0

Related Questions