2

I have two divs.

var e1 = element(by.id('draggable-0'));
var e2 = element(by.id('dropContainer-0'));

I want to drop e1 in e2 .i.e. implementing drag & drop in e2e test case for angular2.

I tried below code:

var e1 = element(by.id('draggable-0'));
var e2 = element(by.id('dropContainer-0'));
browser.driver.actions().dragAndDrop(e1.getWebElement(),e2.getWebElement()).perform();
browser.sleep(2000);

but its not working.My chrome gets opened but nothing happens.

any inputs?

thanks.

Bhushan Gadekar
  • 13,485
  • 21
  • 82
  • 131

1 Answers1

9

Your page implements an HTML5 drag and drop which is not supported by the Selenium dragAndDrop action.

You can however simulate the action by injecting the dragenter, dragover, drop, dragend events with executeScript:

const JS_HTML5_DND = 'function e(e,t,n,i){var r=a.createEvent("DragEvent");r.initMouseEvent(t,!0,!0,o,0,0,0,c,g,!1,!1,!1,!1,0,null),Object.defineProperty(r,"dataTransfer",{get:function(){return d}}),e.dispatchEvent(r),o.setTimeout(i,n)}var t=arguments[0],n=arguments[1],i=arguments[2]||0,r=arguments[3]||0;if(!t.draggable)throw new Error("Source element is not draggable.");var a=t.ownerDocument,o=a.defaultView,l=t.getBoundingClientRect(),u=n?n.getBoundingClientRect():l,c=l.left+(l.width>>1),g=l.top+(l.height>>1),s=u.left+(u.width>>1)+i,f=u.top+(u.height>>1)+r,d=Object.create(Object.prototype,{_items:{value:{}},effectAllowed:{value:"all",writable:!0},dropEffect:{value:"move",writable:!0},files:{get:function(){return this._items.Files}},types:{get:function(){return Object.keys(this._items)}},setData:{value:function(e,t){this._items[e]=t}},getData:{value:function(e){return this._items[e]}},clearData:{value:function(e){delete this._items[e]}},setDragImage:{value:function(e){}}});if(n=a.elementFromPoint(s,f),!n)throw new Error("The target element is not interactable and need to be scrolled into the view.");u=n.getBoundingClientRect(),e(t,"dragstart",101,function(){var i=n.getBoundingClientRect();c=i.left+s-u.left,g=i.top+f-u.top,e(n,"dragenter",1,function(){e(n,"dragover",101,function(){n=a.elementFromPoint(c,g),e(n,"drop",1,function(){e(t,"dragend",1,callback)})})})})';

var e1 = element(by.id('draggable-0'));
var e2 = element(by.id('dropContainer-0'));
browser.executeScript(JS_HTML5_DND, e1.getWebElement(), e2.getWebElement());

The source of the drag and drop script:

https://gist.github.com/florentbr/60ef7cb8d9b1ae690cafc82aad52da73#file-drag-drop-js

Florent B.
  • 41,537
  • 7
  • 86
  • 101
  • Tried this, it hangs the chrome. i.e. my app would not get open in chrome after adding this. – Bhushan Gadekar Nov 15 '16 at 11:57
  • I just test it on http://akserg.github.io/ng2-webpack-demo/#/dnd and it worked as expected. It could be that your version of protractor doesn't resolve the provided elements. Try with `browser.executeScript(JS_HTML5_DND, e1.getWebElement(), e2.getWebElement());`. Also try `browser.driver.executeScript(JS_HTML5_DND, e1.getWebElement(), e2.getWebElement());` to see if it's a sync issue. – Florent B. Nov 15 '16 at 12:13
  • it says target element is not draggable.but I have applied draggable directive on the same element – Bhushan Gadekar Nov 15 '16 at 12:17
  • The source element should have the `draggable` attribute set to `true`. – Florent B. Nov 15 '16 at 12:19
  • Doesn't seem to work with https://github.com/SortableJS/Sortable – methuselah Apr 16 '20 at 17:25