0

I've been trying to practice with drag and drop tests on following page https://www.seleniumeasy.com/test/drag-and-drop-demo.html

Here is the code of PageObject class with only one method, which drags and drops element of the list to the dropzone:

public class DragAndDropDemoPage extends Page {

    public DragAndDropDemoPage(WebDriver driver) {
        super(driver);
        navigateTo();
    }

    @Override
    public void navigateTo() {
        driver.get(Urls.DRAG_AND_DROP_PAGE_URL);
    }

    public void dragAndDropElementWithIndex(int index) {
        List<WebElement> elements = findElementsByCss("span[draggable=true]");
        new Actions(driver).dragAndDrop(elements.get(index), findElementByCss("div#mydropzone")).build().perform();
    }
}

after performing of such an action WebDriver eventually navigates to the Google Search page. And search request contains the name of the element I've been dragging.

What's wrong with this case? How did WebDriver managed to move to another page?

PS: Super class Page is:

public abstract class Page {
    WebDriver driver;

    public Page(WebDriver driver) {
        this.driver = driver;
    }

    public abstract void navigateTo();

    protected WebElement findElementByCss(String cssSelector) {
        return driver.findElement(By.cssSelector(cssSelector));
    }

    protected List<WebElement> findElementsByCss(String cssSelector) {
        return driver.findElements(By.cssSelector(cssSelector));
    }

    protected WebElement findByXpath(String xpath) {
        return driver.findElement(By.xpath(xpath));
    }
}
JeffC
  • 22,180
  • 5
  • 32
  • 55
SanchelliosProg
  • 2,091
  • 3
  • 20
  • 32

2 Answers2

0

As per the HTML you have shared the WebElement which you want to DragAndDrop() contains the attribute draggable=true


draggable

draggable is a attribute that indicates whether an element can be dragged, either with native browser behavior or the HTML Drag and Drop API. draggable can have the following values:

  • true: the element can be dragged.
  • false: the element cannot be dragged.

Note: This attribute is enumerated and not Boolean. A value of true or false is mandatory, and shorthand like <img draggable> is forbidden. The correct usage is <img draggable="false">.

If this attribute is not set, its default value is auto which means drag behavior is the default browser behavior: only text selections, images, and links can be dragged. For other elements, the event ondragstart must be set for drag and drop to work.


Native HTML5 Drag and Drop

Eric Bidelman in the article Native HTML5 Drag and Drop mentioned, making an object draggable is simple as you only need to set the draggable=true attribute on the element you want to make moveable. As an example:

<div id="cols">
  <div class="col" draggable="true"><header>X</header></div>
  <div class="col" draggable="true"><header>Y</header></div>
  <div class="col" draggable="true"><header>Z</header></div>
</div>

To enable other types of content to be draggable you can leverage the HTML5 DnD APIs. However, using CSS3 you can spruce up the markup to look like columns and adding cursor gives users a visual indicator that something is moveable but most browsers will create a ghost image of the content being dragged and draggable won't do anything. Some browser, FF in particular will require that some data be sent in the drag operation.

Further, Remy Sharp in the article Dragging Anything mentioned:

The HTML 5 spec says it should be as simple as adding the following attributes to the markup of the elements in question:

draggable="true"

However, this doesn’t work completely for Safari or Firefox. For Safari you need to add the following style to the element:

[draggable=true] {
  -khtml-user-drag: element;
}

This will start working in Safari, and as you drag it will set a default, empty value with the dataTransfer object. However, Firefox won’t allow you to drag the element unless you manually set some data to go with it.


Solution

To solve this, we need a dragstart event handler, and we’ll give it some data to be dragged around with:

var dragItems = document.querySelectorAll('[draggable=true]');

for (var i = 0; i < dragItems.length; i++) {
  addEvent(dragItems[i], 'dragstart', function (event) {
    // store the ID of the element, and collect it on the drop later on
    event.dataTransfer.setData('Text', this.id);
  });
}

References

A couple of references:

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Thank you for your answer! To be honest, I didn't get how to use event handler in Java code? Should I implement JS executor just to run it? – SanchelliosProg Jan 05 '20 at 22:28
0

Problem: source element is dropping to the mouse position and not to target element. Drag and drop works in other website, you can check here.
When you run script probably your mouse position is somewhere near tab bar of the browser, that's why google opens (same as you put drag any text to the browser bar).

You can try @DebanjanB solution or you can use Robot.

Sers
  • 12,047
  • 2
  • 12
  • 31