Looking at webdriverjs I can see there's a way to do drag and drop such as this:
* <p>Example:<pre><code>
* new webdriver.ActionSequence(driver).
* keyDown(webdriver.Key.SHIFT).
* click(element1).
* click(element2).
* dragAndDrop(element3, element4).
* keyUp(webdriver.Key.SHIFT).
* perform();
* </pre></code>
How to use it with protractor?
You should be able to do the exact same thing, but with protractor instead of webdriver and ptor (or whatever you call your protractor instance) instead of driver.
I tested with it in debug mode but the element doesn't seem to be dragged and dropped as desired....
I was writing another test using dragAndDrop and it seems to work
ptor.actions().dragAndDrop(
ptor.findElement(protractor.By.xpath('//td[contains(concat(" ", @class, " "), "fc-day") and @data-date="' + currentTimePlus1Day.format('YYYY-MM-DD') + '"]')),
ptor.findElement(protractor.By.xpath('//td[contains(concat(" ", @class, " "), "fc-day") and @data-date="' + currentTimePlus3Day.format('YYYY-MM-DD') + '"]'))
).perform();
the code above is to drag the mouse from 1 day to another in fullcalendar and it works fine.
However, my previous test to drag an event into a different day using the same method doesn't seems to work. The only difference between the two is on the other test, I was selecting the event for the first param for dragAndDrop. Does this scenario ring any bell to you?
Along the way I was also researching on how to actually debug the written test in protractor. The method of putting ptor.debugger() like in the documentation just add window.clientSideScripts variable which contains some "protractor-specific" selector functions into the test page which isn't very helpful. Is there a way I could findElement in xpath, do dragAndDrop on them like the above code in the test page instead? Thanks a lot.
I am trying to do DragAndDrop for slider bar , when i launch protractor , the following scripts get executed without any errors or warning but i don't see the slider bar moving.
ptor.get('URL');
var slider = ptor.findElement(protractor.By.xpath(".//*[@id='leftcolumn']/div[2]/div/a[1]")); //slider bar object
ptor.actions().dragAndDrop(slider,{x:1000,y:0}).perform();
ptor.sleep(10000);
What does your template look like? I've added a test which successfully uses drag and drop in this commit: fb46ec9bcd568510248831f11d43d0e2398cc606
Closing as obsolete and solved, please open a new issue if there is still a problem.
Hi,
If anyone gets a cannot find toWireValue method of [Object] error you need to pass a promise which gets the actual element.
e.g.
var handle = $(".ui-handler")
ptor.actions().dragAndDrop(handle.find(), {x:100, y:0}).perform()
the .find() part is important here, took me a while to figure this out
Hi ,
Very new to protractor , and i need to do drag and drop testing for a slider bar.
i believe,
ptor.actions().dragAndDrop(slider.find(), {x:100, y:0}).perform() should do the work .
But can some one please tell me where to look for value of x and y ;
Here's the code snippet

@juliemr Do you have any suggestion for this ?
@snehacharkha, check the implementation; x and y are the offset in pixels (or you can use another WebElement).
/**
* Convenience function for performing a "drag and drop" manuever. The target
* element may be moved to the location of another element, or by an offset (in
* pixels).
* @param {!webdriver.WebElement} element The element to drag.
* @param {(!webdriver.WebElement|{x: number, y: number})} location The
* location to drag to, either as another WebElement or an offset in pixels.
* @return {!webdriver.ActionSequence} A self reference.
*/
webdriver.ActionSequence.prototype.dragAndDrop = function(element, location) {
return this.mouseDown(element).mouseMove(location).mouseUp();
};
ptor.actions().dragAndDrop(handle.find(), {x:100, y:0}).perform() works for me
However when i try to parameterize the x and y values e.g. {x:x, y:y} where x and y are variable no drag and drop effect seen :-( Any ideas?
ptor.actions().dragAndDrop(handle.find(), {x:100, y:0}).perform() DO NOT WORK FOR ME! :(
It gives me the error:
TypeError: undefined is not a function
@SwatiKhandelwal you should use browser global object instead:
browser.actions().dragAndDrop(handle.find(), {x:100, y:0}).perform()
I face the same issue. The following piece of code works on firefox but NOT on chrome.
browser.driver.actions()
.mouseDown(dragElement)
.mouseMove(dropElement)
.mouseUp(dropElement)
.perform()
Any help would be greatly apprerciated.
After a few days I have finally managed to get a drag and drop working but I didn't do this with just protractor.
Step 1
Save this code into a file in your app.
https://gist.github.com/druska/624501b7209a74040175
Step 2
Using the node require() require it into your file I did this via
var dragNDrop = require('../../drag.js');
Step 3
Call the function provided by the drag.js file and insert the elements that you want to drag to and from.
var e1 = element(by.xpath('//*[@id="e1"]/div[1]/div/div/ul/li[1]/button'));
var e2 = element(by.xpath('//*[@id="e2"]/div[2]/div/div/div/div/div/div/div/ul'));
browser.executeScript(dragNDrop, e1.getWebElement(), e2.getWebElement());
browser.sleep(2000) // let the animation do its thing
Hope this helps with this ticket its been a right pain in my neck the past few days so fingers crossed this can help someone else out :+1:
@EvanBurbidge Thank you so much for you method. I tried but got the error: java.util.HashMap cannot be cast to java.lang.String. Any idea?
var textToSelect_begin = element.all(by.css('.numberingLevel1')).get(0);
var textToSelect_end = element.all(by.css('.numberingLevel1')).get(1);
browser.executeScript(dragNDrop, textToSelect_begin.getWebElement(), textToSelect_end.getWebElement());
Thank you
DragAndDrop doesn't work for me. I try to move item of list and it moves a little bit, but still at the same place.
When I move element a new item of list is creates, look at the image.
Have you any ideas?
Here is my code:
var dragElement = element(by.id("i3"));
var dropElement = element(by.id("i1"));
browser.actions().dragAndDrop(dragElement, dropElement).perform();
And here is my page:
<ol ui-tree-nodes="" ng-model="$ctrl.items" class="list-group canSorting ng-pristine ng-untouched ng-valid ng-scope angular-ui-tree-nodes ng-not-empty">
<!-- ngRepeat: item in $ctrl.items --><li collapsed="true" ng-repeat="item in $ctrl.items" ui-tree-node="" class="list-group-item p0 ng-scope angular-ui-tree-node">
<table width="100%">
<tbody><tr>
<td style="vertical-align: middle !important;" class="text-center p0" width="1">
<i id="i0" class="btn btn-sm glyphicon glyphicon-resize-vertical angular-ui-tree-handle ng-scope" ui-tree-handle=""></i>
</td>
<td class="ng-binding" style="border-left: 1px solid #ccc; padding-left: 6px;">
袪邪蟹写械谢 1
</td>
</tr>
</tbody></table>
</li><!-- end ngRepeat: item in $ctrl.items --><li style="" collapsed="true" ng-repeat="item in $ctrl.items" ui-tree-node="" class="list-group-item p0 ng-scope angular-ui-tree-node">
<table width="100%">
<tbody><tr>
<td style="vertical-align: middle !important;" class="text-center p0" width="1">
<i id="i1" class="btn btn-sm glyphicon glyphicon-resize-vertical angular-ui-tree-handle ng-scope" ui-tree-handle=""></i>
</td>
<td class="ng-binding" style="border-left: 1px solid #ccc; padding-left: 6px;">
袪邪蟹写械谢 2
</td>
</tr>
</tbody></table>
</li><!-- end ngRepeat: item in $ctrl.items --><li style="" collapsed="true" ng-repeat="item in $ctrl.items" ui-tree-node="" class="list-group-item p0 ng-scope angular-ui-tree-node">
<table width="100%">
<tbody><tr>
<td style="vertical-align: middle !important;" class="text-center p0" width="1">
<i id="i2" class="btn btn-sm glyphicon glyphicon-resize-vertical angular-ui-tree-handle ng-scope" ui-tree-handle=""></i>
</td>
<td class="ng-binding" style="border-left: 1px solid #ccc; padding-left: 6px;">
袪邪蟹写械谢 c 锌褉芯泄写械薪薪褘屑 褌械褋褌芯屑
</td>
</tr>
</tbody></table>
</li><!-- end ngRepeat: item in $ctrl.items --><li style="" collapsed="true" ng-repeat="item in $ctrl.items" ui-tree-node="" class="list-group-item p0 ng-scope angular-ui-tree-node">
<table width="100%">
<tbody><tr>
<td style="vertical-align: middle !important;" class="text-center p0" width="1">
<i id="i3" class="btn btn-sm glyphicon glyphicon-resize-vertical angular-ui-tree-handle ng-scope" ui-tree-handle=""></i>
</td>
<td class="ng-binding" style="border-left: 1px solid #ccc; padding-left: 6px;">
袪邪蟹写械谢 3
</td>
</tr>
</tbody></table>
</li><!-- end ngRepeat: item in $ctrl.items -->
</ol>

@ayashpatrov: Looks like you have a typo .. var dragElement = [element...
@ryanki1: Oh! Thank you, but it's not a problem. It's just typo in question.
It's not clean but I was able to get drag and drop to move by doing the following:
browser.actions().mouseDown(el).perform();
browser.actions().mouseMove({x:0, y:100}).perform();
browser.actions().mouseDown(el).perform();
browser.actions().mouseMove({x:0, y:75}).perform();
browser.actions().mouseUp().perform();
This worked for me in chrome Version 51.0.2704.103 (64-bit)
@vickyzeng You have to put the drag.js file in module.exports format:
module.exports = 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);
};
or else Java will choke on the '{}' string which node creates when trying to import a naked function.
var elm = ptor.element(protractor.By.id(''));
ptor.driver.actions().dragAndDrop(elm, targetelm )
.mouseMove(elm).perform();
this works for me
module.exports = 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)
}
This function works for me, when you're in the protractor test you then call something along the lines of DragNDrop(formXY, toXY) and it should work.
it does not work with dragular:
http://valor-software.com/ng2-dragula/
p_Login.openUrl("http://valor-software.com/ng2-dragula/");
let ele1=element(by.xpath("//example-app//div[contains(text(),'You can move')]"));
let ele2=element(by.xpath("//example-app//div[contains(text(),'This is the default use case')]/.."));
browser.driver.executeScript(dragAndDropFn, ele1.getWebElement(), ele2.getWebElement());
I got the following working with Angular, Material drag and drop and Protractor:
private async dragAndDrop(element: WebElement, destination: WebElement) {
await browser.actions().mouseDown(element).perform();
await browser.actions().mouseMove(destination).perform();
await browser.actions().mouseUp(destination).perform();
}
Also the non-async version (as some are reporting issues with async and browser actions here):
private dragAndDrop(element: WebElement, destination: WebElement) {
return browser.actions().mouseDown(element).perform()
.then(() => browser.actions().mouseMove(destination).perform())
.then(() => browser.actions().mouseUp(destination).perform());
}
But change anything ever so slightly and it falls apart - including omitting the argument to mouseUp. Go figure. Also, destination is found using css selector .cdk-drop-list. Hope it helps someone.
Most helpful comment
It's not clean but I was able to get drag and drop to move by doing the following:
This worked for me in chrome Version 51.0.2704.103 (64-bit)