The Problem
For jottinx I wrote a small piece of code that allowed to sort items using drag and drop. Of course, after writing it and making sure it works (manually), I want to make sure it keeps working. So I add a test, using cucumber.
My scenario actually looks pretty straightforward:
@javascript
Scenario: Dragging a book
Given I authenticate as a "default user"
And I add a new book with title "a-new-book"
And I add a new book with title "another-book"
And I add a new book with title "one-last-book"
And I drag book "one-last-book" to the top
Then book "one-last-book" is at the top of the list
The difficult bit was: how do I implement the dragging?.
Actually it seemed straightforward, because capybara has a method called drag_to
. So I implemented the step like this:
When /^I drag book "([^"]\*)" to the top$/ do |book_title|
drop_place = page.find(:css, 'ul.sortable-books li:first')
page.find(:xpath, "//a[@href='##{book_title.parameterize}']").drag_to(drop_place)
end
But, unfortunately, this did not work. I googled around a bit and found the following two similar questions:
The short conclusion: it does not work, and it is a combination of how jquery implemented the sortable element, and the fact that the selenium driver does not support it yet. So, refraining to using the selenium driver directly does not help either. After some more googling, I found a similar question on stackoverflow, and there I found the solution.
The solution
Enter jquery.simulate.drag-sortable.js. It is a script that will allow you to simulate dragging in a sortable object by issuing a simple javascript command:
// drag item down one position in the list
$('#itemToDrag').simulateDragSortable({ move: 1 });
If move
parameter is negative, it will move up. And down if positive. If you include the js
inside your project, you can easily test that out inside your Chrome console. It just works. Awesome piece of work. To use that in a step-definition, just write:
When /^I drag book "([^"]\*)" to the top$/ do |book_title|
page.execute_script %Q{
$('.sortable-books li:last').simulateDragSortable({move: -4});
}
end
Hope this helps :)