diff --git a/app/controllers/todos_controller.rb b/app/controllers/todos_controller.rb index e9532f6f..4984c6dc 100644 --- a/app/controllers/todos_controller.rb +++ b/app/controllers/todos_controller.rb @@ -3,7 +3,7 @@ class TodosController < ApplicationController skip_before_filter :login_required, :only => [:index, :calendar, :tag] prepend_before_filter :login_or_feed_token_required, :only => [:index, :calendar, :tag] append_before_filter :find_and_activate_ready, :only => [:index, :list_deferred] - append_before_filter :set_group_view_by, :only => [:index, :tag, :create, :list_deferred, :destroy, :defer, :update] + append_before_filter :set_group_view_by, :only => [:index, :tag, :create, :list_deferred, :destroy, :defer, :update, :toggle_check] protect_from_forgery :except => :check_deferred @@ -328,8 +328,10 @@ class TodosController < ApplicationController # def toggle_check @todo = current_user.todos.find(params['id']) + @source_view = params['_source_view'] || 'todo' + @original_item = current_user.todos.build(@todo.attributes) # create a (unsaved) copy of the original todo @original_item_due = @todo.due @original_item_was_deferred = @todo.deferred? @original_item_was_pending = @todo.pending? @@ -494,6 +496,7 @@ class TodosController < ApplicationController def destroy @source_view = params['_source_view'] || 'todo' @todo = current_user.todos.find(params['id']) + @original_item = current_user.todos.build(@todo.attributes) # create a (unsaved) copy of the original todo @original_item_due = @todo.due @context_id = @todo.context_id @project_id = @todo.project_id diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index f9eb6cd5..51595aca 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -496,16 +496,20 @@ module TodosHelper end def update_needs_to_hide_container - return (@remaining_in_context == 0 && todo_moved_out_of_container ) || - (@remaining_in_context == 0 && (@todo_hidden_state_changed && @todo.hidden?)) || - (@remaining_in_context == 0 && @todo_was_deferred_from_active_state) || - (@remaining_in_context == 0 && @tag_was_removed) || - (@remaining_in_context == 0 && @todo_was_destroyed) || - (@remaining_in_context == 0 && @todo.completed? && !(@original_item_was_deferred || @original_item_was_hidden)) if source_view_is(:tag) + if source_view_is(:tag) + return @remaining_in_context == 0 && ( + todo_moved_out_of_container || + (@todo_hidden_state_changed && @todo.hidden?) || + @todo_was_deferred_from_active_state || + @tag_was_removed || + @todo_was_destroyed || + (@todo.completed? && !(@original_item_was_deferred || @original_item_was_hidden)) + ) + end - return false if source_view_is_one_of(:project, :calendar, :done) + return false if source_view_is_one_of(:project, :calendar, :done, :context) - return (@remaining_in_context == 0) && !source_view_is(:context) + return @remaining_in_context == 0 end def update_needs_to_remove_todo_from_container @@ -559,6 +563,15 @@ module TodosHelper return "without_project_container-empty-d" end + def context_container_empty_id(todo) + return "c#{todo.context_id}-empty-d" + end + + def container_empty_id(todo) + raise Exception.new, "no todo set in TodosHelper::container_empty_id. You probably not assign @original_item" if !todo + @group_view_by == "project" ? project_container_empty_id(todo) : context_container_empty_id(todo) + end + def item_container_id (todo) return "hidden_container" if source_view_is(:tag) && todo.hidden? return "c#{todo.context_id}" if source_view_is :deferred @@ -576,13 +589,12 @@ module TodosHelper source_view do |page| page.project { return "deferred_pending_container-empty-d" if empty_criteria_met - return "p#{todo.project_id}-empty-d" + return project_container_empty_id(todo) } page.tag { return "deferred_pending_container-empty-d" if empty_criteria_met return "hidden_container-empty-d" if @todo.hidden? - return "c#{todo.context_id}-empty-d" if @group_view_by == 'context' - return project_container_empty_id(todo) + return container_empty_id(todo) } page.calendar { return "deferred_pending_container-empty-d" if empty_criteria_met @@ -590,15 +602,14 @@ module TodosHelper } page.context { return "deferred_pending_container-empty-d" if empty_criteria_met - return "c#{todo.context_id}-empty-d" + return context_container_empty_id(todo) } page.todo { - return "c#{todo.context_id}-empty-d" if @group_view_by == 'context' - return project_container_empty_id(todo) + return container_empty_id(todo) } end - return "c#{todo.context_id}-empty-d" + return context_container_empty_id(todo) end def empty_criteria_met @@ -621,11 +632,11 @@ module TodosHelper container_id = "" source_view do |page| page.project { - container_id = "p#{@original_item_project_id}-empty-d" if @remaining_in_context == 0 + container_id = project_container_empty_id(@original_item) if @remaining_in_context == 0 container_id = "deferred_pending_container-empty-d" if todo_was_removed_from_deferred_or_blocked_container && @remaining_deferred_or_pending_count == 0 container_id = "completed_container-empty-d" if @completed_count && @completed_count == 0 && !@todo.completed? } - page.deferred { container_id = "c#{@original_item_context_id}-empty-d" if @remaining_in_context == 0 } + page.deferred { container_id = container_empty_id(@original_item) if @remaining_in_context == 0 } page.calendar { container_id = "#{@original_item_due_id}_container-empty-d" if @old_due_empty } page.tag { container_id = "hidden_container-empty-d" if (@remaining_hidden_count == 0 && !@todo.hidden? && @todo_hidden_state_changed) || @@ -635,11 +646,11 @@ module TodosHelper container_id = "completed_container-empty-d" if @completed_count && @completed_count == 0 && !@todo.completed? } page.context { - container_id = "c#{@original_item_context_id}-empty-d" if @remaining_in_context == 0 + container_id = context_container_empty_id(@original_item) if @remaining_in_context == 0 container_id = "deferred_pending_container-empty-d" if todo_was_removed_from_deferred_or_blocked_container && @remaining_deferred_or_pending_count == 0 container_id = "completed_container-empty-d" if @completed_count && @completed_count == 0 && !@todo.completed? } - page.todo { container_id = "c#{@original_item_context_id}-empty-d" if @remaining_in_context == 0 } + page.todo { container_id = context_container_empty_id(@original_item) if @remaining_in_context == 0 } page.done { container_id = "completed_#{@original_completed_period}_container-empty-d" if @remaining_in_context == 0 } end return container_id.blank? ? "" : "$(\"##{container_id}\").slideDown(100);".html_safe diff --git a/app/views/todos/create.js.erb b/app/views/todos/create.js.erb index 27e1a006..a097f2ef 100644 --- a/app/views/todos/create.js.erb +++ b/app/views/todos/create.js.erb @@ -51,7 +51,7 @@ function add_todo_to_existing_container(next_steps) { $('#<%= empty_container_msg_div_id %>').hide(); - $('#<%= item_container_id(@todo) %>').append(html_for_new_todo()); + $('#<%= item_container_id(@todo) %>_items').append(html_for_new_todo()); $('#<%= item_container_id(@todo) %>').slideDown(500, function() { $('#<%= dom_id(@todo) %>').effect('highlight', {}, 2000 ); next_steps.go(); diff --git a/app/views/todos/destroy.js.erb b/app/views/todos/destroy.js.erb index 5fbb6d03..0fa16768 100644 --- a/app/views/todos/destroy.js.erb +++ b/app/views/todos/destroy.js.erb @@ -54,7 +54,7 @@ function show_new_todo_if_todo_was_recurring() { <% if @todo.from_recurring_todo? -%> <% unless @new_recurring_todo.nil? || @new_recurring_todo.deferred? -%> TodoItemsContainer.ensureVisibleWithEffectAppear("<%=item_container_id(@new_recurring_todo)%>"); - $('#<%=item_container_id(@new_recurring_todo)%>').append(html_for_new_recurring_todo()); + $('#<%=item_container_id(@new_recurring_todo)%>_items').append(html_for_new_recurring_todo()); $('#<%= dom_id(@new_recurring_todo, 'line')%>').effect('highlight', {}, 2000 ); TracksPages.page_notify('notice', "<%=t('todos.recurring_action_deleted')%>", 5); <% else -%> @@ -75,11 +75,11 @@ function activate_pending_todos() { if source_view_is_one_of(:project,:tag) -%> $('#<%= dom_id(t) %>').fadeOut(400, function() { $('#<%= dom_id(t) %>').remove(); - $('#<%= item_container_id(t) %>').append("<%= html %>"); + $('#<%= item_container_id(t) %>_items').append("<%= html %>"); <%= "$('#deferred_pending_container-empty-d').show();".html_safe if @remaining_deferred_or_pending_count==0 -%> }); <% else -%> - $('#<%= item_container_id(t) %>').append("<%= html%>"); + $('#<%= item_container_id(t) %>_items').append("<%= html%>"); <% end -%> TodoItems.highlight_todo('#<%= dom_id(t, 'line')%>'); <% end -%> diff --git a/app/views/todos/toggle_check.js.erb b/app/views/todos/toggle_check.js.erb index 60a7973a..4600d6aa 100644 --- a/app/views/todos/toggle_check.js.erb +++ b/app/views/todos/toggle_check.js.erb @@ -11,9 +11,8 @@ animation << "add_to_completed_container" unless source_view_is_one_of(:calendar, :deferred) animation << "add_new_recurring_todo" animation << "activate_pending_todos" - animation << "remove_source_container" else - animation << "add_todo_to_context" unless source_view_is(:done) + animation << "add_todo_to_container" unless source_view_is(:done) animation << "block_predecessors" end animation << "update_empty_container" if source_view_is_one_of(:tag, :todo, :deferred) @@ -34,7 +33,7 @@ function remove_todo(next_steps) { <% if (@remaining_in_context == 0) && update_needs_to_hide_container # remove context with deleted todo -%> - $('#c<%=@todo.context_id%>').fadeOut(400, function() { + $('#<%= item_container_id(@original_item)%>').slideUp(400, function() { $('#<%=dom_id(@todo)%>').remove(); next_steps.go(); }); @@ -52,7 +51,7 @@ function remove_todo(next_steps) { function add_to_completed_container(next_steps) { <% unless current_user.prefs.hide_completed_actions? -%> - $('#<%= item_container_id(@todo) %>').prepend(html_for_todo()); + $('#<%= item_container_id(@todo) %>_items').prepend(html_for_todo()); $("#completed_container-empty-d").slideUp(100); highlight_updated_todo(next_steps); <% end -%> @@ -63,10 +62,11 @@ function replace_todo(next_steps) { next_steps.go(); } -function add_todo_to_context(next_steps) { - $('#<%= item_container_id(@todo) %>').append(html_for_todo()); +function add_todo_to_container(next_steps) { + // <%= @group_view_by %> + $('#<%= item_container_id(@todo) %>_items').append(html_for_todo()); <% if should_make_context_visible -%> - $('#c<%= @todo.context_id %>').fadeIn(500, function() { + $('#<%= item_container_id(@todo) %>').slideDown(500, function() { $("#<%= empty_container_msg_div_id %>").slideUp(100); highlight_updated_todo(next_steps); }); @@ -83,8 +83,8 @@ function add_new_recurring_todo(next_steps) { <% # show new todo if the completed todo was recurring if @todo.from_recurring_todo? unless @new_recurring_todo.nil? || (@new_recurring_todo.deferred? && !source_view_is(:deferred)) -%> - $('#<%= item_container_id(@new_recurring_todo) %>').append(html_for_recurring_todo()); - $('#c<%= @new_recurring_todo.context_id %>').fadeIn(500, function() { + $('#<%= item_container_id(@new_recurring_todo) %>_items').append(html_for_recurring_todo()); + $('#c<%= @new_recurring_todo.context_id %>').slideDown(500, function() { highlight_updated_recurring_todo(next_steps); }); <% else @@ -102,7 +102,7 @@ function update_empty_container(next_steps) { <% if @down_count==0 -%> $('#no_todos_in_view').slideDown(400, function(){ next_steps.go(); }); <% else -%> - $('#no_todos_in_view').fadeOut(100, function(){ next_steps.go(); }); + $('#no_todos_in_view').slideUp(400, function(){ next_steps.go(); }); <% end -%> } @@ -126,13 +126,13 @@ function activate_pending_todos(next_steps) { html = escape_javascript(render(:partial => t, :locals => { :parent_container_type => parent_container_type })) # only project and tag view have a deferred/blocked container if source_view_is_one_of(:project,:tag) -%> - $('#<%= dom_id(t) %>').fadeOut(400, function() { + $('#<%= dom_id(t) %>').slideUp(400, function() { $('#<%= dom_id(t) %>').remove(); - $('#<%= item_container_id(t) %>').append("<%= html %>"); + $('#<%= item_container_id(t) %>_items').append("<%= html %>"); <%= "$('#deferred_pending_container-empty-d').show();".html_safe if @remaining_deferred_or_pending_count==0 -%> }); <% else -%> - $('#<%= item_container_id(t) %>').append("<%= html%>"); + $('#<%= item_container_id(t) %>_items').append("<%= html%>"); <% end -%> TodoItems.highlight_todo('#<%= dom_id(t)%>'); <% end -%> @@ -145,10 +145,10 @@ function block_predecessors(next_steps) { if @saved && @active_to_block # do not render the js in case of an error or if no todos to block @active_to_block.each do |t| %> - $('#<%= dom_id(t) %>').fadeOut(400, function() { + $('#<%= dom_id(t) %>').slideUp(400, function() { $('#<%= dom_id(t) %>').remove(); <% if source_view_is(:project) or source_view_is(:tag) # Insert it in deferred/pending block if existing -%> - $('#<%= item_container_id(t) %>').append("<%= escape_javascript(render(:partial => t, :locals => { :parent_container_type => parent_container_type }))%>"); + $('#<%= item_container_id(t) %>_items').append("<%= escape_javascript(render(:partial => t, :locals => { :parent_container_type => parent_container_type }))%>"); TodoItems.highlight_todo('#<%= dom_id(t)%>'); <% end -%> }); @@ -171,18 +171,6 @@ end next_steps.go(); } -function remove_source_container(next_steps) { - <% if (@remaining_in_context == 0 && source_view_is_one_of(:todo, :tag)) - # remove context with deleted todo - -%> - $('#c<%=@todo.context_id%>').fadeOut(1000, function() { - next_steps.go(); - }); - <% else %> - next_steps.go(); - <% end %> -} - function html_for_recurring_todo() { <%- js = @saved && @new_recurring_todo ? escape_javascript(render(:partial => @new_recurring_todo, :locals => { :parent_container_type => parent_container_type })) : "" diff --git a/app/views/todos/update.js.erb b/app/views/todos/update.js.erb index 45e3def5..6ded8fb8 100644 --- a/app/views/todos/update.js.erb +++ b/app/views/todos/update.js.erb @@ -101,7 +101,7 @@ function update_badge_count() { function insert_new_context_with_updated_todo(next_steps) { $('#display_box').prepend(html_for_new_context()); - $('#c<%= @todo.context_id %>').fadeIn(500, function() { next_steps.go(); }); + $('#<%= item_container_id(@todo) %>').fadeIn(500, function() { next_steps.go(); }); } function html_for_todo() { diff --git a/features/dependencies.feature b/features/dependencies.feature index 3ad1873d..dfaf9600 100644 --- a/features/dependencies.feature +++ b/features/dependencies.feature @@ -57,7 +57,7 @@ Feature: dependencies Then I should not see "test 1" within the dependencies of "test 2" And I should not see "test 1" in the deferred container - @javascript + @javascript Scenario: Completing a predecessor will activate successors Given I have a context called "@pc" And I have a project "dependencies" that has the following todos @@ -75,7 +75,7 @@ Feature: dependencies And I should not see "test 2" in the deferred container And I should see empty message for deferred todos of project - @javascript + @javascript Scenario: Deleting a predecessor will activate successors Given I have a context called "@pc" And I have a project "dependencies" that has the following todos @@ -124,9 +124,10 @@ Feature: dependencies Then I should see an error flash message saying "Cannot add this action as a dependency to a completed action!" And I should see "test 1" in the project container of "dependencies" - @javascript + @javascript Scenario Outline: Marking a successor as complete will update predecessor Given I have a context called "@pc" + And I have selected the view for group by And I have a project "dependencies" that has the following todos | description | context | completed | tags | | test 1 | @pc | no | bla | @@ -142,13 +143,15 @@ Feature: dependencies And I should see "test 1" in the completed container Scenarios: - | page | - | "dependencies" project | - | tag page for "bla" | + | page | grouping | + | "dependencies" project | project | + | tag page for "bla" | context | + | tag page for "bla" | project | @javascript Scenario Outline: Marking a successor as active will update predecessor Given I have a context called "@pc" + And I have selected the view for group by And I have a project "dependencies" that has the following todos | description | context | completed | tags | | test 1 | @pc | no | bla | @@ -166,6 +169,7 @@ Feature: dependencies And I should see "test 1" within the dependencies of "test 2" Scenarios: - | page | - | "dependencies" project | - | tag page for "bla" | \ No newline at end of file + | page | grouping | + | "dependencies" project | project | + | tag page for "bla" | context | + | tag page for "bla" | project | \ No newline at end of file diff --git a/features/edit_a_todo.feature b/features/edit_a_todo.feature index da0d4793..f3cbca99 100644 --- a/features/edit_a_todo.feature +++ b/features/edit_a_todo.feature @@ -19,7 +19,7 @@ Feature: Edit a next action from every page When I go to the tag page for "starred" Then I should see "star me" - @javascript + @javascript Scenario: I can delete a todo Given I have a todo "delete me" in the context "@home" When I go to the home page @@ -27,27 +27,47 @@ Feature: Edit a next action from every page When I delete the action "delete me" Then I should not see "delete me" - @javascript @wip - Scenario: Removing the last todo in context will hide context - # this script fails on https://code.google.com/p/selenium/issues/detail?id=3075 for selenium-webdriver > 2.14. - # and selenium-webdriver < 2.20 fails on firefox 11 :-( So @wip for now. This will work on webkit though - Given I have a todo "delete me" in the context "@home" + @javascript + Scenario Outline: Removing the last todo in container will hide that container + Given I have a todo "delete me" in the context "@home" in the project "do it!" + And I have selected the view for group by When I go to the home page - Then I should see the container for context "@home" - And I should see "delete me" in the context container for "@home" + Then I should see the + And I should see "delete me" in the When I mark "delete me" as complete - Then I should not see the container for context "@home" + Then I should not see the And I should see "delete me" in the completed container When I mark "delete me" as uncompleted - Then I should see the container for context "@home" - When I edit the context of "delete me" to "@pc" - Then I should not see the container for context "@home" - And I should see the container for context "@pc" - And I should see "delete me" in the context container for "@pc" - And I delete the todo "delete me" + Then I should see the + And I should see "delete me" in the + + Scenarios: + | grouping | container | + | context | container for context "@home" | + | project | container for project "do it!" | + + @javascript @wipp + Scenario Outline: Changing container of the todo in that container will hide it + # this script fails on https://code.google.com/p/selenium/issues/detail?id=3075 for selenium-webdriver > 2.14. + # and selenium-webdriver < 2.20 fails on firefox 11 :-( So @wip for now. This may work on webkit though + Given I have a todo "delete me" in the context "@home" in the project "do it" + And I have a project "go for it" + And I have selected the view for group by + When I go to the home page + And I edit the of "delete me" to + Then I should not see the + And I should see the + And I should see "delete me" in the + When I delete the todo "delete me" Then I should not see the todo "delete me" - And I should not see the container for context "@home" - And I should not see the container for context "@pc" + And I should not see the + And I should not see the + + Scenarios: + | grouping | container | new_grouping | new_container | + | context | container for context "@home" | "@pc" | container for context "@pc" | + | project | container for project "do it" | "go for it" | container for project "go for it" | + @javascript Scenario Outline: Deleting the last todo in container will show empty message # only project, context, tag, not todo @@ -112,20 +132,23 @@ Feature: Edit a next action from every page @javascript Scenario Outline: I can mark a completed todo active and it will update empty messages and context containers Given I have a completed todo with description "visible todo" in project "visible project" with tags "starred" in the context "visible context" + And I have selected the view for group by When I go to the Then I should see empty message for todos of - And I should not see the container for context "visible context" + And I should not see the And I should not see empty message for completed todos of When I mark the completed todo "visible todo" active - Then I should see the container for context "visible context" + Then I should see the And I should see empty message for completed todos of - And I should see "visible todo" in the context container for "visible context" + And I should see "visible todo" in the And I should not see empty message for todos of Scenarios: - | page | page type | - | tag page for "starred" | tag | - | home page | home | + | page | page type | grouping | container | + | tag page for "starred" | tag | context | container for context "visible context" | + | tag page for "starred" | tag | project | container for project "visible project" | + | home page | home | context | container for context "visible context" | + | home page | home | project | container for project "visible project" | @javascript Scenario Outline: I can mark a completed todo active and it will update empty messages for pages without context containers @@ -145,36 +168,43 @@ Feature: Edit a next action from every page @javascript Scenario Outline: I can edit a todo to change its description Given I have a todo with description "visible todo" in project "visible project" with tags "starred" in the context "visible context" that is due next week + And I have selected the view for group by When I go to the And I edit the description of "visible todo" to "changed todo" Then I should not see the todo "visible todo" And I should see the todo "changed todo" Scenarios: - | page | - | home page | - | context page for "visible context" | - | "visible project" project | - | tag page for "starred" | - | calendar page | + | page | grouping | + | home page | context | + | home page | project | + | context page for "visible context" | context | + | "visible project" project | context | + | tag page for "starred" | context | + | tag page for "starred" | project | + | calendar page | context | @javascript - Scenario Outline: I can edit a todo to move it to another context + Scenario Outline: I can edit a todo to move it to another container Given I have a context called "@laptop" - And I have a project "my project" that has the following todos + And I have selected the view for group by + And I have a project "project 1" that has the following todos | context | description | tags | | @pc | first action | bla | | @laptop | second action | bla | + And I have a project "project 2" When I go to the - Then I should see "first action" in the context container for "@pc" - When I edit the context of "first action" to "@laptop" - Then I should not see "first action" in the context container for "@pc" - Then I should see "first action" in the context container for "@laptop" + Then I should see "first action" in the + When I edit the of "first action" to + Then I should not see "first action" in the + Then I should see "first action" in the Scenarios: - | page | - | home page | - | tag page for "bla" | + | page | grouping | container | new grouping | new container | + | home page | context | context container for "@pc" | "@laptop" | context container for "@laptop" | + | home page | project | project container for "project 1" | "project 2" | project container for "project 2" | + | tag page for "bla" | context | context container for "@pc" | "@laptop" | context container for "@laptop" | + | tag page for "bla" | project | project container for "project 1" | "project 2" | project container for "project 2" | @javascript Scenario: I can edit a todo to move it to another context in tickler page @@ -267,16 +297,19 @@ Feature: Edit a next action from every page And I should see "tagc" @javascript - Scenario Outline: Editing the context of a todo to a new context will show new context - Given I have a todo "moving" in context "@pc" with tags "tag" + Scenario Outline: Editing the container of a todo to a new container will show new container + Given I have a todo "moving" in context "@pc" in project "project 1 " with tags "tag" + And I have selected the view for group by When I go to the - And I edit the context of "moving" to "@new" - And I should see the container for context "@new" + And I edit the of "moving" to + And I should see the Scenarios: - | page | - | home page | - | tag page for "tag" | + | page | grouping | new grouping | container | + | home page | context | "@new" | container for context "@new" | + | home page | project | "project 2" | container for project "project 2" | + | tag page for "tag" | context | "@new" | container for context "@new" | + | tag page for "tag" | project | "project 2" | container for project "project 2" | @javascript Scenario: Editing the context of a todo in the tickler to a new context will show new context diff --git a/features/search.feature b/features/search.feature index 7a5f58d2..ef725755 100644 --- a/features/search.feature +++ b/features/search.feature @@ -43,7 +43,7 @@ Feature: Show all due actions in a calendar view Then I should not see the todo "tester of stuff" And I should see the todo "test 1-2-3" - @javascript + @javascript Scenario: I can delete found todos Given I have the following todos: | description | context | diff --git a/features/step_definitions/container_steps.rb b/features/step_definitions/container_steps.rb index 95eed0f0..e8f82bd4 100644 --- a/features/step_definitions/container_steps.rb +++ b/features/step_definitions/container_steps.rb @@ -1,19 +1,11 @@ -When /^I collapse the context container of "([^"]*)"$/ do |context_name| - context = @current_user.contexts.where(:name => context_name).first - context.should_not be_nil - - xpath = "//a[@id='toggle_c#{context.id}']" - toggle = page.find(:xpath, xpath) +When(/^I collapse the context container of "([^"]*)"$/) do |context_name| + toggle = page.find(:xpath, toggle_context_container_xpath(find_context(context_name))) toggle.should be_visible toggle.click end When(/^I collapse the project container of "(.*?)"$/) do |project_name| - project = @current_user.projects.where(:name => project_name).first - project.should_not be_nil - - xpath = "//a[@id='toggle_p#{project.id}']" - toggle = page.find(:xpath, xpath) + toggle = page.find(:xpath, toggle_project_container_xpath(find_project(project_name))) toggle.should be_visible toggle.click end @@ -24,97 +16,61 @@ end ####### Context ####### -Then /^I should not see the context "([^"]*)"$/ do |context_name| - context = @current_user.contexts.where(:name => context_name).first - context.should_not be_nil - - xpath = "//div[@id='c#{context.id}']" - page.should_not have_xpath(xpath, :visible => true) +Then(/^I should (see|not see) the context "([^"]*)"$/) do |visible, context_name| + check_xpath_visibility(visible, context_container_xpath(find_context(context_name))) end -Then /^I should not see the container for context "([^"]*)"$/ do |context_name| - step "I should not see the context \"#{context_name}\"" +Then /^I should (see|not see) the container for context "([^"]*)"$/ do |visible, context_name| + step("I should #{visible} the context \"#{context_name}\"") end -Then /^I should not see the context container for "([^"]*)"$/ do |context_name| - step "I should not see the context \"#{context_name}\"" +Then /^I should (see|not see) the context container for "([^"]*)"$/ do |visible, context_name| + step "I should #{visible} the context \"#{context_name}\"" end -Then /^the container for the context "([^"]*)" should not be visible$/ do |context_name| - step "I should not see the context \"#{context_name}\"" -end - -Then /^I should see the container for context "([^"]*)"$/ do |context_name| - context = @current_user.contexts.where(:name => context_name).first - context.should_not be_nil - - xpath = "//div[@id='c#{context.id}']" - page.should have_xpath(xpath) -end - -Then /^the container for the context "([^"]*)" should be visible$/ do |context_name| - step "I should see the container for context \"#{context_name}\"" +Then(/^the container for the context "([^"]*)" should (be|not be) visible$/) do |context_name, visible| + mapping = {"be" => "see", "not be" => "not see"} + step "I should #{mapping[visible]} the context \"#{context_name}\"" end Then /^I should (see|not see) "([^"]*)" in the context container for "([^"]*)"$/ do |visible, todo_description, context_name| - context = @current_user.contexts.where(:name => context_name).first - context.should_not be_nil - todo = @current_user.todos.where(:description => todo_description).first - todo.should_not be_nil + check_xpath_visibility(visible, todo_in_context_container_xpath(find_todo(todo_description), find_context(context_name))) +end - xpath = "//div[@id=\"c#{context.id}\"]//div[@id='line_todo_#{todo.id}']" - page.send( visible=='see' ? :should : :should_not, have_xpath(xpath)) +Then /^I should (see|not see) "([^"]*)" in the container for context "([^"]*)"$/ do |visible, todo_description, context_name| + step "I should #{visible} \"#{todo_description}\" in the context container for \"#{context_name}\"" end ####### Deferred ####### -Then /^I should see "([^"]*)" in the deferred container$/ do |todo_description| - todo = @current_user.todos.where(:description => todo_description).first - todo.should_not be_nil - - page.should have_xpath("//div[@id='deferred_pending_container']//div[@id='line_todo_#{todo.id}']") +Then(/^I should (not see|see) "([^"]*)" in the deferred container$/) do |visible, todo_description| + check_xpath_visibility(visible, todo_in_deferred_container_xpath(find_todo(todo_description))) end -Then /^I should not see "([^"]*)" in the deferred container$/ do |todo_description| - todo = @current_user.todos.where(:description => todo_description).first - todo.should_not be_nil - - page.should_not have_xpath("//div[@id='deferred_pending_container']//div[@id='line_todo_#{todo.id}']") -end - -Then /^I should (not see|see) "([^"]*)" in the action container$/ do |visible, todo_description| - todo = @current_user.todos.where(:description => todo_description).first - todo.should_not be_nil - - id = @source_view=="project" ? "p#{todo.project_id}_items" : "c#{todo.context_id}_items" - - xpath = "//div[@id='#{id}']//div[@id='line_todo_#{todo.id}']" - page.send(visible=="see" ? :should : :should_not, have_xpath(xpath)) -end - -Then /^I should not see "([^"]*)" in the context container of "([^"]*)"$/ do |todo_description, context_name| - step "I should not see \"#{todo_description}\" in the action container" +Then(/^I should (not see|see) "([^"]*)" in the action container$/) do |visible, todo_description| + check_xpath_visibility(visible, todo_in_container_xpath(@source_view.to_s, find_todo(todo_description))) end ####### Project ####### Then /^I should (see|not see) "([^"]*)" in the project container of "([^"]*)"$/ do |visible, todo_description, project_name| - todo = @current_user.todos.where(:description => todo_description).first - todo.should_not be_nil + check_xpath_visibility(visible, todo_in_project_container_xpath(find_todo(todo_description), find_project(project_name))) +end - project = @current_user.projects.where(:name => project_name).first - project.should_not be_nil +Then(/^I should (see|not see) "(.*?)" in the container for project "(.*?)"$/) do |visible, todo_description, project_name| + step "I should #{visible} \"#{todo_description}\" in the project container of \"#{project_name}\"" +end - xpath = "//div[@id='p#{todo.project.id}_items']//div[@id='line_todo_#{todo.id}']" - page.send( visible=='see' ? :should : :should_not, have_xpath(xpath)) +Then(/^I should (see|not see) "(.*?)" in the project container for "(.*?)"$/) do |visible, todo_description, project_name| + step "I should #{visible} \"#{todo_description}\" in the project container of \"#{project_name}\"" end Then(/^I should (see|not see) the project container for "([^"]*)"$/) do |visible, project_name| - project = @current_user.projects.where(:name => project_name).first - project.should_not be_nil + check_xpath_visibility(visible, project_container_xpath(find_project(project_name))) +end - xpath = "//div[@id='p#{project.id}']" - page.send( visible=='see' ? :should : :should_not, have_xpath(xpath, :visible => true)) +Then(/^I should (see|not see) the container for project "(.*?)"$/) do |visible, project_name| + step "I should #{visible} the project container for \"#{project_name}\"" end Then(/^the container for the project "(.*?)" should (be visible|not be visible)$/) do |project_name, visible| @@ -124,37 +80,28 @@ end ####### Completed ####### -Then /^I should (not see|see) "([^"]*)" in the (completed|done today|done this week|done this month) container$/ do |visible, todo_description, container| - todo = @current_user.todos.where(:description => todo_description).first - todo.should_not be_nil - +Then(/^I should (not see|see) "([^"]*)" in the (completed|done today|done this week|done this month) container$/) do |visible, todo_description, container| id = 'completed_container' if container == 'completed' id = 'completed_today_container' if container == 'done today' id = 'completed_rest_of_week_container' if container == 'done this week' id = 'completed_rest_of_month_container' if container == 'done this month' - xpath = "//div[@id='#{id}']//div[@id='line_todo_#{todo.id}']" - page.send( visible=='see' ? :should : :should_not, have_xpath(xpath)) + xpath = "//div[@id='#{id}']//div[@id='line_todo_#{find_todo(todo_description).id}']" + check_xpath_visibility(visible, xpath) end ####### Hidden ####### -Then /^I should see "([^"]*)" in the hidden container$/ do |todo_description| - todo = @current_user.todos.where(:description => todo_description).first - todo.should_not be_nil - - xpath = "//div[@id='hidden_container']//div[@id='line_todo_#{todo.id}']" - page.should have_xpath(xpath) +Then /^I should (not see|see) "([^"]*)" in the hidden container$/ do |visible, todo_description| + xpath = "//div[@id='hidden_container']//div[@id='line_todo_#{find_todo(todo_description).id}']" + check_xpath_visibility(visible, xpath) end ####### Calendar ####### Then /^I should see "([^"]*)" in the due next month container$/ do |todo_description| - todo = @current_user.todos.where(:description => todo_description).first - todo.should_not be_nil - within "div#due_after_this_month_container" do - page.should have_css("div#line_todo_#{todo.id}") + page.should have_css("div#line_todo_#{find_todo(todo_description).id}") end end @@ -165,20 +112,20 @@ Then /^I should (see|not see) "([^"]*)" in the active recurring todos container$ unless repeat.nil? xpath = "//div[@id='active_recurring_todos_container']//div[@id='recurring_todo_#{repeat.id}']" - page.send(visibility == "see" ? "should" : "should_not", have_xpath(xpath, :visible => true)) + check_xpath_visibility(visibility, xpath) else step "I should #{visibility} \"#{repeat_pattern}\"" end end -Then /^I should not see "([^"]*)" in the completed recurring todos container$/ do |repeat_pattern| +Then /^I should (see|not see) "([^"]*)" in the completed recurring todos container$/ do |visible, repeat_pattern| repeat = @current_user.todos.where(:description => repeat_pattern).first unless repeat.nil? xpath = "//div[@id='completed_recurring_todos_container']//div[@id='recurring_todo_#{repeat.id}']" - page.should_not have_xpath(xpath, :visible => true) + check_xpath_visibility(visible, xpath) else - step "I should not see \"#{repeat_pattern}\"" + step "I should #{visible} \"#{repeat_pattern}\"" end end @@ -190,12 +137,13 @@ Then /^I should (see|not see) empty message for (done today|done this week|done css = "div#p#{@project.id}-empty-d" if state == "todos" && type == "of project" css = "div#no_todos_in_view" if state == "todos" && (type == "of home" || type == "of tag") css = "div#completed_today_container" if state == "done today" - css = "div#completed_rest_of_week_container" if state == "done this week" - css = "div#completed_rest_of_month_container" if state == "done this month" + css = "div#completed_rest_of_week_container" if state == "done this week" + css = "div#completed_rest_of_month_container" if state == "done this month" css = "div#completed_container-empty-d" if state == "completed todos" css = "div#deferred_pending_container-empty-d" if state == "deferred todos" elem = find(css) elem.should_not be_nil - elem.send(visible=="see" ? :should : :should_not, be_visible) + + check_elem_visibility(visible, elem) end \ No newline at end of file diff --git a/features/step_definitions/todo_create_steps.rb b/features/step_definitions/todo_create_steps.rb index 25d7961a..bd276e95 100644 --- a/features/step_definitions/todo_create_steps.rb +++ b/features/step_definitions/todo_create_steps.rb @@ -13,6 +13,16 @@ Given /^I have a todo "([^"]*)" in context "([^"]*)" with tags "([^"]*)"$/ do |d @todo.save! end +Given(/^I have a todo "([^"]*)" in the context "([^"]*)" in the project "([^"]*)"$/) do |description, context_name, project_name| + step "I have a todo \"#{description}\" in the context \"#{context_name}\"" + + @project = @current_user.projects.where(:name => project_name).first_or_create + @project.should_not be_nil + + @todo.project = @project + @todo.save! +end + Given /^I have a todo "([^"]*)" in the context "([^"]*)" which is due tomorrow$/ do |description, context_name| context = @current_user.contexts.where(:name => context_name).first_or_create @todo = @current_user.todos.create!(:context_id => context.id, :description => description) @@ -21,11 +31,8 @@ Given /^I have a todo "([^"]*)" in the context "([^"]*)" which is due tomorrow$/ end Given /^I have (\d+) todos in project "([^"]*)" in context "([^"]*)" with tags "([^"]*)" prefixed by "([^"]*)"$/ do |number_of_todos, project_name, context_name, tag_names, prefix| - @context = @current_user.contexts.where(:name => context_name).first - @context.should_not be_nil - - @project = @current_user.projects.where(:name => project_name).first - @project.should_not be_nil + @context = find_context(context_name) + @project = find_project(project_name) @todos = [] number_of_todos.to_i.downto 1 do |i| @@ -76,6 +83,11 @@ Given /^I have a todo with description "([^"]*)" in project "([^"]*)" with tags @todo.save! end +Given(/^I have a todo "(.*?)" in context "(.*?)" in project "(.*?)" with tags "(.*?)"$/) do |action_description, context_name, project_name, tags| + step "I have a todo with description \"#{action_description}\" in project \"#{project_name}\" with tags \"#{tags}\" in the context \"#{context_name}\"" +end + + ###### DEFERRED TODOS ####### Given /^I have ([0-9]+) deferred todos$/ do |count| @@ -107,11 +119,8 @@ end ####### COMPLETED TODOS ####### Given /^I have ([0-9]+) completed todos in project "([^"]*)" in context "([^"]*)"$/ do |count, project_name, context_name| - @context = @current_user.contexts.where(:name => context_name).first - @context.should_not be_nil - - @project = @current_user.projects.where(:name => project_name).first - @project.should_not be_nil + @context = find_context(context_name) + @project = find_project(project_name) @todos = [] count.to_i.downto 1 do |i| @@ -132,9 +141,8 @@ Given /^I have (\d+) completed todos in project "([^"]*)" in context "([^"]*)" w @todos.each { |t| t.tag_with(tags); t.save! } end -Given /^I have ([0-9]+) completed todos in context "([^"]*)"$/ do |count, context_name| - context = @current_user.contexts.where(:name => context_name).first - context.should_not be_nil +Given(/^I have ([0-9]+) completed todos in context "([^"]*)"$/) do |count, context_name| + find_context(context_name) count.to_i.downto 1 do |i| todo = @current_user.todos.create!(:context_id => context.id, :description => "todo #{i}") @@ -170,27 +178,21 @@ Given(/^I have a completed todo with description "([^"]*)" in context "(.*?)" co @todo.reload end - ####### PROJECT WITH TODOS ###### Given /^I have a project "([^"]*)" that has the following (todos|deferred todos)$/ do |project_name, kind_of_todo, todos| step "I have a project called \"#{project_name}\"" @project.should_not be_nil + todos.hashes.each do |todo| - context = @current_user.contexts.where(:name => todo[:context]).first - context.should_not be_nil new_todo = @current_user.todos.create!( :description => todo[:description], - :context_id => context.id, - :project_id=>@project.id, - :notes => todo[:notes]) + :context_id => find_context(todo[:context]).id, + :project_id => @project.id, + :notes => todo[:notes]) new_todo.show_from = Time.zone.now+1.week if kind_of_todo=="deferred todos" - unless todo[:tags].nil? - new_todo.tag_with(todo[:tags]) - end - unless todo[:completed].nil? - new_todo.complete! if todo[:completed] == 'yes' - end + new_todo.tag_with(todo[:tags]) unless todo[:tags].nil? + new_todo.complete! if !todo[:completed].nil? && todo[:completed] == 'yes' end end @@ -221,19 +223,15 @@ When(/^I submit a new action with description "([^"]*)" to project "([^"]*)" wit end When /^I submit a new action with description "([^"]*)" with a dependency on "([^"]*)"$/ do |todo_description, predecessor_description| - predecessor = @current_user.todos.where(:description => predecessor_description).first - predecessor.should_not be_nil + predecessor = find_todo(predecessor_description) within "form#todo-form-new-action" do fill_in "todo[description]", :with => todo_description fill_in "predecessor_input", :with => predecessor_description end - # wait for auto complete - page.should have_css("a.ui-state-focus", :visible => true) - - # click first line - page.find(:css, "ul li a.ui-state-focus").click + wait_for_auto_complete + click_first_line_of_auto_complete new_dependency_line = "//li[@id='pred_#{predecessor.id}']" page.should have_xpath(new_dependency_line, :visible => true) @@ -285,7 +283,7 @@ end ####### submitting using sidebar form: DEFERRED ####### -When /^I submit a new deferred action with description "([^"]*)"$/ do |description| +When(/^I submit a new deferred action with description "([^"]*)"$/) do |description| fill_in "todo[description]", :with => description fill_in "todo[show_from]", :with => format_date(@current_user.time + 1.week) submit_next_action_form diff --git a/features/support/tracks_form_helper.rb b/features/support/tracks_form_helper.rb new file mode 100644 index 00000000..6ff6028f --- /dev/null +++ b/features/support/tracks_form_helper.rb @@ -0,0 +1,93 @@ +module TracksFormHelper + + def open_edit_form_for(todo) + edit_link = "div#line_todo_#{todo.id} a#icon_edit_todo_#{todo.id}" + + # make sure we can open the edit form + page.should have_css(edit_link) + + # on calendar page there can be more than 1 occurance of a todo, so we select the first here + all(:css, edit_link)[0].click + wait_for_ajax + wait_for_animations_to_end + end + + def submit_form(form_xpath, button_name) + handle_js_confirm do + # on calendar page there can be more than 1 occurance of a todo, so we select the first here + within all(:xpath, form_xpath)[0] do + click_button(button_name) + end + wait_for_ajax + wait_for_animations_to_end + end + end + + def submit_multiple_next_action_form + submit_form("//form[@id='todo-form-multi-new-action']", "todo_multi_new_action_submit") + end + + def submit_next_action_form + submit_form("//form[@id='todo-form-new-action']", "todo_new_action_submit") + end + + def submit_new_context_form + submit_form("//form[@id='context-form']", "context_new_submit") + end + + def submit_new_project_form + submit_form("//form[@id='project_form']", "project_new_project_submit") + end + + def submit_edit_todo_form (todo) + submit_form("//div[@id='edit_todo_#{todo.id}']", "submit_todo_#{todo.id}") + wait_for_todo_form_to_go_away(todo) + end + + def wait_for_todo_form_to_go_away(todo) + page.should_not have_content("button#submit_todo_#{todo.id}") + end + + def open_project_edit_form(project) + click_link "link_edit_project_#{project.id}" + page.should have_css("button#submit_project_#{project.id}") + end + + def submit_project_edit_form(project) + page.find("button#submit_project_#{project.id}").click + end + + def edit_project_no_wait(project) + open_project_edit_form(project) + yield + submit_project_edit_form(project) + end + + def edit_project(project) + open_project_edit_form(project) + within "form#edit_form_project_#{project.id}" do + yield + end + submit_project_edit_form(project) + + wait_for_ajax + wait_for_animations_to_end + + page.should_not have_css("button#submit_project_#{project.id}", :visible => true) + end + + def edit_project_settings(project) + edit_project(project) do + yield + end + end + + def clear_context_name_from_next_action_form + execute_javascript("$('#todo_context_name').val('');") + end + + def clear_project_name_from_next_action_form + execute_javascript("$('#todo_project_name').val('');") + end + +end diff --git a/features/support/tracks_id_helper.rb b/features/support/tracks_id_helper.rb new file mode 100644 index 00000000..b5a83c60 --- /dev/null +++ b/features/support/tracks_id_helper.rb @@ -0,0 +1,39 @@ +module TracksIdHelper + + def toggle_context_container_xpath(context) + "//a[@id='toggle_c#{context.id}']" + end + + def toggle_project_container_xpath(project) + "//a[@id='toggle_p#{project.id}']" + end + + def context_container_xpath(context) + "//div[@id='c#{context.id}']" + end + + def project_container_xpath(project) + id = project.nil? ? "without_project_container" : "p#{project.id}" + "//div[@id='#{id}']" + end + + def todo_in_container_xpath(todo, container_type) + id = "wrong" + id = todo_in_context_container_xpath(todo, todo.context) if container_type == :context + id = todo_in_project_container_xpath(todo, todo.project) if container_type == :project + return "//div[@id=\"#{id}\"]//div[@id='line_todo_#{todo.id}']" + end + + def todo_in_context_container_xpath(todo, context) + "#{context_container_xpath(context)}//div[@id='line_todo_#{todo.id}']" + end + + def todo_in_project_container_xpath(todo, project) + return "#{project_container_xpath(project)}//div[@id='line_todo_#{todo.id}']" + end + + def todo_in_deferred_container_xpath(todo) + "//div[@id='deferred_pending_container']//div[@id='line_todo_#{todo.id}']" + end + +end \ No newline at end of file diff --git a/features/support/tracks_step_helper.rb b/features/support/tracks_step_helper.rb new file mode 100644 index 00000000..5e392a17 --- /dev/null +++ b/features/support/tracks_step_helper.rb @@ -0,0 +1,124 @@ +module TracksStepHelper + + def wait_until(timeout = 5) + timeout(timeout) { yield } + end + + def timeout(seconds = 1, error_message = nil, &block) + start_time = Time.now + + result = nil + + until result + return result if result = yield + + delay = seconds - (Time.now - start_time) + if delay <= 0 + raise TimeoutError, error_message || "timed out" + end + + sleep(0.05) + end + end + + def wait_for_animations_to_end + wait_until do + page.evaluate_script('$(":animated").length') == 0 + end + end + + def wait_for_ajax + start_time = Time.now + page.evaluate_script('jQuery.isReady&&jQuery.active==0').class.should_not eql(String) + until(page.evaluate_script('jQuery.isReady&&jQuery.active==0') || (start_time + 5.seconds) < Time.now) + sleep 0.05 + end + end + + def wait_for_auto_complete + page.should have_css("a.ui-state-focus", :visible => true) + end + + def click_first_line_of_auto_complete + page.find(:css, "ul li a.ui-state-focus").click + end + + def check_xpath_visibility(visible, xpath) + page.send( (visible=="see" ? :should : :should_not), have_xpath(xpath, :visible => true)) + end + + def check_css_visibility(visible, css) + page.send( (visible=="see" ? :should : :should_not), have_css(css, :visible => true)) + end + + def check_elem_visibility(visible, elem) + elem.send(visible=="see" ? :should : :should_not, be_visible) + end + + def find_todo(description) + todo = @current_user.todos.where(:description => description).first + todo.should_not be_nil + return todo + end + + def find_context(context_name) + context = @current_user.contexts.where(:name => context_name).first + context.should_not be_nil + return context + end + + def find_project(project_name) + project = @current_user.projects.where(:name => project_name).first + project.should_not be_nil + return project + end + + def context_list_find_index(context_name) + div_id = "context_#{@current_user.contexts.where(:name => context_name).first.id}" + contexts = page.all("div.context").map { |x| x[:id] } + return contexts.find_index(div_id) + end + + def project_list_find_index(project_name) + # TODO: refactor with context_list_find_index + div_id = "project_#{@current_user.projects.where(:name => project_name).first.id}" + project = page.all("div.project").map { |x| x[:id] } + return project.find_index(div_id) + end + + def format_date(date) + # copy-and-past from ApplicationController::format_date + return date ? date.in_time_zone(@current_user.prefs.time_zone).strftime("#{@current_user.prefs.date_format}") : '' + end + + def execute_javascript(js) + page.execute_script(js) + end + + def open_submenu_for(todo) + submenu_arrow = "div#line_todo_#{todo.id} img.todo-submenu" + page.should have_css(submenu_arrow, :visible=>true) + + page.find(submenu_arrow, :match => :first).click + + page.should have_css("div#line_todo_#{todo.id} ul#ultodo_#{todo.id}", :visible => true) + + within all("div#line_todo_#{todo.id} ul#ultodo_#{todo.id}")[0] do + yield + end + end + + def handle_js_confirm(accept=true) + page.execute_script "window.original_confirm_function = window.confirm" + page.execute_script "window.confirmMsg = null" + page.execute_script "window.confirm = function(msg) { window.confirmMsg = msg; return #{!!accept}; }" + yield + ensure + page.execute_script "window.confirm = window.original_confirm_function" + end + + def get_confirm_text + page.evaluate_script "window.confirmMsg" + end + +end \ No newline at end of file diff --git a/features/support/world.rb b/features/support/world.rb index e099ff6e..d76d6896 100644 --- a/features/support/world.rb +++ b/features/support/world.rb @@ -1,179 +1,3 @@ -module TracksStepHelper - - def wait_until(timeout = 5) - timeout(timeout) { yield } - end - - def timeout(seconds = 1, error_message = nil, &block) - start_time = Time.now - - result = nil - - until result - return result if result = yield - - delay = seconds - (Time.now - start_time) - if delay <= 0 - raise TimeoutError, error_message || "timed out" - end - - sleep(0.05) - end - end - - def open_edit_form_for(todo) - edit_link = "div#line_todo_#{todo.id} a#icon_edit_todo_#{todo.id}" - - # make sure we can open the edit form - page.should have_css(edit_link) - - # on calendar page there can be more than 1 occurance of a todo, so we select the first here - all(:css, edit_link)[0].click - wait_for_ajax - wait_for_animations_to_end - end - - def submit_form(form_xpath, button_name) - handle_js_confirm do - # on calendar page there can be more than 1 occurance of a todo, so we select the first here - within all(:xpath, form_xpath)[0] do - click_button(button_name) - end - wait_for_ajax - wait_for_animations_to_end - end - end - - def submit_multiple_next_action_form - submit_form("//form[@id='todo-form-multi-new-action']", "todo_multi_new_action_submit") - end - - def submit_next_action_form - submit_form("//form[@id='todo-form-new-action']", "todo_new_action_submit") - end - - def submit_new_context_form - submit_form("//form[@id='context-form']", "context_new_submit") - end - - def submit_new_project_form - submit_form("//form[@id='project_form']", "project_new_project_submit") - end - - def submit_edit_todo_form (todo) - submit_form("//div[@id='edit_todo_#{todo.id}']", "submit_todo_#{todo.id}") - wait_for_todo_form_to_go_away(todo) - end - - def wait_for_todo_form_to_go_away(todo) - page.should_not have_content("button#submit_todo_#{todo.id}") - end - - def open_project_edit_form(project) - click_link "link_edit_project_#{project.id}" - page.should have_css("button#submit_project_#{project.id}") - end - - def submit_project_edit_form(project) - page.find("button#submit_project_#{project.id}").click - end - - def edit_project_no_wait(project) - open_project_edit_form(project) - yield - submit_project_edit_form(project) - end - - def edit_project(project) - open_project_edit_form(project) - within "form#edit_form_project_#{project.id}" do - yield - end - submit_project_edit_form(project) - - wait_for_ajax - wait_for_animations_to_end - - page.should_not have_css("button#submit_project_#{project.id}", :visible => true) - end - - def edit_project_settings(project) - edit_project(project) do - yield - end - end - - def open_submenu_for(todo) - submenu_arrow = "div#line_todo_#{todo.id} img.todo-submenu" - page.should have_css(submenu_arrow, :visible=>true) - - # pick the first because calendar page could have the same todo more than once - page.all(submenu_arrow)[0].click - - page.should have_css("div#line_todo_#{todo.id} ul#ultodo_#{todo.id}", :visible => true) - - within all("div#line_todo_#{todo.id} ul#ultodo_#{todo.id}")[0] do - yield - end - end - - def context_list_find_index(context_name) - div_id = "context_#{@current_user.contexts.where(:name => context_name).first.id}" - contexts = page.all("div.context").map { |x| x[:id] } - return contexts.find_index(div_id) - end - - def project_list_find_index(project_name) - # TODO: refactor with context_list_find_index - div_id = "project_#{@current_user.projects.where(:name => project_name).first.id}" - project = page.all("div.project").map { |x| x[:id] } - return project.find_index(div_id) - end - - def wait_for_animations_to_end - wait_until do - page.evaluate_script('$(":animated").length') == 0 - end - end - - def wait_for_ajax - start_time = Time.now - page.evaluate_script('jQuery.isReady&&jQuery.active==0').class.should_not eql(String) - until(page.evaluate_script('jQuery.isReady&&jQuery.active==0') || (start_time + 5.seconds) < Time.now) - sleep 0.25 - end - end - - def format_date(date) - # copy-and-past from ApplicationController::format_date - return date ? date.in_time_zone(@current_user.prefs.time_zone).strftime("#{@current_user.prefs.date_format}") : '' - end - - def execute_javascript(js) - page.execute_script(js) - end - - def clear_context_name_from_next_action_form - execute_javascript("$('#todo_context_name').val('');") - end - - def clear_project_name_from_next_action_form - execute_javascript("$('#todo_project_name').val('');") - end - - def handle_js_confirm(accept=true) - page.execute_script "window.original_confirm_function = window.confirm" - page.execute_script "window.confirmMsg = null" - page.execute_script "window.confirm = function(msg) { window.confirmMsg = msg; return #{!!accept}; }" - yield - ensure - page.execute_script "window.confirm = window.original_confirm_function" - end - - def get_confirm_text - page.evaluate_script "window.confirmMsg" - end - -end - -World(TracksStepHelper) \ No newline at end of file +World(TracksStepHelper) +World(TracksFormHelper) +World(TracksIdHelper) \ No newline at end of file diff --git a/features/toggle_containers.feature b/features/toggle_containers.feature index 3690cf16..ce01b982 100644 --- a/features/toggle_containers.feature +++ b/features/toggle_containers.feature @@ -52,9 +52,9 @@ Feature: Toggle the containers | test 3 | @boss | And I have selected the view for group by project When I go to the home page - Then I should see "test 1" in the project container for "collapse those containers" - And I should see "test 2" in the project container for "collapse those containers" - And I should see "test 3" in the project container for "collapse those containers" + Then I should see "test 1" in the project container of "collapse those containers" + And I should see "test 2" in the project container of "collapse those containers" + And I should see "test 3" in the project container of "collapse those containers" When I collapse the project container of "collapse those containers" Then I should not see the todo "test 1" And I should not see the todo "test 2" @@ -100,8 +100,8 @@ Feature: Toggle the containers | test 2 | @ipad | And I have selected the view for group by project When I go to the home page - Then I should see "test 1" in the project container for "collapse those containers" - And I should see "test 2" in the project container for "collapse those other containers" + Then I should see "test 1" in the project container of "collapse those containers" + And I should see "test 2" in the project container of "collapse those other containers" When I collapse the project container of "collapse those containers" Then I should not see the todo "test 1" And I should see the todo "test 2"