mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-16 15:20:13 +01:00
migrate context and context_list features. Drag and drop is still WIP
This commit is contained in:
parent
de309c8ee8
commit
4a8fdbabc2
12 changed files with 246 additions and 94 deletions
1
Gemfile
1
Gemfile
|
|
@ -47,6 +47,7 @@ group :test do
|
||||||
gem "thoughtbot-factory_girl"
|
gem "thoughtbot-factory_girl"
|
||||||
gem 'memory_test_fix', '~>0.1.3'
|
gem 'memory_test_fix', '~>0.1.3'
|
||||||
gem "capybara", ">=0.3.5"
|
gem "capybara", ">=0.3.5"
|
||||||
|
gem "capybara-webkit"
|
||||||
gem "database_cleaner", ">=0.5.0"
|
gem "database_cleaner", ">=0.5.0"
|
||||||
gem "cucumber-rails", "~>0.3.2"
|
gem "cucumber-rails", "~>0.3.2"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@ GEM
|
||||||
rack-test (>= 0.5.4)
|
rack-test (>= 0.5.4)
|
||||||
selenium-webdriver (~> 2.0)
|
selenium-webdriver (~> 2.0)
|
||||||
xpath (~> 0.1.4)
|
xpath (~> 0.1.4)
|
||||||
|
capybara-webkit (0.8.0)
|
||||||
|
capybara (>= 1.0.0, < 1.2)
|
||||||
|
json
|
||||||
cgi_multipart_eof_fix (2.5.0)
|
cgi_multipart_eof_fix (2.5.0)
|
||||||
childprocess (0.3.0)
|
childprocess (0.3.0)
|
||||||
ffi (~> 1.0.6)
|
ffi (~> 1.0.6)
|
||||||
|
|
@ -134,6 +137,7 @@ DEPENDENCIES
|
||||||
acts_as_list (~> 0.1.4)
|
acts_as_list (~> 0.1.4)
|
||||||
bcrypt-ruby (~> 2.1.4)
|
bcrypt-ruby (~> 2.1.4)
|
||||||
capybara (>= 0.3.5)
|
capybara (>= 0.3.5)
|
||||||
|
capybara-webkit
|
||||||
cucumber-rails (~> 0.3.2)
|
cucumber-rails (~> 0.3.2)
|
||||||
database_cleaner (>= 0.5.0)
|
database_cleaner (>= 0.5.0)
|
||||||
flexmock
|
flexmock
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
<%= javascript_include_tag 'hoverIntent','superfish','application',
|
<%= javascript_include_tag 'hoverIntent','superfish','application',
|
||||||
'accesskey-hints','niftycube','swfobject',
|
'accesskey-hints','niftycube','swfobject',
|
||||||
:cache => 'tracks-cached' %>
|
:cache => 'tracks-cached' %>
|
||||||
|
<%= javascript_include_tag('jquery.simulate.drag-sortable') if ENV['RAILS_ENV']=='test' -%>
|
||||||
<%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>
|
<%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>
|
||||||
<%= javascript_tag "var SOURCE_VIEW = '#{@source_view}';" %>
|
<%= javascript_tag "var SOURCE_VIEW = '#{@source_view}';" %>
|
||||||
<%= javascript_tag "var TAG_NAME = '#{@tag_name}';" if @tag_name %>
|
<%= javascript_tag "var TAG_NAME = '#{@tag_name}';" if @tag_name %>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ Feature: Edit a context
|
||||||
And I have a project called "test project"
|
And I have a project called "test project"
|
||||||
And I have 2 todos in project "test project" in context "@pc" with tags "starred"
|
And I have 2 todos in project "test project" in context "@pc" with tags "starred"
|
||||||
|
|
||||||
@selenium
|
@javascript
|
||||||
Scenario: In place edit of context name
|
Scenario: In place edit of context name
|
||||||
Given I have a context called "Errands"
|
Given I have a context called "Errands"
|
||||||
When I go to the context page for "Errands"
|
When I go to the context page for "Errands"
|
||||||
|
|
@ -22,7 +22,7 @@ Feature: Edit a context
|
||||||
Then he should see that a context named "Errands" is not present
|
Then he should see that a context named "Errands" is not present
|
||||||
And he should see that a context named "OutAndAbout" is present
|
And he should see that a context named "OutAndAbout" is present
|
||||||
|
|
||||||
@selenium
|
@javascript
|
||||||
Scenario: Editing the context of a todo will remove the todo
|
Scenario: Editing the context of a todo will remove the todo
|
||||||
When I go to the the context page for "@pc"
|
When I go to the the context page for "@pc"
|
||||||
Then the badge should show 2
|
Then the badge should show 2
|
||||||
|
|
@ -30,14 +30,14 @@ Feature: Edit a context
|
||||||
Then I should not see "todo 1"
|
Then I should not see "todo 1"
|
||||||
And the badge should show 1
|
And the badge should show 1
|
||||||
|
|
||||||
@selenium
|
@javascript
|
||||||
Scenario: Editing the description of a a todo will update that todo
|
Scenario: Editing the description of a a todo will update that todo
|
||||||
When I go to the the context page for "@pc"
|
When I go to the the context page for "@pc"
|
||||||
And I edit the description of "todo 1" to "changed"
|
And I edit the description of "todo 1" to "changed"
|
||||||
Then I should not see "todo 1"
|
Then I should not see "todo 1"
|
||||||
And I should see "changed"
|
And I should see "changed"
|
||||||
|
|
||||||
@selenium
|
@javascript
|
||||||
Scenario: Editing the context of the last todo will remove the todo and show empty message
|
Scenario: Editing the context of the last todo will remove the todo and show empty message
|
||||||
When I go to the the context page for "@pc"
|
When I go to the the context page for "@pc"
|
||||||
And I edit the context of "todo 1" to "@laptop"
|
And I edit the context of "todo 1" to "@laptop"
|
||||||
|
|
@ -48,7 +48,7 @@ Feature: Edit a context
|
||||||
And the badge should show 0
|
And the badge should show 0
|
||||||
And I should see "Currently there are no incomplete actions in this context"
|
And I should see "Currently there are no incomplete actions in this context"
|
||||||
|
|
||||||
@selenium
|
@javascript
|
||||||
Scenario: Adding a todo to a hidden project will not show the todo
|
Scenario: Adding a todo to a hidden project will not show the todo
|
||||||
Given I have a hidden project called "hidden project"
|
Given I have a hidden project called "hidden project"
|
||||||
When I go to the the context page for "@pc"
|
When I go to the the context page for "@pc"
|
||||||
|
|
@ -61,7 +61,7 @@ Feature: Edit a context
|
||||||
And I should see "todo X"
|
And I should see "todo X"
|
||||||
And the badge should show 2
|
And the badge should show 2
|
||||||
|
|
||||||
@selenium
|
@javascript
|
||||||
Scenario: Adding a todo to a hidden context will show that todo
|
Scenario: Adding a todo to a hidden context will show that todo
|
||||||
Given I have a hidden context called "@personal"
|
Given I have a hidden context called "@personal"
|
||||||
When I go to the the context page for "@pc"
|
When I go to the the context page for "@pc"
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ Feature: Manage the list of contexts
|
||||||
Then I should be on the context page for "@bar"
|
Then I should be on the context page for "@bar"
|
||||||
And the badge should show 3
|
And the badge should show 3
|
||||||
|
|
||||||
@selenium
|
@javascript
|
||||||
Scenario: Delete context from context page should update badge
|
Scenario: Delete context from context page should update badge
|
||||||
Given I have a context called "@computer"
|
Given I have a context called "@computer"
|
||||||
And I have a context called "@ipad"
|
And I have a context called "@ipad"
|
||||||
|
|
@ -48,7 +48,7 @@ Feature: Manage the list of contexts
|
||||||
And the badge should show 1
|
And the badge should show 1
|
||||||
And the context list badge for active contexts should show 1
|
And the context list badge for active contexts should show 1
|
||||||
|
|
||||||
@selenium
|
@javascript
|
||||||
Scenario: Delete last context from context page should remove the contexts container for hidden or active contexts
|
Scenario: Delete last context from context page should remove the contexts container for hidden or active contexts
|
||||||
Given I have a context called "@computer"
|
Given I have a context called "@computer"
|
||||||
And I have a hidden context called "@ipad"
|
And I have a hidden context called "@ipad"
|
||||||
|
|
@ -62,7 +62,7 @@ Feature: Manage the list of contexts
|
||||||
Then I should see that a context named "@ipad" is not present
|
Then I should see that a context named "@ipad" is not present
|
||||||
And I should see that the context container for hidden contexts is not present
|
And I should see that the context container for hidden contexts is not present
|
||||||
|
|
||||||
@selenium
|
@javascript
|
||||||
Scenario: Delete context from context page right after an edit
|
Scenario: Delete context from context page right after an edit
|
||||||
Given I have a context called "@computer"
|
Given I have a context called "@computer"
|
||||||
When I go to the contexts page
|
When I go to the contexts page
|
||||||
|
|
@ -71,7 +71,7 @@ Feature: Manage the list of contexts
|
||||||
Then he should see that a context named "@laptop" is not present
|
Then he should see that a context named "@laptop" is not present
|
||||||
And the badge should show 0
|
And the badge should show 0
|
||||||
|
|
||||||
@selenium
|
@javascript
|
||||||
Scenario: Edit context from context twice
|
Scenario: Edit context from context twice
|
||||||
Given I have a context called "@computer"
|
Given I have a context called "@computer"
|
||||||
When I go to the contexts page
|
When I go to the contexts page
|
||||||
|
|
@ -82,7 +82,7 @@ Feature: Manage the list of contexts
|
||||||
And he should see that a context named "@ipad" is present
|
And he should see that a context named "@ipad" is present
|
||||||
And the badge should show 1
|
And the badge should show 1
|
||||||
|
|
||||||
@selenium
|
@javascript
|
||||||
Scenario Outline: Add a new context with state
|
Scenario Outline: Add a new context with state
|
||||||
Given I have the following contexts
|
Given I have the following contexts
|
||||||
| context | hide |
|
| context | hide |
|
||||||
|
|
@ -97,13 +97,13 @@ Feature: Manage the list of contexts
|
||||||
| active | @phone |
|
| active | @phone |
|
||||||
| hidden | @hidden |
|
| hidden | @hidden |
|
||||||
|
|
||||||
@selenium
|
@javascript
|
||||||
Scenario: Cannot add a context with comma in the name
|
Scenario: Cannot add a context with comma in the name
|
||||||
When I go to the contexts page
|
When I go to the contexts page
|
||||||
And I add a new active context "foo, bar"
|
And I add a new active context "foo, bar"
|
||||||
Then I should see "Name cannot contain the comma"
|
Then I should see "Name cannot contain the comma"
|
||||||
|
|
||||||
@selenium
|
@javascript @wip
|
||||||
Scenario: I can drag and drop to order the contexts
|
Scenario: I can drag and drop to order the contexts
|
||||||
Given I have the following contexts
|
Given I have the following contexts
|
||||||
| context |
|
| context |
|
||||||
|
|
@ -112,10 +112,10 @@ Feature: Manage the list of contexts
|
||||||
| @boss |
|
| @boss |
|
||||||
When I go to the contexts page
|
When I go to the contexts page
|
||||||
Then context "@ipad" should be above context "@home"
|
Then context "@ipad" should be above context "@home"
|
||||||
When I drag context "@ipad" below context "@home"
|
When I drag context "@home" above context "@ipad"
|
||||||
Then context "@home" should be above context "@ipad"
|
Then context "@home" should be above context "@ipad"
|
||||||
|
|
||||||
@selenium
|
@javascript
|
||||||
Scenario: Hiding and unhiding the new context form
|
Scenario: Hiding and unhiding the new context form
|
||||||
When I go to the contexts page
|
When I go to the contexts page
|
||||||
Then the new context form should be visible
|
Then the new context form should be visible
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,27 @@
|
||||||
When /^I delete the context "([^\"]*)"$/ do |context_name|
|
When /^I delete the context "([^\"]*)"$/ do |context_name|
|
||||||
context = @current_user.contexts.find_by_name(context_name)
|
context = @current_user.contexts.find_by_name(context_name)
|
||||||
context.should_not be_nil
|
context.should_not be_nil
|
||||||
click_link "delete_context_#{context.id}"
|
|
||||||
selenium.get_confirmation.should == "Are you sure that you want to delete the context '#{context_name}'? Be aware that this will also delete all (repeating) actions in this context!"
|
handle_js_confirm do
|
||||||
wait_for do
|
click_link "delete_context_#{context.id}"
|
||||||
!selenium.is_element_present("delete_context_#{context.id}")
|
|
||||||
end
|
end
|
||||||
|
get_confirm_text.should == "Are you sure that you want to delete the context '#{context_name}'? Be aware that this will also delete all (repeating) actions in this context!"
|
||||||
|
wait_for_animations_to_end
|
||||||
end
|
end
|
||||||
|
|
||||||
When /^I edit the context to rename it to "([^\"]*)"$/ do |new_name|
|
When /^I edit the context to rename it to "([^\"]*)"$/ do |new_name|
|
||||||
click_link "edit_context_#{@context.id}"
|
find("a#link_edit_context_#{@context.id}").click
|
||||||
|
|
||||||
wait_for do
|
wait_until do
|
||||||
selenium.is_element_present("submit_context_#{@context.id}")
|
page.has_css?("button#submit_context_#{@context.id}")
|
||||||
end
|
end
|
||||||
|
|
||||||
fill_in "context_name", :with => new_name
|
fill_in "context_name", :with => new_name
|
||||||
|
|
||||||
selenium.click "submit_context_#{@context.id}",
|
click_button "submit_context_#{@context.id}"
|
||||||
:wait_for => :text,
|
|
||||||
:text => "Context saved",
|
wait_until do
|
||||||
:timeout => 5
|
!page.has_css?("button#submit_context_#{@context.id}", :visible=>true)
|
||||||
|
|
||||||
wait_for do
|
|
||||||
!selenium.is_element_present("submit_context_#{@context.id}")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -42,57 +40,70 @@ When /^I add a new hidden context "([^"]*)"$/ do |context_name|
|
||||||
submit_new_context_form
|
submit_new_context_form
|
||||||
end
|
end
|
||||||
|
|
||||||
When /^I drag context "([^"]*)" below context "([^"]*)"$/ do |context_drag, context_drop|
|
When /^I drag context "([^"]*)" above context "([^"]*)"$/ do |context_drag, context_drop|
|
||||||
drag_id = @current_user.contexts.find_by_name(context_drag).id
|
drag_id = @current_user.contexts.find_by_name(context_drag).id
|
||||||
drop_id = @current_user.contexts.find_by_name(context_drop).id
|
drop_id = @current_user.contexts.find_by_name(context_drop).id
|
||||||
|
|
||||||
container_height = selenium.get_element_height("//div[@id='container_context_#{drag_id}']").to_i
|
# container_height = page.driver.get_element_height("//div[@id='container_context_#{drag_id}']").to_i
|
||||||
vertical_offset = container_height*2
|
# vertical_offset = container_height*2
|
||||||
coord_string = "10,#{vertical_offset}"
|
# coord_string = "10,#{vertical_offset}"
|
||||||
|
|
||||||
drag_context_handle_xpath = "//div[@id='context_#{drag_id}']//span[@class='handle']"
|
drag_context_handle = find("div#context_#{drag_id} span.handle")
|
||||||
drop_context_container_xpath = "//div[@id='container_context_#{drop_id}']"
|
drag_context_handle.text.should == "DRAG"
|
||||||
|
|
||||||
|
drop_context_container = find("div#container_context_#{drop_id}")
|
||||||
|
|
||||||
selenium.mouse_down_at(drag_context_handle_xpath,"2,2")
|
drag_context_handle.drag_to(drop_context_container)
|
||||||
selenium.mouse_move_at(drop_context_container_xpath,coord_string)
|
|
||||||
# no need to simulate mouse_over for this test
|
# TODO: omzetten naar volgende script
|
||||||
selenium.mouse_up_at(drop_context_container_xpath,coord_string)
|
page.execute_script %Q{
|
||||||
|
$('.sortable-books li:last').simulateDragSortable({move: -4});
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(5)
|
||||||
|
|
||||||
|
# page.driver.mouse_down_at(drag_context_handle_xpath,"2,2")
|
||||||
|
# page.driver.mouse_move_at(drop_context_container_xpath,coord_string)
|
||||||
|
# # no need to simulate mouse_over for this test
|
||||||
|
# page.driver.mouse_up_at(drop_context_container_xpath,coord_string)
|
||||||
end
|
end
|
||||||
|
|
||||||
Then /^context "([^"]*)" should be above context "([^"]*)"$/ do |context_high, context_low|
|
Then /^context "([^"]*)" should be above context "([^"]*)"$/ do |context_high, context_low|
|
||||||
high_id = @current_user.contexts.find_by_name(context_high).id
|
high_id = "context_#{@current_user.contexts.find_by_name(context_high).id}"
|
||||||
low_id = @current_user.contexts.find_by_name(context_low).id
|
low_id = "context_#{@current_user.contexts.find_by_name(context_low).id}"
|
||||||
high_pos = selenium.get_element_position_top("//div[@id='context_#{high_id}']").to_i
|
contexts = page.all("div.context").map { |x| x[:id] }
|
||||||
low_pos = selenium.get_element_position_top("//div[@id='context_#{low_id}']").to_i
|
contexts.find_index(high_id).should < contexts.find_index(low_id)
|
||||||
(high_pos < low_pos).should be_true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Then /^I should see that a context named "([^"]*)" is not present$/ do |context_name|
|
Then /^I should see that a context named "([^"]*)" is not present$/ do |context_name|
|
||||||
Then "I should not see \"#{context_name}\""
|
within "div#display_box" do
|
||||||
|
Then "I should not see \"#{context_name}\""
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Then /^I should see that the context container for (.*) contexts is not present$/ do |state|
|
Then /^I should see that the context container for (.*) contexts is not present$/ do |state|
|
||||||
selenium.is_visible("list-#{state}-contexts-container").should_not be_true
|
page.has_css?("div#list-#{state}-contexts-container", :visible => true).should be_false
|
||||||
end
|
end
|
||||||
|
|
||||||
Then /^I should see that the context container for (.*) contexts is present$/ do |state|
|
Then /^I should see that the context container for (.*) contexts is present$/ do |state|
|
||||||
selenium.is_visible("list-#{state}-contexts-container").should be_true
|
find("div#list-#{state}-contexts-container", :visible => true).should_not be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
Then /^I should see the context "([^"]*)" under "([^"]*)"$/ do |context_name, state|
|
Then /^I should see the context "([^"]*)" under "([^"]*)"$/ do |context_name, state|
|
||||||
context = Context.find_by_name(context_name)
|
context = Context.find_by_name(context_name)
|
||||||
context.should_not be_nil
|
context.should_not be_nil
|
||||||
response.should have_xpath("//div[@id='list-contexts-#{state}']//div[@id='context_#{context.id}']")
|
|
||||||
|
page.has_css?("div#list-contexts-#{state} div#context_#{context.id}").should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
Then /^the new context form should be visible$/ do
|
Then /^the new context form should be visible$/ do
|
||||||
selenium.is_visible("context_new").should be_true
|
page.has_css?("div#context_new", :visible => true).should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
Then /^the new context form should not be visible$/ do
|
Then /^the new context form should not be visible$/ do
|
||||||
selenium.is_visible("context_new").should be_false
|
page.has_css?("div#context_new", :visible => true).should be_false
|
||||||
end
|
end
|
||||||
|
|
||||||
Then /^the context list badge for ([^"]*) contexts should show (\d+)$/ do |state_name, count|
|
Then /^the context list badge for ([^"]*) contexts should show (\d+)$/ do |state_name, count|
|
||||||
selenium.get_text("xpath=//span[@id='#{state_name}-contexts-count']").should == count
|
find("span##{state_name}-contexts-count").text.should == count
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ Given /^I have a context "([^\"]*)" with (.*) actions$/ do |context_name, number
|
||||||
end
|
end
|
||||||
|
|
||||||
When /^I edit the context name in place to be "([^\"]*)"$/ do |new_context_name|
|
When /^I edit the context name in place to be "([^\"]*)"$/ do |new_context_name|
|
||||||
selenium.click "context_name"
|
page.find("span#context_name").click
|
||||||
fill_in "value", :with => new_context_name
|
fill_in "value", :with => new_context_name
|
||||||
click_button "Ok"
|
click_button "Ok"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,9 @@ When /I change the (.*) field of "([^\"]*)" to "([^\"]*)"$/ do |field_name, todo
|
||||||
todo.should_not be_nil
|
todo.should_not be_nil
|
||||||
|
|
||||||
open_edit_form_for(todo)
|
open_edit_form_for(todo)
|
||||||
selenium.type("css=form.edit_todo_form input[name=#{field_name}]", new_value)
|
within "form.edit_todo_form" do
|
||||||
|
fill_in "#{field_name}", :with => new_value
|
||||||
|
end
|
||||||
submit_edit_todo_form(todo)
|
submit_edit_todo_form(todo)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,11 @@ require 'capybara/session'
|
||||||
# BUG in this version of cucumber/capybara: require 'cucumber/rails/capybara_javascript_emulation' # Lets you click links with onclick javascript handlers without using @culerity or @javascript
|
# BUG in this version of cucumber/capybara: require 'cucumber/rails/capybara_javascript_emulation' # Lets you click links with onclick javascript handlers without using @culerity or @javascript
|
||||||
|
|
||||||
Capybara.default_wait_time = 5
|
Capybara.default_wait_time = 5
|
||||||
|
Capybara.javascript_driver = :selenium
|
||||||
|
|
||||||
|
if Capybara.javascript_driver == :webkit
|
||||||
|
require 'capybara/webkit'
|
||||||
|
end
|
||||||
|
|
||||||
# Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In
|
# Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In
|
||||||
# order to ease the transition to Capybara we set the default here. If you'd
|
# order to ease the transition to Capybara we set the default here. If you'd
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,10 @@ module TracksStepHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def submit_new_context_form
|
def submit_new_context_form
|
||||||
selenium.click("xpath=//form[@id='context-form']//button[@id='context_new_submit']", :wait_for => :ajax, :javascript_framework => :jquery)
|
within "form#context-form" do
|
||||||
|
find("button#context_new_submit").click
|
||||||
|
end
|
||||||
|
wait_for_animations_to_end
|
||||||
end
|
end
|
||||||
|
|
||||||
def submit_new_project_form
|
def submit_new_project_form
|
||||||
|
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
|
|
||||||
# It is recommended to regenerate this file in the future when you upgrade to a
|
|
||||||
# newer version of cucumber-rails. Consider adding your own code to a new file
|
|
||||||
# instead of editing this one. Cucumber will automatically load all features/**/*.rb
|
|
||||||
# files.
|
|
||||||
|
|
||||||
vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
|
|
||||||
$LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
|
|
||||||
|
|
||||||
begin
|
|
||||||
require 'cucumber/rake/task'
|
|
||||||
|
|
||||||
namespace :cucumber do
|
|
||||||
Cucumber::Rake::Task.new({:selenium => :env_to_selenium}, 'Run features that require selenium') do |t|
|
|
||||||
t.binary = vendored_cucumber_bin
|
|
||||||
t.fork = true # You may get faster startup if you set this to false
|
|
||||||
t.profile = 'selenium'
|
|
||||||
end
|
|
||||||
|
|
||||||
Cucumber::Rake::Task.new({:selenium_wip => :env_to_selenium}, 'Run unfinished features that require selenium') do |t|
|
|
||||||
t.binary = vendored_cucumber_bin
|
|
||||||
t.fork = true # You may get faster startup if you set this to false
|
|
||||||
t.profile = 'selenium_wip'
|
|
||||||
end
|
|
||||||
|
|
||||||
task :env_to_selenium => 'db:test:prepare' do
|
|
||||||
ENV['RAILS_ENV'] = 'selenium'
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'Run all features'
|
|
||||||
task :all => [:ok, :wip, :selenium, :selenium_wip]
|
|
||||||
end
|
|
||||||
rescue LoadError
|
|
||||||
desc 'cucumber rake task not available (cucumber not installed)'
|
|
||||||
task :cucumber do
|
|
||||||
abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
163
public/javascripts/jquery.simulate.drag-sortable.js
Normal file
163
public/javascripts/jquery.simulate.drag-sortable.js
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
(function($) {
|
||||||
|
/*
|
||||||
|
* Simulate drag of a JQuery UI sortable list
|
||||||
|
* Repository: https://github.com/mattheworiordan/jquery.simulate.drag-sortable.js
|
||||||
|
* Author: http://mattheworiordan.com
|
||||||
|
*
|
||||||
|
* options are:
|
||||||
|
* - move: move item up (positive) or down (negative) by Integer amount
|
||||||
|
* - handle: selector for the draggable handle element (optional)
|
||||||
|
* - listItem: selector to limit which sibling items can be used for reordering
|
||||||
|
* - placeHolder: if a placeholder is used during dragging, we need to consider it's height
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$.fn.simulateDragSortable = function(options) {
|
||||||
|
// build main options before element iteration
|
||||||
|
var opts = $.extend({}, $.fn.simulateDragSortable.defaults, options);
|
||||||
|
|
||||||
|
// iterate and move each matched element
|
||||||
|
return this.each(function() {
|
||||||
|
// allow for a drag handle if item is not draggable
|
||||||
|
var that = this,
|
||||||
|
handle = opts.handle ? $(this).find(opts.handle)[0] : $(this)[0],
|
||||||
|
listItem = opts.listItem,
|
||||||
|
placeHolder = opts.placeHolder,
|
||||||
|
sibling = $(this),
|
||||||
|
moveCounter = Math.floor(opts.move),
|
||||||
|
direction = moveCounter > 0 ? 'down' : 'up',
|
||||||
|
moveVerticalAmount = 0,
|
||||||
|
dragPastBy = 0;
|
||||||
|
|
||||||
|
if (moveCounter === 0) { return; }
|
||||||
|
|
||||||
|
while (moveCounter !== 0) {
|
||||||
|
if (direction === 'down') {
|
||||||
|
if (sibling.next(listItem).length) {
|
||||||
|
sibling = sibling.next(listItem);
|
||||||
|
moveVerticalAmount += sibling.outerHeight();
|
||||||
|
}
|
||||||
|
moveCounter -= 1;
|
||||||
|
} else {
|
||||||
|
if (sibling.prev(listItem).length) {
|
||||||
|
sibling = sibling.prev(listItem);
|
||||||
|
moveVerticalAmount -= sibling.outerHeight();
|
||||||
|
}
|
||||||
|
moveCounter += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var center = findCenter(handle);
|
||||||
|
var x = Math.floor(center.x), y = Math.floor(center.y);
|
||||||
|
dispatchEvent(handle, 'mousedown', createEvent('mousedown', handle, { clientX: x, clientY: y }));
|
||||||
|
// simulate drag start
|
||||||
|
dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x+1, clientY: y+1 }));
|
||||||
|
|
||||||
|
// Sortable is using a fixed height placeholder meaning items jump up and down as you drag variable height items into fixed height placeholder
|
||||||
|
placeHolder = placeHolder && $(this).parent().find(placeHolder);
|
||||||
|
if (placeHolder && placeHolder.length) {
|
||||||
|
// we're going to move past it, and back again
|
||||||
|
moveVerticalAmount += (direction === 'down' ? -1 : 1) * Math.min($(this).outerHeight() / 2, 5);
|
||||||
|
// Sortable UI bug when dragging down and place holder exists. You need to drag past by the total height of this
|
||||||
|
// and then drag back to the right point
|
||||||
|
dragPastBy = (direction === 'down' ? 1 : -1) * $(this).outerHeight() / 2;
|
||||||
|
} else {
|
||||||
|
// no place holder
|
||||||
|
if (direction === 'down') {
|
||||||
|
// need to move at least as far as this item and or the last sibling
|
||||||
|
if ($(this).outerHeight() > $(sibling).outerHeight()) {
|
||||||
|
moveVerticalAmount += $(this).outerHeight() - $(sibling).outerHeight();
|
||||||
|
}
|
||||||
|
moveVerticalAmount += $(sibling).outerHeight() / 2;
|
||||||
|
} else {
|
||||||
|
// move a little extra to ensure item clips into next position
|
||||||
|
moveVerticalAmount -= Math.min($(this).outerHeight() / 2, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sibling[0] !== $(this)[0]) {
|
||||||
|
// step through so that the UI controller can determine when to show the placeHolder
|
||||||
|
var targetOffset = moveVerticalAmount + dragPastBy;
|
||||||
|
for (var offset = 0; Math.abs(offset) < Math.abs(targetOffset); offset += (direction === 'down' ? 10 : -10)) {
|
||||||
|
// drag move
|
||||||
|
dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x, clientY: y + offset }));
|
||||||
|
}
|
||||||
|
dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x, clientY: y + targetOffset }));
|
||||||
|
} else {
|
||||||
|
if (window.console) {
|
||||||
|
console.log('Could not move as at top or bottom already');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x, clientY: y + moveVerticalAmount }));
|
||||||
|
}, 5);
|
||||||
|
setTimeout(function() {
|
||||||
|
dispatchEvent(handle, 'mouseup', createEvent('mouseup', handle, { clientX: x, clientY: y + moveVerticalAmount }));
|
||||||
|
}, 10);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function createEvent(type, target, options) {
|
||||||
|
var evt;
|
||||||
|
var e = $.extend({
|
||||||
|
target: target,
|
||||||
|
preventDefault: function() { },
|
||||||
|
stopImmediatePropagation: function() { },
|
||||||
|
stopPropagation: function() { },
|
||||||
|
isPropagationStopped: function() { return true; },
|
||||||
|
isImmediatePropagationStopped: function() { return true; },
|
||||||
|
isDefaultPrevented: function() { return true; },
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: (type != "mousemove"),
|
||||||
|
view: window,
|
||||||
|
detail: 0,
|
||||||
|
screenX: 0,
|
||||||
|
screenY: 0,
|
||||||
|
clientX: 0,
|
||||||
|
clientY: 0,
|
||||||
|
ctrlKey: false,
|
||||||
|
altKey: false,
|
||||||
|
shiftKey: false,
|
||||||
|
metaKey: false,
|
||||||
|
button: 0,
|
||||||
|
relatedTarget: undefined
|
||||||
|
}, options || {});
|
||||||
|
|
||||||
|
if ($.isFunction(document.createEvent)) {
|
||||||
|
evt = document.createEvent("MouseEvents");
|
||||||
|
evt.initMouseEvent(type, e.bubbles, e.cancelable, e.view, e.detail,
|
||||||
|
e.screenX, e.screenY, e.clientX, e.clientY,
|
||||||
|
e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
|
||||||
|
e.button, e.relatedTarget || document.body.parentNode);
|
||||||
|
} else if (document.createEventObject) {
|
||||||
|
evt = document.createEventObject();
|
||||||
|
$.extend(evt, e);
|
||||||
|
evt.button = { 0:1, 1:4, 2:2 }[evt.button] || evt.button;
|
||||||
|
}
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dispatchEvent(el, type, evt) {
|
||||||
|
if (el.dispatchEvent) {
|
||||||
|
el.dispatchEvent(evt);
|
||||||
|
} else if (el.fireEvent) {
|
||||||
|
el.fireEvent('on' + type, evt);
|
||||||
|
}
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findCenter(el) {
|
||||||
|
var el = $(el), o = el.offset();
|
||||||
|
return {
|
||||||
|
x: o.left + el.outerWidth() / 2,
|
||||||
|
y: o.top + el.outerHeight() / 2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// plugin defaults
|
||||||
|
//
|
||||||
|
$.fn.simulateDragSortable.defaults = {
|
||||||
|
move: 0
|
||||||
|
};
|
||||||
|
})(jQuery);
|
||||||
Loading…
Add table
Add a link
Reference in a new issue