How to test “drag and drop” elements with Behat/Selenium

Smart Gamma
3 min readOct 24, 2016

--

Smart Gamma team got a task to create a functionality on our site to sort records with drag and drop action.

Task

But we need not only create an implementation, but create a functional test with Behat.

The implementation is pretty easy and looks like:

so we have 4 elements and after last row will be moved to 1st, we will call AJAX request and update backend.

We decided to use follow “Sortable” jquery plugin https://jqueryui.com/sortable

It has an event “update”, which we can use for AJAX call to backend. So done!

Problem

Now we are going to the task to cover our implementation by UI functional test. Smart Gamma usually uses Behat BDD framework with combination of different web drivers.

“Googling” gives not much information about exactly solutions.

First proposed solution is to use “DragTo” function of Selenium driver.

Like:

$this->getSession()->getDriver()->dragTo(‘li:eq(‘.$element.’)’, ‘ul#’.$block);

but in our case we was not able to get it up. “DragTo” function was not able to find our draggable element and throwed follow error:

When I drag li "1" in ul block with id "sortQueue" to top # CoreFeatureContext::iDragLiToTop()
The given selector li:eq(1) is either invalid or does not result in a WebElement. The following error occurred:
InvalidSelectorError: Unable to locate an element with the xpath expression li:eq(1) because of the following error:
NamespaceError: An attempt was made to create or change an object in a way which is incorrect with regard to namespaces
For documentation on this error, please visit:
http://seleniumhq.org/exceptions/invalid_selector_exception.html
Build info: version: '2.53.1', revision: 'a36b8b1', time: '2016-06-30 17:37:03'
System info: host: 'jekccs-ubuntu', ip: '127.0.1.1', os.name: 'Linux', os.arch: 'amd64', os.version: '3.13.0-55-generic', java.version: '1.7.0_65'
Driver info: driver.version: unknown (WebDriver\Exception\InvalidSelector)

Second proposed solution was found in the blog of Joeri Timmermans “Testing drag and drop with Behat and Guzzle

The idea is simple:

1. Call the move url with the right data
2. Send the request
3. Validate the success of the request
4. Refresh your browser since you want to view your move

As you can see it has a trick, that we actually skipped UI part, where real interaction with draggable element is performed. But in our UI test we didn’t want to skip real sortable actions.

Smart Gamma Solution

So we implemented real javascript code execution with Behat/Mink “evaluateScript” function as:

/**
* @When I drag li :element in ul block with id :block to top
*/
public function iDragLiToTop($element, $block)
{
$this->getSession()->evaluateScript('$(document).ready(function(){
$("ul#'.$block.'").prepend($("ul#'.$block.' li:eq('.$element.')"));
$("ul#'.$block.'").sortable("option", "update")();})'
);
}

1. change position of elements
2. manually call “update” plugin’s event

Feature: In order to sort element 
As user
I should be able drag and drop elements
@javascript
Scenario: I drag list
Given I am logged as user with login “simple@cloud.lloc” and password “simple@cloud.lloc”
Given I go to "/media/list"
When I drag element with “http://test.com/torrent-3” to top position
Then torrent “http://test.com/torrent-3” should be on position “1”

Originally posted at www.smart-gamma.com

--

--