Why doesn’t this work?
I went to test a drag and drop feature using NightWatch. If you are like me, you tried something like the following:
module.exports = {
"Drag and drop": function(browser) {
// here's the pseudocode
browser.moveToElement('#draggable')
browser.mouseButtonDown(...)
browser.moveToElement('#drop')
browser.mouseButtonUp(...)
}
}
When you run this test, you don’t get the results you expected. No drag and drop happens.
The Fix: html-dnd
The problem is due to Selenium. It doesn’t properly expose HTML5 drag and drop functionality. (I tried to find the main bug report to share, but I couldn’t find it.)
The fix is to use the following npm package: html-dnd. This package enables drag and drop testing in NightWatch by triggering the drag and drop events directly in a web page.
Install
npm install html-dnd --save-dev
Usage
// pull in the dragAndDrop function from the package
const dragAndDrop = require('html-dnd').codeForSelectors
// ...
// Then, in your test, inject the drag and drop script into the page
browser.execute(dragAndDrop, ['#draggable', '#drop'])
Code Example
I hacked a small example drag and drop page for you to test against. Just run the following code to see how your tests work.
I added a couple of browser.pause
calls so you can see what’s happening when the code runs. Otherwise, it’s way too fast.
const dragAndDrop = require('html-dnd').codeForSelectors
module.exports = {
"Drag and drop": function(browser){
browser.url('http://tutorials.actionqa.com/yt/nw/dndexample.htm')
browser.pause(2000)
browser.execute( dragAndDrop, ['#drag1', '#div1'])
browser.pause(2000)
browser.end()
}
}
Remaining Problems
Even though html-dnd let’s you drag-and-drop, other types of testing are still not doable. You can’t “drag and hold”. If you want to verify any behavior of your app while you are in the process of dragging, I haven’t found a way to simulate that.
You can’t slowly drag something, either. You aren’t getting control of the mouse moving the element.
html-dnd
simply triggers the web page’s drag and drop events.
How do we solve this? I’m not sure. The real solution needs to be enabled with Selenium and WebDriver. Until then, I’ll keep looking for hacks.