Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/backlog_controller.rb | 1 +
app/controllers/task_controller.rb | 127 ------------
app/controllers/tasks_controller.rb | 167 ++++++++++++++++
app/helpers/application_helper.rb | 9 -
app/models/task.rb | 51 ++++--
app/views/backlog/view.html.erb | 66 +------
app/views/task/_edit.html.erb | 47 -----
app/views/task/create.html.erb | 3 -
app/views/task/modify.html.erb | 1 -
app/views/tasks/_edit.html.erb | 52 +++++
app/views/tasks/_list.html.erb | 34 ++++
app/views/tasks/index.html.erb | 1 +
app/views/tasks/modify.html.erb | 1 +
app/views/tasks/new.html.erb | 3 +
app/views/tasks/show.html.erb | 35 ++++
config/routes.rb | 5 +
test/functional/task_controller_test.rb | 233 ----------------------
test/functional/tasks_controller_test.rb | 313 ++++++++++++++++++++++++++++++
test/unit/product_test.rb | 3 +-
19 files changed, 650 insertions(+), 502 deletions(-)
delete mode 100644 app/controllers/task_controller.rb
create mode 100644 app/controllers/tasks_controller.rb
delete mode 100644 app/views/task/_edit.html.erb
delete mode 100644 app/views/task/create.html.erb
delete mode 100644 app/views/task/modify.html.erb
create mode 100644 app/views/tasks/_edit.html.erb
create mode 100644 app/views/tasks/_list.html.erb
create mode 100644 app/views/tasks/index.html.erb
create mode 100644 app/views/tasks/modify.html.erb
create mode 100644 app/views/tasks/new.html.erb
create mode 100644 app/views/tasks/show.html.erb
delete mode 100644 test/functional/task_controller_test.rb
create mode 100644 test/functional/tasks_controller_test.rb
diff --git a/app/controllers/backlog_controller.rb
b/app/controllers/backlog_controller.rb
index 3e6ca56..6011264 100644
--- a/app/controllers/backlog_controller.rb
+++ b/app/controllers/backlog_controller.rb
@@ -28,6 +28,7 @@ class BacklogController < ApplicationController
@task = Task.new
@task.primary = @user if @user
@users = User.find(:all, :conditions => "id in (select user_id from
product_roles where product_id = #{(a)product.id})")
+ @tasks = @backlog_item.tasks
end
def modify
diff --git a/app/controllers/task_controller.rb b/app/controllers/task_controller.rb
deleted file mode 100644
index 6c6e42b..0000000
--- a/app/controllers/task_controller.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-# task_controller.rb
-# Copyright (C) 2008, Darryl L. Pierce <mcpierce(a)gmail.com>
-#
-# This program is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <
http://www.gnu.org/licenses/>.
-#
-
-# +TaskController+ allows the user to create and modify tasks for a backlog
-# item.
-#
-class TaskController < ApplicationController
- before_filter :authenticated, :except => [:view]
- before_filter :load_backlog_item, :only => [:create]
- before_filter :load_task, :only => [:modify, :delete]
- before_filter :authorized_to_create, :only => [:create]
- before_filter :authorized_to_manage, :only => [:modify, :delete]
- before_filter :before_edit, :only => [:create, :modify]
- before_filter :ensure_sprint_is_active, :only => [:create]
-
- def create
- if request.post?
- begin
- Task.transaction do
- @task = Task.create(params[:task])
- @task.backlog_item = @backlog_item
- @backlog_item.tasks << @task
- @backlog_item.save!
- @task.save!
-
- redirect_to :controller => :backlog, :action => :view, :id =>
@backlog_item
- end
-
- rescue ActiveRecord::RecordInvalid => error
- flash[:message] = error.message
- @task.valid?
- render :action => :create
- end
- else
- @task = Task.new(:backlog_item => @backlog_item, :primary => @user)
- end
- end
-
- def modify
- if request.post?
- @task.update_attributes(params[:task])
-
- @task.save
-
- redirect_to :controller => :backlog, :action => :view, :id =>
@task.backlog_item.id
- end
- end
-
- def delete
- if request.post?
- begin
- Task.transaction do
- @task.destroy
- end
-
- redirect_to :controller => :backlog, :action => :view, :id =>
@backlog_item.id
-
- rescue Exception => error
- flash[:message] = error.message
-
- redirect_to error_path
- end
- else
- redirect_to :controller => :backlog, :action => :view, :id =>
@backlog_item.id
- end
- end
-
- private
-
- def load_backlog_item
- @backlog_item = BacklogItem.find_by_id(params[:backlog_item])
-
- unless @backlog_item
- flash[:message] = 'Invalid user id.'
- redirect_to error_path
- end
- end
-
- def load_task
- @task = Task.find_by_id(params[:id])
- @backlog_item = @task.backlog_item if @task
-
- unless @task
- flash[:message] = 'Invalid task id.'
- redirect_to error_path
- end
- end
-
- def authorized_to_create
- unless TaskHelper.can_create_task(@user,@backlog_item)
- flash[:message] = 'You are not authorized to work on tasks for this user
story.'
- redirect_to :controller => :backlog, :action => :view, :id =>
@backlog_item.id
- end
- end
-
- def authorized_to_manage
- unless TaskHelper.can_manage_task(@user,@task)
- flash[:message] = 'You are not authorized to modify this task.'
- redirect_to :controller => :backlog, :action => :view, :id =>
@task.backlog_item.id
- end
- end
-
- def before_edit
- @users = User.find(:all, :order => 'display_name ASC')
- end
-
- def ensure_sprint_is_active
- unless @backlog_item.sprint.status == Sprint::STATUS_ACTIVE
- flash[:message] = 'The sprint must be active for that action.'
- redirect_to :controller => :backlog, :action => :view, :id =>
@backlog_item.id
- end
- end
-end
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
new file mode 100644
index 0000000..dda739c
--- /dev/null
+++ b/app/controllers/tasks_controller.rb
@@ -0,0 +1,167 @@
+# tasks_controller.rb
+# Copyright (C) 2008, Darryl L. Pierce <mcpierce(a)gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <
http://www.gnu.org/licenses/>.
+#
+
+# +TasksController+ allows the user to create and modify tasks for a backlog
+# item.
+#
+class TasksController < ApplicationController
+ before_filter :authenticated, :except => [:index, :show]
+ before_filter :load_backlog_item, :only => [:index, :new, :create]
+ before_filter :load_task, :only => [:show, :edit, :update, :delete]
+ before_filter :before_edit, :only => [:create, :modify]
+ before_filter :ensure_sprint_is_active, :only => [:create]
+
+ # GET /tasks
+ def index
+ @tasks = Task.find_all_by_backlog_item_id((a)backlog_item.id)
+
+ respond_to do |format|
+ format.html
+ end
+ end
+
+ # GET /tasks/1
+ def show
+ respond_to do |format|
+ format.html
+ end
+ end
+
+ # GET /tasks/new
+ def new
+ if @backlog_item.user_can_add_tasks?(@user)
+ @task = Task.new(
+ :backlog_item_id => @backlog_item.id,
+ :primary_id => @user.id
+ )
+ @users = User.find(:all, :order => 'display_name ASC')
+ else
+ flash[:error] = 'You are not allowed to add tasks to this backlog item.'
+ redirect_to :controller => :backlog, :action => :view, :id =>
@backlog_item
+ end
+ end
+
+ # GET /tasks/1;edit
+ def edit
+ unless @task.user_can_edit?(@user)
+ flash[:error] = "You are not allowd to edit this task."
+ redirect_to :controller => :backlog, :action => :view, :id =>
@backlog_item
+ end
+ @users = User.find(:all, :order => 'display_name ASC')
+ end
+
+ # POST /tasks
+ def create
+ if @backlog_item.user_can_add_tasks?(@user)
+ Task.transaction do
+ @task = Task.new(params[:task])
+ @task.backlog_item = @backlog_item
+
+ respond_to do |format|
+ if @task.save
+ flash[:message] = "Recorded #{(a)task.hours} against this backlog
item."
+ format.html { redirect_to :controller => :backlog, :action => :view,
:id => @backlog_item }
+ else
+ format.html { render :action => 'new' }
+ end
+ end
+ end
+ else
+ flash[:error] = "You are not allowed to add tasks to this backlog item."
+ redirect_to :controller => :backlog, :action => :view, :id =>
@backlog_item
+ end
+ end
+
+ # PUT /tasks/1
+ def update
+ if @task.user_can_edit?(@user)
+ begin
+ Task.transaction do
+ @task.update_attributes(params[:task])
+ @task.save!
+ end
+
+ flash[:message] = "Task updated."
+ rescue Exception => error
+ flash[:error] = "ERROR: #{error.message}"
+ end
+
+ respond_to do |format|
+ format.html { redirect_to :controller => :backlog, :action => :view, :id
=> @backlog_item}
+ end
+ else
+ flash[:error] = "You are not allowed to update that task."
+
+ @task.valid?
+
+ respond_to do |format|
+ format.html { render :action => :edit }
+ end
+ end
+ end
+
+ # DELETE /tasks/1
+ def delete
+ if @task.user_can_delete?(@user)
+ begin
+ Task.transaction do
+ @task.destroy
+ end
+
+ redirect_to :controller => :backlog, :action => :view, :id =>
@backlog_item
+ rescue Exception => error
+ flash[:error] = "ERROR: #{error.message}"
+ redirect_to error_url
+ end
+ else
+ flash[:error] = 'You are not allowed to delete this task.'
+ redirect_to :controller => :backlog, :action => :view, :id =>
@backlog_item
+ end
+ end
+
+ private
+
+ def load_backlog_item
+ @backlog_item = BacklogItem.find_by_id(params[:backlog_item])
+
+ unless @backlog_item
+ flash[:message] = 'Invalid user id.'
+ redirect_to error_path
+ end
+ end
+
+ def load_task
+ @task = Task.find_by_id(params[:id])
+ @backlog_item = @task.backlog_item if @task
+
+ unless @task
+ flash[:message] = 'Invalid task id.'
+ redirect_to error_path
+ end
+ end
+
+ def before_edit
+ @users = User.find(:all, :order => 'display_name ASC')
+ end
+
+ def ensure_sprint_is_active
+ unless @backlog_item.sprint.status == Sprint::STATUS_ACTIVE
+ flash[:message] = 'The sprint must be active for that action.'
+ redirect_to :controller => :backlog, :action => :view, :id =>
@backlog_item.id
+ end
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index f20df88..96d59a7 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -102,15 +102,6 @@ module ApplicationHelper
:id => backlog_item.id)
end
- # Creates a link to a task.
- #
- def link_to_task(task, options = {})
- @template.link_to(options[:text] ? options[:text] : task.id,
- :controller => :task,
- :action => options[:action] ? options[:action] : :view,
- :id => task.id)
- end
-
# Shows the hours for a given object as estimated, actual and remaining.
#
def show_hours_as_ear(estimated)
diff --git a/app/models/task.rb b/app/models/task.rb
index 89af73d..b518364 100644
--- a/app/models/task.rb
+++ b/app/models/task.rb
@@ -1,22 +1,22 @@
# task.rb
# Copyright (C) 2008, Darryl L. Pierce <mcpierce(a)gmail.com>
#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <
http://www.gnu.org/licenses/>.
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <
http://www.gnu.org/licenses/>.
#
# A +Task+ represents a single piece of work associated with a +UserStory+.
-# Tasks have a primary developer, and an optional backup developer.
+# Tasks have a primary developer, and an optional backup developer.
class Task < ActiveRecord::Base
validates_presence_of :backlog_item_id
@@ -24,16 +24,33 @@ class Task < ActiveRecord::Base
belongs_to :backup, :class_name => 'User', :foreign_key =>
'backup_id'
validates_presence_of :description,
- :message => 'You need to describe this task.'
+ :message => 'You need to describe this task.'
validates_length_of :description,
- :maximum => 1000,
- :too_long => 'Please shorten the description.'
+ :maximum => 1000,
+ :too_long => 'Please shorten the description.'
validates_presence_of :hours,
- :message => 'You must report the hours worked on this
task.'
+ :message => 'You must report the hours worked on this task.'
validates_numericality_of :hours,
- :greater_than => 0,
- :message => 'Hours must be numeric and greater than
0.'
+ :greater_than => 0,
+ :message => 'Hours must be numeric and greater than 0.'
belongs_to :backlog_item
+
+ # Returns whether the user can edit the task.
+ #
+ def user_can_edit?(user)
+ user &&
+ backlog_item.sprint.active? &&
+ ((primary && (primary.id == user.id)) ||
+ (backup && backup.id == user.id))
+ end
+
+ # Returns whether the user can delete the task or not.
+ #
+ def user_can_delete?(user)
+ user &&
+ (backlog_item.owner && (backlog_item.owner.id == user.id)) &&
+ backlog_item.sprint.active?
+ end
end
diff --git a/app/views/backlog/view.html.erb b/app/views/backlog/view.html.erb
index c02f27e..8ee0333 100644
--- a/app/views/backlog/view.html.erb
+++ b/app/views/backlog/view.html.erb
@@ -63,67 +63,5 @@
</tbody>
</table>
-<table class="list">
- <colgroup>
- <col class="row_id" />
- <col class="description" />
- <col class="user" />
- <col class="user" />
- <col class="hours" />
- <col class="date" />
- <col class="actions" />
- </colgroup>
-
- <thead>
- <tr>
- <th colspan="7" class="title">Tasks</th>
- </tr>
- <tr>
- <th>##</th>
- <th>Description</th>
- <th>Primary</th>
- <th>Backup</th>
- <th>Hours</th>
- <th>Date</th>
- <th>Action</th>
- </tr>
- </thead>
-
- <tbody>
-
- <% if @backlog_item.user_can_add_tasks?(@user) %>
- <% form_for :task, :url => {:controller => :task, :action => :create}
do |form| %>
- <%= hidden_field_tag :backlog_item, @backlog_item.id %>
- <tr>
- <td></td>
- <td><%= form.text_field :description %></td>
- <td><%= collection_select :task, :primary_id, @users, :id,
- :display_name, {:include_blank => true} %></td>
- <td><%= collection_select :task, :backup_id, @users, :id,
- :display_name, {:include_blank => true} %></td>
- <td><%= form.text_field :hours %></td>
- <td><%= form.date_select :when %></td>
- <td><%= submit_tag "Create" %></td>
- </tr>
- <% end %>
- <% end %>
-
- <% @backlog_item.tasks.each_with_index do |task,i| %>
- <tr class="<% row_class = i%2 == 0 ? 'even' : 'odd'
%>">
-
- <td><%= link_to_task task, :action => :modify %></td>
- <td><%= simple_format task.description %></td>
- <td><%= link_to_user task.primary %></td>
- <td><%= link_to_user task.backup %></td>
- <td><%= task.hours %></td>
- <td><%= task.when.to_s(:date) %></td>
- <td>
- <% form_for :task, :url => {:controller => :task, :action =>
:delete} do |f| %>
- <%= hidden_field_tag :id, task.id %>
- <%= submit_tag "Delete" %>
- <% end %>
- </td>
- </tr>
- <% end %>
- </tbody>
-</table>
+<%= link_to "Add Task", new_task_path(:backlog_item => @backlog_item)
%>
+<%= render(:partial => 'tasks/list', :object => @backlog_item.tasks)
%>
diff --git a/app/views/task/_edit.html.erb b/app/views/task/_edit.html.erb
deleted file mode 100644
index 4195c45..0000000
--- a/app/views/task/_edit.html.erb
+++ /dev/null
@@ -1,47 +0,0 @@
-<div>
- <% form_for :task do |form| %>
-
- <%= hidden_field_tag :backlog_item, @task.backlog_item.id %>
-
- <table class="edit">
- <tbody>
- <tr>
- <td class="label">Primary:</td>
- <td class="value">
- <%= collection_select :task, :primary_id, @users, :id,
- :display_name, {:include_blank => true} %>
- </td>
- </tr>
-
- <tr>
- <td class="label">Backup:</td>
- <td class="value">
- <%= collection_select :task, :backup_id, @users, :id,
- :display_name, {:include_blank => true} %>
- </td>
- </tr>
-
- <tr>
- <td class="label">Hours:</td>
- <td class="value"><%= form.text_field :hours
%></td>
- </tr>
-
- <tr>
- <td class="label">Description:</td>
- <td class="value"><%= form.text_area :description
%></td>
- </tr>
-
- <tr>
- <td class="buttons" colspan="2">
- <% if @task.new_record? %>
- <%= submit_tag "Create", :class => 'button' %>
- <% else %>
- <%= submit_tag "Update", :class => 'button' %>
- <% end %>
- </td>
- </tr>
- </tbody>
- </table>
-
- <% end %>
-</div>
\ No newline at end of file
diff --git a/app/views/task/create.html.erb b/app/views/task/create.html.erb
deleted file mode 100644
index ad1a69b..0000000
--- a/app/views/task/create.html.erb
+++ /dev/null
@@ -1,3 +0,0 @@
-<div>
- <%= render :partial => 'edit', :object => @task %>
-</div>
\ No newline at end of file
diff --git a/app/views/task/modify.html.erb b/app/views/task/modify.html.erb
deleted file mode 100644
index e536180..0000000
--- a/app/views/task/modify.html.erb
+++ /dev/null
@@ -1 +0,0 @@
-<%= render :partial => "edit", :object => @task %>
diff --git a/app/views/tasks/_edit.html.erb b/app/views/tasks/_edit.html.erb
new file mode 100644
index 0000000..8fa5ad1
--- /dev/null
+++ b/app/views/tasks/_edit.html.erb
@@ -0,0 +1,52 @@
+<div>
+ <% form_for(:task, @task, :url => tasks_path) do |form| %>
+
+ <%= hidden_field_tag :backlog_item, @task.backlog_item.id %>
+
+ <table class="edit">
+ <tbody>
+ <tr>
+ <td class="label">When</td>
+ <td class="value"><%= form.date_select :when
%></td>
+ </tr>
+
+ <tr>
+ <td class="label">Primary</td>
+ <td class="value">
+ <%= collection_select :task, :primary_id, @users, :id,
+ :display_name, {:include_blank => true} %>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="label">Backup</td>
+ <td class="value">
+ <%= collection_select :task, :backup_id, @users, :id,
+ :display_name, {:include_blank => true} %>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="label">Hours</td>
+ <td class="value"><%= form.text_field :hours
%></td>
+ </tr>
+
+ <tr>
+ <td class="label">Description</td>
+ <td class="value"><%= form.text_area :description
%></td>
+ </tr>
+
+ <tr>
+ <td class="buttons" colspan="2">
+ <% if @task.new_record? %>
+ <%= submit_tag "Create", :class => 'button' %>
+ <% else %>
+ <%= submit_tag "Update", :class => 'button' %>
+ <% end %>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <% end %>
+</div>
diff --git a/app/views/tasks/_list.html.erb b/app/views/tasks/_list.html.erb
new file mode 100644
index 0000000..3571b09
--- /dev/null
+++ b/app/views/tasks/_list.html.erb
@@ -0,0 +1,34 @@
+<table class="list">
+ <thead>
+ <tr>
+ <th>Date</th>
+ <th>Description</th>
+ <th>Primary</th>
+ <th>Backup</th>
+ <th>Hours</th>
+ <th>Actions</th>
+ </tr>
+ </thead>
+
+ <tbody>
+ <% @tasks.each_with_index do |task, index| %>
+ <% row_class = index%2 == 0 ? 'even' : 'odd' %>
+ <tr class="<%= row_class %>">
+ <td><%= task.when %></td>
+ <td><%= simple_format task.description %></td>
+ <td><%= link_to_user task.primary %></td>
+ <td><%= link_to_user task.backup %></td>
+ <td><%= format "%0.2f", task.hours %>
+ <td>
+ <%= link_to "View", task_path(task) %>
+ <% if task.user_can_edit?(@user) %>
+ <%= link_to "Edit", edit_task_path(task) %>
+ <% end %>
+ <% if task.user_can_delete?(@user) %>
+ <%= link_to "Delete", task_path(task), :config => "Are
you sure?", :method => :delete %>
+ <% end %>
+ </td>
+ </tr>
+ <% end %>
+ </tbody>
+</table>
diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb
new file mode 100644
index 0000000..0a9c778
--- /dev/null
+++ b/app/views/tasks/index.html.erb
@@ -0,0 +1 @@
+<%= render(:partial => 'list') %>
diff --git a/app/views/tasks/modify.html.erb b/app/views/tasks/modify.html.erb
new file mode 100644
index 0000000..e536180
--- /dev/null
+++ b/app/views/tasks/modify.html.erb
@@ -0,0 +1 @@
+<%= render :partial => "edit", :object => @task %>
diff --git a/app/views/tasks/new.html.erb b/app/views/tasks/new.html.erb
new file mode 100644
index 0000000..ad1a69b
--- /dev/null
+++ b/app/views/tasks/new.html.erb
@@ -0,0 +1,3 @@
+<div>
+ <%= render :partial => 'edit', :object => @task %>
+</div>
\ No newline at end of file
diff --git a/app/views/tasks/show.html.erb b/app/views/tasks/show.html.erb
new file mode 100644
index 0000000..fb0cfb9
--- /dev/null
+++ b/app/views/tasks/show.html.erb
@@ -0,0 +1,35 @@
+<table class="details">
+ <tr>
+ <td class="label">Description:</td>
+ <td class="value"><%= simple_format @task.description
%></td>
+ </tr>
+
+ <tr>
+ <td class="label">When:</td>
+ <td class="value"><%= @task.when %></td>
+ </tr>
+
+ <tr>
+ <td class="label">Hours:</td>
+ <td class="value"><%= format "%0.2f", @task.hours
%></td>
+ </tr>
+
+ <tr>
+ <td class="label">Primary:</td>
+ <td class="value"><%= link_to_user @task.primary %></td>
+ </tr>
+
+ <tr>
+ <td class="label">Backup:</td>
+ <td class="label"><%= link_to_user @task.backup %></td>
+ </tr>
+
+</table>
+
+<%= link_to "Back", :controller => :backlog, :action => :view, :id
=> @task.backlog_item %>
+<% if @task.user_can_edit?(@user) %>
+ <% link_to "Edit", edit_task_path(@task) %>
+<% end %>
+<% if @task.user_can_delete?(@user) %>
+ <%= link_to "Delete", task_path(@task), :confirm => "Are you
sure?", :method => :delete %>
+<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index 874f8e9..2f66a65 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -16,10 +16,15 @@
#
ActionController::Routing::Routes.draw do |map|
+ map.resources :tasks
+
# You can have the root of your site routed with map.root -- just remember to
# delete public/index.html.
map.root :controller => 'project'
+ # Login URL
+ map.login "/login", :controller => 'home', :action =>
'login'
+
# Error handling
map.error "/error", :controller => 'home', :action =>
'error'
diff --git a/test/functional/task_controller_test.rb
b/test/functional/task_controller_test.rb
deleted file mode 100644
index 92551da..0000000
--- a/test/functional/task_controller_test.rb
+++ /dev/null
@@ -1,233 +0,0 @@
-# task_controller_test.rb
-# Copyright (C) 2008, Darryl L. Pierce <mcpierce(a)gmail.com>
-#
-# This program is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <
http://www.gnu.org/licenses/>.
-#
-
-require File.dirname(__FILE__) + '/../test_helper'
-
-class TaskControllerTest < ActionController::TestCase
- fixtures :backlog_items
- fixtures :users
-
- def setup
- @backlog_item = backlog_items(:owned_backlog_item)
- @task = @backlog_item.tasks.first
- @owner = @backlog_item.owner
- @non_owner = users(:jdonuts)
- @inactive_sprint_item = backlog_items(:owned_inactive_sprint_backlog_item)
-
- flunk "FIXTURES ARE BROKEN" if @owner.id == @non_owner.id
-
- @details = {
- :primary_id => @backlog_item.owner.id,
- :description => 'This is a new task.',
- :hours => '2.5',
- :when => Date.today
- }
- end
-
- # Ensures that an invalid user story causes create to fail.
- #
- def test_create_with_invalid_user_story
- get :create,
- nil,
- {:user_id => users(:mcpierce).id}
-
- assert_redirected_to error_path
-
- get :create,
- {:user_story => 9999},
- {:user_id => users(:mcpierce).id}
-
- assert_redirected_to error_path
- end
-
- # Ensures that an anonymous user cannot create a task.
- #
- def test_create_for_anonymous
- get :create,
- {:backlog_item => @backlog_item.id}
-
- assert_redirected_to :controller => :home, :action => :login
- end
-
- # Ensures that a user who doesn't have authorization aren't able to create
- # tasks.
- #
- def test_create_for_unauthorized_user
- get :create, {:backlog_item => @backlog_item.id}, {:user_id =>
users(:jdonuts).id}
-
- assert_redirected_to :controller => :backlog, :action => :view
- end
-
- # Ensures that tasks cannot be created for a backlog item on an non-active
- # sprint.
- #
- def test_create_for_nonactive_sprint
- count = @inactive_sprint_item.tasks.size
-
- get :create,
- {:backlog_item => @inactive_sprint_item.id},
- {:user_id => @inactive_sprint_item.owner.id}
-
- assert_redirected_to :controller => :backlog, :action => :view, :id =>
@inactive_sprint_item.id
- result = BacklogItem.find_by_id((a)inactive_sprint_item.id)
- assert_equal count, result.tasks.size, 'Tasks should not have been updated'
- end
-
- # Ensures that creating a task works as expected.
- #
- def test_create
- get :create,
- {
- :backlog_item => @backlog_item.id,
- :task => @details
- },
- {:user_id => users(:mcpierce).id}
-
- assert_response :success
- assert assigns['task'], 'Did not create a new task.'
- assert assigns['users'], 'Did not load users.'
- end
-
- # Ensures that tasks are saved corrected.
- #
- def test_create_as_save
- post :create,
- {
- :backlog_item => @backlog_item.id,
- :task => @details
- },
- {:user_id => users(:mcpierce).id}
-
- assert_redirected_to :controller => :backlog, :action => :view
- end
-
- # Ensures that attempting to modify an invalid task fails.
- #
- def test_modify_with_invalid_task
- get :modify, nil, {:user_id => users(:mcpierce).id}
-
- assert_redirected_to error_path
-
- get :modify, {:id => 9999}
-
- assert_redirected_to error_path
- end
-
- # Ensures that anonymous users cannot modify tasks.
- #
- def test_modify_for_anonymous
- get :modify, {:id => tasks(:created_login_view).id}
-
- assert_redirected_to :controller => :home, :action => :login
- end
-
- # Ensures that a user who's not the task owner or backup cannot modify the
- # task.
- #
- def test_modify_for_non_developer
- get :modify,
- {:id => tasks(:created_login_view).id},
- {:user_id => users(:project_admin).id}
-
- assert_redirected_to :controller => :backlog, :action => :view
- end
-
- # Ensures that the owner of the user story is allowed to edit a task against
- # that user story.
- #
- def test_modify_for_user_story_owner
- get :modify,
- {:id => tasks(:created_login_view).id},
- {:user_id => users(:mcpierce).id}
-
- assert_response :success
- end
-
- # Ensures that modifying works as expected.
- #
- def test_modify
- get :modify,
- {:id => tasks(:created_login_view).id},
- {:user_id => tasks(:created_login_view).primary_id}
-
- assert_response :success
- assert assigns['task'], 'Did not load the task.'
- assert_equal tasks(:created_login_view).id, assigns['task'].id, 'Did not
load the right task.'
- assert assigns['users'], 'Did not load the series.'
- end
-
- # Ensures that saving a task after modifying it works as expected.
- #
- def test_modify_as_save
- task = tasks(:created_login_view).attributes
-
- post :modify,
- {:id => tasks(:created_login_view), :task => task},
- {:user_id => tasks(:created_login_view).primary_id}
-
- assert_redirected_to :controller => :backlog, :action => :view
- end
-
- # Ensures that anonymous users can't delete tasks
- #
- def test_delete_as_anonymous
- get :delete
-
- assert_redirected_to :controller => :home, :action => :login
- end
-
- # Ensures that deletion requires a valid task id.
- #
- def test_delete_with_invalid_id
- post :delete,
- {:id => 9999},
- {:user_id => @owner.id}
-
- assert_redirected_to error_path
- end
-
- # Ensures that someone who is not the backlog item owner can't add tasks to
- # it.
- #
- def test_delete_as_non_owner
- post :delete,
- {
- :id => @task.id
- },
- {
- :user_id => @non_owner.id
- }
-
- assert Task.find_by_id((a)task.id), 'Task should not have been deleted.'
- end
-
- # Ensures that the primary can delete a task.
- #
- def test_delete
- post :delete,
- {
- :id => @task.id
- },
- {:user_id => @owner.id}
-
- assert_redirected_to(
- :controller => :backlog,
- :action => :view,
- :id => @task.backlog_item.id)
- assert_equal nil, Task.find_by_id((a)task.id), 'Did not delete the task.'
- end
-end
diff --git a/test/functional/tasks_controller_test.rb
b/test/functional/tasks_controller_test.rb
new file mode 100644
index 0000000..7e0360d
--- /dev/null
+++ b/test/functional/tasks_controller_test.rb
@@ -0,0 +1,313 @@
+# tasks_controller_test.rb
+# Copyright (C) 2008, Darryl L. Pierce <mcpierce(a)gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <
http://www.gnu.org/licenses/>.
+#
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+class TasksControllerTest < ActionController::TestCase
+ fixtures :backlog_items
+ fixtures :users
+
+ def setup
+ @backlog_item = backlog_items(:owned_backlog_item)
+ @task = @backlog_item.tasks.first
+ @owner = @backlog_item.owner
+ @nonowner = users(:jdonuts)
+ @inactive_sprint_item = backlog_items(:owned_inactive_sprint_backlog_item)
+
+ flunk "FIXTURES ARE BROKEN" if @owner.id == @nonowner.id
+
+ @details = {
+ :primary_id => @backlog_item.owner.id,
+ :description => 'This is a new task.',
+ :hours => '2.5',
+ :when => Date.today
+ }
+ end
+
+ # Ensures that viewing tasks when no backlog item is specified fails.
+ #
+ def test_index_without_backlog_item
+ get :index
+
+ assert_redirected_to error_url
+ end
+
+ # Ensures that getting the list of tasks for a backlog item works as expected.
+ #
+ def test_index
+ get :index, {:backlog_item => @backlog_item.id}
+
+ assert_response :success
+ assert assigns['backlog_item'], "Failed to load the backlog item."
+ assert_equal @backlog_item.id, assigns['backlog_item'].id,
+ "Did not load the right backlog item."
+ assert assigns['tasks'], "Failed to load the tasks."
+ end
+
+ # Ensures that an error is show if no task id is present.
+ #
+ def test_show_without_task_id
+ get :show
+
+ assert_redirected_to error_url
+ end
+
+ # Ensures that creating a task requires the user to be logged in.
+ #
+ def test_new_for_anonymous
+ get :new
+
+ assert_redirected_to login_url
+ end
+
+ # Ensures that creating a task without a backlog item fails.
+ #
+ def test_new_without_backlog_item
+ get :new, nil, {:user_id => @owner.id}
+
+ assert_redirected_to error_url
+ end
+
+ # Ensures that a non-owner cannot create tasks for a backlog item.
+ #
+ def test_new_for_nonowner
+ get :new,
+ {:backlog_item => @backlog_item.id},
+ {:user_id => @nonowner.id}
+
+ assert_redirected_to :controller => :backlog, :action => :view, :id =>
@backlog_item.id
+ end
+
+ # Ensures that creating a task works as expected.
+ #
+ def test_new
+ get :new,
+ {:backlog_item => @backlog_item.id},
+ {:user_id => @owner.id}
+
+ assert_response :success
+ assert assigns['task'], "Didn't create a task."
+ assert assigns['users'], "Didn't load the list of users."
+ assert_equal @backlog_item.id, assigns['task'].backlog_item_id,
+ "Didn't set the backlog item correctly."
+ assert_equal @owner.id, assigns['task'].primary_id,
+ "Didn't set the primary developer correctly."
+ end
+
+ # Ensures that attempting to modify an invalid task fails.
+ #
+ def test_edit_with_invalid_task
+ get :edit, nil, {:user_id => users(:mcpierce).id}
+
+ assert_redirected_to error_path
+
+ get :edit, {:id => 9999}
+
+ assert_redirected_to error_path
+ end
+
+ # Ensures that anonymous users cannot modify tasks.
+ #
+ def test_edit_for_anonymous
+ get :edit, {:id => tasks(:created_login_view).id}
+
+ assert_redirected_to :controller => :home, :action => :login
+ end
+
+ # Ensures that a user who's not the task owner or backup cannot modify the
+ # task.
+ #
+ def test_edit_for_non_developer
+ get :edit,
+ {:id => tasks(:created_login_view).id},
+ {:user_id => users(:project_admin).id}
+
+ assert_redirected_to :controller => :backlog, :action => :view
+ end
+
+ # Ensures that the owner of the user story is allowed to edit a task against
+ # that user story.
+ #
+ def test_edit_for_user_story_owner
+ get :edit,
+ {:id => tasks(:created_login_view).id},
+ {:user_id => users(:mcpierce).id}
+
+ assert_response :success
+ end
+
+ # Ensures that modifying works as expected.
+ #
+ def test_edit
+ get :edit,
+ {:id => tasks(:created_login_view).id},
+ {:user_id => tasks(:created_login_view).primary_id}
+
+ assert_response :success
+ assert assigns['task'], 'Did not load the task.'
+ assert_equal tasks(:created_login_view).id, assigns['task'].id, 'Did not
load the right task.'
+ assert assigns['users'], 'Did not load the series.'
+ end
+
+ # Ensures that an invalid user story causes create to fail.
+ #
+ def test_create_with_invalid_user_story
+ get :create,
+ nil,
+ {:user_id => users(:mcpierce).id}
+
+ assert_redirected_to error_path
+
+ get :create,
+ {:user_story => 9999},
+ {:user_id => users(:mcpierce).id}
+
+ assert_redirected_to error_path
+ end
+
+ # Ensures that an anonymous user cannot create a task.
+ #
+ def test_create_for_anonymous
+ get :create,
+ {:backlog_item => @backlog_item.id}
+
+ assert_redirected_to :controller => :home, :action => :login
+ end
+
+ # Ensures that a user who doesn't have authorization aren't able to create
+ # tasks.
+ #
+ def test_create_for_unauthorized_user
+ get :create, {:backlog_item => @backlog_item.id}, {:user_id =>
users(:jdonuts).id}
+
+ assert_redirected_to :controller => :backlog, :action => :view, :id =>
@backlog_item
+ end
+
+ # Ensures that tasks cannot be created for a backlog item on an non-active
+ # sprint.
+ #
+ def test_create_for_nonactive_sprint
+ count = @inactive_sprint_item.tasks.size
+
+ get :create,
+ {:backlog_item => @inactive_sprint_item.id},
+ {:user_id => @inactive_sprint_item.owner.id}
+
+ assert_redirected_to :controller => :backlog, :action => :view, :id =>
@inactive_sprint_item.id
+ result = BacklogItem.find_by_id((a)inactive_sprint_item.id)
+ assert_equal count, result.tasks.size, 'Tasks should not have been updated'
+ end
+
+ # Ensures that tasks are saved corrected.
+ #
+ def test_create
+ post :create,
+ {
+ :backlog_item => @backlog_item.id,
+ :task => @details
+ },
+ {:user_id => users(:mcpierce).id}
+
+ assert_redirected_to :controller => :backlog, :action => :view, :id =>
@backlog_item
+ end
+
+ # Ensures that anonymous users can't delete tasks
+ #
+ def test_delete_as_anonymous
+ get :delete
+
+ assert_redirected_to :controller => :home, :action => :login
+ end
+
+ # Ensures that deletion requires a valid task id.
+ #
+ def test_delete_with_invalid_id
+ post :delete,
+ {:id => 9999},
+ {:user_id => @owner.id}
+
+ assert_redirected_to error_path
+ end
+
+ # Ensures that someone who is not the backlog item owner can't add tasks to
+ # it.
+ #
+ def test_delete_as_non_owner
+ post :delete,
+ {
+ :id => @task.id
+ },
+ {
+ :user_id => @nonowner.id
+ }
+
+ assert Task.find_by_id((a)task.id), 'Task should not have been deleted.'
+ end
+
+ # Ensures that the primary can delete a task.
+ #
+ def test_delete
+ post :delete,
+ {
+ :id => @task.id
+ },
+ {:user_id => @owner.id}
+
+ assert_redirected_to(
+ :controller => :backlog,
+ :action => :view,
+ :id => @task.backlog_item.id)
+ assert_equal nil, Task.find_by_id((a)task.id), 'Did not delete the task.'
+ end
+
+ # Ensures that an update requires the user be loggeg in.
+ #
+ def test_update_as_anonymous
+ put :update
+
+ assert_redirected_to login_url
+ end
+
+ # Ensures that an update fails without a task id.
+ #
+ def test_update_without_id
+ put :update, {}, {:user_id => @owner.id}
+
+ assert_redirected_to error_url
+ end
+
+ # Ensures that an update fails with an invalid id.
+ #
+ def test_update_with_invalid_id
+ put :update,
+ {:id => 9999},
+ {:user_id => @owner.id}
+ end
+
+ # Ensures that a non-owner cannot update a task.
+ #
+ def test_update_as_nonowner
+ put :update,
+ {:id => @task.id, :task => @task.attributes},
+ {:user_id => @nonowner.id}
+
+ assert_redirected_to :controller => :backlog, :action => :view, :id =>
@backlog_item
+ result = Task.find_by_id((a)task.id)
+ assert_equal @task.updated_at, result.updated_at,
+ "Task should not have been updated."
+ end
+end
diff --git a/test/unit/product_test.rb b/test/unit/product_test.rb
index a0df74d..62647db 100644
--- a/test/unit/product_test.rb
+++ b/test/unit/product_test.rb
@@ -25,7 +25,8 @@ class ProductTest < ActiveSupport::TestCase
def setup
@new_product = Product.new(
:project_id => projects(:cairo).id,
- :owner_id => users(:mcpierce).id)
+ :owner_id => users(:mcpierce).id,
+ :name => "Test Product")
@product = products(:cairo_web)
@owner = @product.owner
--
1.6.0.2