Added tests to enforce business rules for editing an epic story.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/epics_controller.rb | 50 +++++++++++++-
app/views/epics/index.html.erb | 7 ++-
doc/ChangeLog | 1 +
test/functional/epics_controller_test.rb | 111 ++++++++++++++++++++++++++++++
4 files changed, 165 insertions(+), 4 deletions(-)
diff --git a/app/controllers/epics_controller.rb b/app/controllers/epics_controller.rb
index 1c662ea..55aadcb 100644
--- a/app/controllers/epics_controller.rb
+++ b/app/controllers/epics_controller.rb
@@ -16,8 +16,9 @@
# +EpicsController+ allows users to work with +Epic+ stories.
class EpicsController < ApplicationController
- before_filter :authenticated, :only => [:new, :create]
- before_filter :load_project, :only => [:index, :new, :create]
+ before_filter :authenticated, :only => [:new, :edit, :create, :update]
+ before_filter :load_project
+ before_filter :load_epic, :only => [:edit, :update]
# GET /projects/1/epics
def index
@@ -45,10 +46,17 @@ class EpicsController < ApplicationController
end
end
+ # GET /projects/1/epics/1/edit
def edit
+ if @project.can_edit_epics?(@user)
+ @title = "Edit epic for #{(a)project.name}"
+ else
+ flash[:error] = "You are not authorized to edit epics for this project."
+ redirect_to project_path(@project)
+ end
end
- # POST /proces/1/epics
+ # POST /projects/1/epics
def create
respond_to do |format|
if @project.can_edit_epics?(@user)
@@ -70,7 +78,26 @@ class EpicsController < ApplicationController
end
end
+ # PUT /projects/1/epics/1
def update
+ respond_to do |format|
+ if @project.can_edit_epics?(@user)
+ Epic.transaction do
+ @epic.update_attributes(params[:epic])
+ if @epic.save
+ flash[:message] = "Epic was updated."
+ format.html { redirect_to project_epic_path(@project, @epic) }
+ else
+ @title = "Edit epic for #{(a)project.name}"
+ @epic.valid?
+ format.html { render :action => :edit }
+ end
+ end
+ else
+ flash[:message] = "You are not authorized to update epics for this
project."
+ format.html { redirect_to project_epic_path(@project, @epic) }
+ end
+ end
end
def destroy
@@ -87,4 +114,21 @@ class EpicsController < ApplicationController
end
end
end
+
+ def load_epic
+ @epic = Epic.find_by_id(params[:id])
+ if @epic
+ unless @epic.project_id == @project.id
+ respond_to do |format|
+ flash[:error] = "The epic requested does not belong to the project
specified."
+ format.html { redirect_to error_path }
+ end
+ end
+ else
+ respond_to do |format|
+ format[:error] = "Invalid or missing epic id."
+ format.html { redirect_to error_path }
+ end
+ end
+ end
end
diff --git a/app/views/epics/index.html.erb b/app/views/epics/index.html.erb
index 5baf843..9ff7974 100644
--- a/app/views/epics/index.html.erb
+++ b/app/views/epics/index.html.erb
@@ -28,7 +28,12 @@
<td><%= epic.title %></td>
<td><%= epic.user_stories.size %></td>
<td><%= show_date epic.created_at, true %></td>
- <td></td>
+ <td>
+ <% if @project.can_edit_epics?(@user) %>
+ <%= link_to(image_tag("/images/icons/edit.png", :title => "Edit
this epic story..."),
+ edit_project_epic_path(@project, epic)) %>
+ <% end %>
+ </td>
</tr>
<% end %>
</tbody>
diff --git a/doc/ChangeLog b/doc/ChangeLog
index d22f359..640ee02 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -25,5 +25,6 @@ Change Log (0.2.0):
* #142 - The product owner can populate the sprint team.
* #143 - Only sprint team members can accept sprint items.
* #147 - Project owners can write new epic stories.
+ * #148 - Project owners can edit epics stories.
* #152 - Users can view all epic stories for a project.
diff --git a/test/functional/epics_controller_test.rb
b/test/functional/epics_controller_test.rb
index 1df9485..c095704 100644
--- a/test/functional/epics_controller_test.rb
+++ b/test/functional/epics_controller_test.rb
@@ -24,6 +24,11 @@ class EpicsControllerTest < ActionController::TestCase
def setup
@project = projects(:projxp)
@owner = @project.owner
+ @epic = epics(:user_stories_epic)
+ raise "Epic is not in this project!" unless @epic.project_id ==
@project.id
+
+ @other_project = projects(:teatime)
+ @other_owner = @other_project.owner
@nonowner = users(:mcpierce)
raise "Nonowner and owner cannot be the same user!" if @owner.id ==
@nonowner.id
@@ -112,4 +117,110 @@ class EpicsControllerTest < ActionController::TestCase
assert result, "The new epic was not saved."
assert_redirected_to project_epic_path(@project, result)
end
+
+ # Ensures that anonymous users cannot edit epics.
+ def test_edit_as_anonymous
+ get :edit
+
+ assert_redirected_to login_path
+ end
+
+ # Ensures that a valid project is required.
+ def test_edit_with_invalid_project
+ get :edit, { }, {:user_id => @owner.id}
+
+ assert_redirected_to error_path
+ end
+
+ # Ensures that a valid epic id is required.
+ def test_edit_with_invalid_epic
+ get :edit, {:project_id => @project.id}, {:user_id => @owner.id}
+
+ assert_redirected_to error_path
+ end
+
+ # Ensures that the epic and project must be a match.
+ def test_edit_with_epic_project_mismatch
+ get :edit, {:id => @epic.id, :project_id => @other_project.id}, {:user_id =>
@other_owner.id}
+
+ assert_redirected_to error_path
+ end
+
+ # Ensures that a non-owner cannot edit an epic.
+ def test_edit_as_nonowner
+ get :edit, {:id => @epic.id, :project_id => @project.id}, {:user_id =>
@nonowner.id}
+
+ assert_redirected_to project_path(@project)
+ end
+
+ # Ensures that editing loads the epic story correctly.
+ def test_edit
+ get :edit, {:id => @epic.id, :project_id => @project.id}, {:user_id =>
@owner.id}
+
+ assert_response :success
+ assert assigns['epic'], "Failed to load the epic."
+ assert_equal @epic.id, assigns['epic'].id, "Failed to load the correct
epic."
+ end
+
+ # Ensures that anonymous users cannot update epics.
+ def test_update_as_anonymous
+ put :update
+
+ assert_redirected_to login_path
+ end
+
+ # Ensures that a valid project is required.
+ def test_update_with_invalid_project
+ put :update, { }, {:user_id => @owner.id}
+
+ assert_redirected_to error_path
+ end
+
+ # Ensures that a valid epic id is required.
+ def test_update_with_invalid_epic
+ put :update, {:project_id => @project.id}, {:user_id => @owner.id}
+
+ assert_redirected_to error_path
+ end
+
+ # Ensures that the epic belongs to the specified project.
+ def test_update_with_epic_project_mismatch
+ put :update, {:project_id => @other_project.id, :id => @epic.id}, {:user_id
=> @other_owner.id}
+
+ assert_redirected_to error_path
+ end
+
+ # Ensures that only the project owner can update an epic.
+ def test_update_as_nonowner
+ put :update,
+ {:project_id => @project.id, :id => @epic.id, :epic => {:title =>
"test"}},
+ {:user_id => @nonowner.id}
+
+ assert_redirected_to project_epic_path(@project, @epic)
+ result = Epic.find_by_id((a)epic.id)
+ assert_equal @epic.title, result.title, "Epic should not have been
updated."
+ end
+
+ # Ensures that a malformed epic sends the user back to the edit page.
+ def test_update_with_invalid_epic
+ put :update,
+ {:project_id => @project.id,:id => @epic.id, :epic => {:title =>
''}},
+ {:user_id => @owner.id}
+
+ assert_response :success
+ assert_template "edit"
+ result = Epic.find_by_id((a)epic.id)
+ assert_equal @epic.title, result.title, "Epic should not have been
updated."
+ end
+
+ # Ensures that epics are updated as expected.
+ def test_update
+ put :update,
+ {:project_id => @project.id, :id => @epic.id, :epic => {:title =>
"test"}},
+ {:user_id => @owner.id}
+
+ assert_redirected_to project_epic_path(@project, @epic)
+ result = Epic.find_by_id((a)epic.id)
+ assert_equal "test", result.title, "Epic was not updated as
expected."
+ end
end
--
1.6.0.6