-
-
Save druska/624501b7209a74040175 to your computer and use it in GitHub Desktop.
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) | |
} |
Hi Marina,
Is there a solution for the same when using selenium ? The Drag and Drop action doesn't work in selenium for html5 ( firefox driver ). I wish to code a custom drag and drop action using java for html5; I have tried these 3 methods and none of them work, (a) Trying to click-and-hold then release onto the drop co-ordinates (b) Using iframes ( works only with frames, but I want a general solution ) (c) Saving all the drag and drop helper code in a js file and then calling this in the main java program ( this seems to be the most hyped solution to this problem in stackoverflow and github; doesn't work or maybe I messed up ).
Is there a work around to this ? Using selenium in RedwoodHQ, custom actions coded in java , any help would be appreciated.
cool beans
@pidupuis - did you resolve the duplication of elements?
I have the similar issue with the script above..
@elenatosheva - Not sure what your exact setup is but i was getting the same duplication issue when using https://github.com/marceljuenemann/angular-drag-and-drop-lists.
This was due to the dnd-moved
callback not firing so not removing the original element.
Looking at the source code this is due to dropEffect of move
not being specified in the dataTransfer object.
Adding dropEffect: 'move'
to the object fixed the issue, however this has only been tested on chrome 54 / linux.
event.dataTransfer = {
data: {
},
setData: function(type, val) {
this.data[type] = val
},
getData: function(type) {
return this.data[type]
},
dropEffect: 'move'
}
@leesaxby - Thank very much for the reply. I'm using protractor on windows/chrome to test an angular application, which
have html 5 drag and drop implementation.
I'll try your suggestion soon in the coming days, because now we are busy with testing :(
Otherwise I searched everywhere for a similar problem, but to no avail :(
I'll inform you about the results.
Regards,
Elena
Many thanks, @leesaxby , your solution appears to work in my case too.
Now I can continue writing drag&drop tests.
Regards,
Elena
@leesaxby @elenatosheva
While using above gist to automate https://github.com/marceljuenemann/angular-drag-and-drop-lists only click is happening on source div.
Issue
Even after event.dataTransfer.setData(mimeType, angular.toJson(item));
dataTransfer.types is not set or probably not allowed to read in dragstart and drop event
Observation : during manual drag drop dragstart event
dataTransfer {dropEffect: "none", effectAllowed: "move", items: DataTransferItemList, types: Array(1), files: FileList}
dropEffect:"move"
effectAllowed:"move"
files:FileList
items:DataTransferItemList
types:Array(0)
__proto__:DataTransfer
DataTransferItemList {0: DataTransferItem, length: 1}
length: 0
__proto__: DataTransferItemList
DataTransferItem {kind: "string", type: "application/x-dnd"}
kind: ""type: ""
__proto__: DataTransferItem
**Observation : when using above script - custom event **
dataTransfer:Object
data:Object
application/x-dnd:"[{"id":"706","title":"Ab 2","drag":false,"selected":true}]"
__proto__:Object
dropEffect:"move"
effectAllowed:"move"
getData:function (type)
setData:function (type,val)
files:Object
items:Object
types:Array(0)
I am using
var event = new CustomEvent("CustomEvent", {"cancelable": true})
event.initCustomEvent(type, true, true, null);
event.dataTransfer = {
data: {
},
setData: function(type,val) {
this.data[type] = val
},
getData: function(type) {
return this.data[type]
},
dropEffect: 'move',
effectAllowed:'move',
types: [],
items:{},
files:{}
}
Solved above issue by changing . Now working fine in chrome for ruby for angular drag drop lists
setData: function(type,val) {
this.data[type] = val
this.types[0] = type
}
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());
As of angular-drag-and-drop-lists version >= 2.0.0 the above work around no longer seems to work as is, due to the directive using a custom MIME type.
Iv'e forked the gist and updated it, allowing drag and drop of html elements in protractor tests.
https://gist.github.com/leesaxby/fabc59c82569a225f8d833b5924e23c6
Basic app to test the fix.
https://github.com/leesaxby/protractor-drag-drop/blob/master/README.md
@druska What is the licensing on this code?
Can someone give me an example how to use it in Python script please
Thank you, the solution above works fine in Protractor
Amazing! Thank you for this script, I finally have a test passing. I adapted it slightly to reflect the exact events I was using in my drag/drop component (I also needed 'dragover').
Can you share the dragover event changes done in javascript?
Brilliant solution. Thanks a lot.
I was simulating dropping files onto Facebook's chat window and adding files: []
property to event.dataTransfer
with arbitrary File()
objects actually upload these files.
Hi! I am trying to use this with Sortable.js but nothing happens. No errors and the drag and drop doesn't happen. Is this supposed to work with current browsers?
Hi! I am trying to use this with Sortable.js but nothing happens. No errors and the drag and drop doesn't happen. Is this supposed to work with current browsers?
Same here. Doesn't seem to work with Sortable.js.
Great. Works fine with selenium + java
This is amazing! Works perfectly with Selenium JavascriptExecutor =)
Can anybody please help me to know how can we drag and drop by offset using Javascript executor in Python?
how to drag element to offset?
Thanks !!
If someone is doing this in 2021, and is having trouble with data transfer object (in the above example dataTransfer object is a very trimmed down version of the actual object in 2021, so some of the application implementation could reject this object) then the following would work. Just replaced the Custom event with DragEvent and used the actual DataTransfer object instead of the dummy one.
function simulateDragDrop(sourceNode, destinationNode) {
var EVENT_TYPES = {
DRAG_END: 'dragend',
DRAG_START: 'dragstart',
DROP: 'drop'
}
function createCustomEvent(type, dataTransfer) {
var event = new DragEvent(type, {dataTransfer});
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, new DataTransfer())
dispatchEvent(sourceNode, EVENT_TYPES.DRAG_START, event)
var dropEvent = createCustomEvent(EVENT_TYPES.DROP, event.dataTransfer)
dispatchEvent(destinationNode, EVENT_TYPES.DROP, dropEvent)
var dragEndEvent = createCustomEvent(EVENT_TYPES.DRAG_END, event.dataTransfer)
dispatchEvent(sourceNode, EVENT_TYPES.DRAG_END, dragEndEvent)
}
I was using Selenide and Kotlin. Also had to add a few extra props for my page to the transfer event and a few extra events:
It's both usable with SelenideElements or css selectors if you keep the commented line in the script:
The script:
function simulateDragDrop(sourceNode, destinationNode) {
var EVENT_TYPES = {
MOUSE_DOWN: 'mousedown',
MOUSE_UP: 'mouseup',
DRAG: 'drag',
DRAG_END: 'dragend',
DRAG_OVER: 'dragover',
DRAG_START: 'dragstart',
DROP: 'drop'
}
function createCustomEvent(type) {
var event = new CustomEvent("CustomEvent")
event.initCustomEvent(type, true, true, null)
event.dataTransfer = {
dropEffect: 'move',
effectAllowed: 'all',
files :[],
items: [],
types: [],
data: {
},
setData: function(type, val) {
this.data[type] = val
this.items.push(val);
this.types.push(type);
},
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 mouse_down = createCustomEvent(EVENT_TYPES.MOUSE_DOWN)
dispatchEvent(sourceNode, EVENT_TYPES.MOUSE_DOWN, mouse_down)
var event = createCustomEvent(EVENT_TYPES.DRAG_START)
dispatchEvent(sourceNode, EVENT_TYPES.DRAG_START, event)
var drag = createCustomEvent(EVENT_TYPES.DRAG)
dispatchEvent(sourceNode, EVENT_TYPES.DRAG, drag)
drag_over = createCustomEvent(EVENT_TYPES.DRAG_OVER)
drag_over.dataTransfer = event.dataTransfer
dispatchEvent(destinationNode, EVENT_TYPES.DRAG_OVER, drag_over)
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)
var mouse_up = createCustomEvent(EVENT_TYPES.MOUSE_UP)
dispatchEvent(sourceNode, EVENT_TYPES.MOUSE_UP, mouse_up)
return 1
}
// simulateDragDrop(document.querySelector(arguments[0]),document.querySelector(arguments[1]))
simulateDragDrop(arguments[0],arguments[1])
usage:
val file = File("src/test/resources/js_drag_and_drop.js")
val js = file.readText()
Selenide.executeJavaScript<String>(js, loginIdCard, uniqueIdDropField)
@csbalazs-inst Thank you very much!!!
@mufasalg0 you can use the script above, save it in your repo and read the file into a String object.
I don't know exactly what stack you're using but selenium or most drivers have options for executing javascript directly.
look for "selenium javascript executor" for example.
@Praveer-grover
Hi, is it possible to upgrade this script and move the element to the given coordinates?
If someone is doing this in 2021, and is having trouble with data transfer object (in the above example dataTransfer object is a very trimmed down version of the actual object in 2021, so some of the application implementation could reject this object) then the following would work. Just replaced the Custom event with DragEvent and used the actual DataTransfer object instead of the dummy one.
function simulateDragDrop(sourceNode, destinationNode) { var EVENT_TYPES = { DRAG_END: 'dragend', DRAG_START: 'dragstart', DROP: 'drop' } function createCustomEvent(type, dataTransfer) { var event = new DragEvent(type, {dataTransfer}); 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, new DataTransfer()) dispatchEvent(sourceNode, EVENT_TYPES.DRAG_START, event) var dropEvent = createCustomEvent(EVENT_TYPES.DROP, event.dataTransfer) dispatchEvent(destinationNode, EVENT_TYPES.DROP, dropEvent) var dragEndEvent = createCustomEvent(EVENT_TYPES.DRAG_END, event.dataTransfer) dispatchEvent(sourceNode, EVENT_TYPES.DRAG_END, dragEndEvent) }
@Praveer-grover this changes in this script are not moving elements for me, is it possible that you can confirm this method is still functional?
DragEvent
function simulateDragDrop(sourceNode, destinationNode) {
var EVENT_TYPES = {
DRAG_END: 'dragend',
DRAG_START: 'dragstart',
DROP: 'drop'
}
function createCustomEvent(type, dataTransfer) {
dataTransfer.data = {};
dataTransfer.setData = function(type,val){this.data[type] = val};
dataTransfer.getData = function(type){return this.data[type]};
dataTransfer.dropEffect = 'move';
dataTransfer.effectAllowed = 'move';
dataTransfer.types = [];
dataTransfer.items = {};
dataTransfer.files = {};
var event = new DragEvent(
type,
{
bubbles: true,
cancelable: true,
dataTransfer: dataTransfer
});
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, new DataTransfer())
dispatchEvent(sourceNode, EVENT_TYPES.DRAG_START, event)
var dropEvent = createCustomEvent(EVENT_TYPES.DROP, event.dataTransfer)
dispatchEvent(destinationNode, EVENT_TYPES.DROP, dropEvent)
var dragEndEvent = createCustomEvent(EVENT_TYPES.DRAG_END, event.dataTransfer)
dispatchEvent(sourceNode, EVENT_TYPES.DRAG_END, dragEndEvent)
}
Amazing! Thank you for this script, I finally have a test passing. I adapted it slightly to reflect the exact events I was using in my drag/drop component (I also needed 'dragover').