-
-
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) | |
} |
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)
}
Thank you, the solution above works fine in Protractor