This patch requires a migration as it adds a new table, notifications,
to the project.
Added a new action to the users controller, called notifications,
that takes posted data to update the user's notifications.
From the dashboard the user can select to view their profile. On
the profile page are options for selecting notification types.
Side tasks:
Removed the "Owner" column from the user view since it's redundant
to show the owner's name when it's the owner that's being viewed.
Refactored the BacklogItem.closed? to be BacklogItem.completed? since
the item state is actually STATE_COMPLETED.
Fixed a ton of unit tests that were broken by a refactoring exercise.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/sprints_controller.rb | 2 +
app/controllers/users_controller.rb | 31 +++++++++++-
app/models/backlog_item.rb | 2 +-
app/models/notifications.rb | 2 +
app/models/user.rb | 1 +
app/models/user_mailer.rb | 9 +++
app/views/home/dashboard.html.erb | 6 ++-
app/views/items/_list.html.erb | 17 +++++--
app/views/user_mailer/daily_updates.html.erb | 28 ++++++++++
app/views/users/_notifications.html.erb | 29 +++++++++++
app/views/users/show.html.erb | 7 ++-
config/initializers/schedules.rb | 69 +++++++++++++++++++++++---
config/routes.rb | 2 +-
config/schedules.yml.example | 11 +++--
db/migrate/020_create_notifications.rb | 19 +++++++
db/schema.rb | 30 ++++++++++-
public/stylesheets/lists.css | 2 +-
test/fixtures/notifications.yml | 6 ++
test/functional/tasks_controller_test.rb | 4 +-
test/functional/user_items_test.rb | 2 +-
test/functional/users_controller_test.rb | 40 ++++++++++++++-
test/unit/backlog_item_test.rb | 3 +-
test/unit/notifications_test.rb | 8 +++
23 files changed, 299 insertions(+), 31 deletions(-)
create mode 100644 app/models/notifications.rb
create mode 100644 app/views/user_mailer/daily_updates.html.erb
create mode 100644 app/views/users/_notifications.html.erb
create mode 100644 db/migrate/020_create_notifications.rb
create mode 100644 test/fixtures/notifications.yml
create mode 100644 test/unit/notifications_test.rb
diff --git a/app/controllers/sprints_controller.rb
b/app/controllers/sprints_controller.rb
index 713d330..09ebe5b 100644
--- a/app/controllers/sprints_controller.rb
+++ b/app/controllers/sprints_controller.rb
@@ -129,6 +129,8 @@ class SprintsController < ApplicationController
if @sprint.can_populate?(@user)
@title = "Sprint #{(a)sprint.id} (Planning)"
@user_stories = UserStory.find_all_by_product_id((a)product.id)
+ @selected = []
+ @estimates = {}
format.html
else
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 1c58dbf..3ed21e4 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -16,7 +16,7 @@
# +UsersController+ allows for CRUD operations on instances of +User+.
class UsersController < ApplicationController
- before_filter :authenticated, :except => [:index, :show, :new, :create, :backlog,
:roles]
+ before_filter :authenticated, :only => [:edit, :update, :verify, :notifications]
before_filter :load_this_user, :except => [:index, :new, :create]
# GET /users
@@ -31,6 +31,11 @@ class UsersController < ApplicationController
# GET /users/1
def show
@title = "#{(a)this_user.display_name}"
+ @backlog_items = BacklogItem.paginate(
+ :conditions => ['owner_id = ?', @this_user.id],
+ :page => params[:page],
+ :per_page => 10
+ )
end
# GET /users/new
@@ -59,6 +64,7 @@ class UsersController < ApplicationController
if (@user == nil) || (@user.create_users?)
@this_user = User.new(params[:user])
@this_user.privileges = UserPrivilege.new
+ @this_user.notifications = Notifications.new
@this_user.verification = UserVerification.new(
:sent => Date.today,
:token => UserVerification.create_token)
@@ -151,11 +157,32 @@ class UsersController < ApplicationController
:per_page => 10)
end
+ # POST /users/1/notifications
+ def notifications
+ respond_to do |format|
+ if @user.id == @this_user.id
+ Notifications.transaction do
+ @this_user.notifications.update_attributes(params[:notifications])
+
+ if @this_user.notifications.save
+ flash[:message] = "Notifications updated."
+ else
+ flash[:error] = "Unable to update notifications."
+ end
+
+ format.html { redirect_to user_path(@this_user) }
+ end
+ else
+ flash[:error] = "You cannot alter notifications for
#{(a)this_user.display_name}."
+ format.html { redirect_to user_path(@this_user) }
+ end
+ end
+ end
+
private
def load_this_user
@this_user = User.find_by_id(params[:id])
- @backlog_items = @this_user.backlog if @this_user
unless @this_user
flash[:error] = "Missing or invalid user."
diff --git a/app/models/backlog_item.rb b/app/models/backlog_item.rb
index 5a88800..4fd4501 100644
--- a/app/models/backlog_item.rb
+++ b/app/models/backlog_item.rb
@@ -94,7 +94,7 @@ class BacklogItem < ActiveRecord::Base
end
# Reports if the task is closed.
- def closed?
+ def completed?
state == STATE_COMPLETED
end
diff --git a/app/models/notifications.rb b/app/models/notifications.rb
new file mode 100644
index 0000000..199a196
--- /dev/null
+++ b/app/models/notifications.rb
@@ -0,0 +1,2 @@
+class Notifications < ActiveRecord::Base
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index bdd1514..613b7ad 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -30,6 +30,7 @@ class User < ActiveRecord::Base
has_many :product_roles, :dependent => :destroy
has_one :verification, :class_name => "UserVerification", :dependent =>
:destroy
has_many :backlog, :class_name => "BacklogItem", :foreign_key =>
'owner_id'
+ has_one :notifications, :dependent => :destroy
attr_accessor :password_confirmation
validates_confirmation_of :password,
diff --git a/app/models/user_mailer.rb b/app/models/user_mailer.rb
index 200edcb..e830463 100644
--- a/app/models/user_mailer.rb
+++ b/app/models/user_mailer.rb
@@ -57,6 +57,15 @@ class UserMailer < ActionMailer::Base
body :role => role
end
+ # Sends an email to a user letting him know his daily activities.
+ def daily_updates(user, open_items, completed_items, task_performed)
+ recipients user.email
+ from MAIL_CONFIG[:from]
+ subject "Daily updates for #{user.display_name}"
+ body :user => user, :open_items => open_items,
+ :completed_items => completed_items, :tasks_performed =>
task_performed
+ end
+
# Send an email to a user to notify him that no activity has been detected in
# his backlog.
def no_activity_recorded(user, backlog_items)
diff --git a/app/views/home/dashboard.html.erb b/app/views/home/dashboard.html.erb
index b41ccbf..32f1913 100644
--- a/app/views/home/dashboard.html.erb
+++ b/app/views/home/dashboard.html.erb
@@ -1,7 +1,9 @@
<div>
-
+
+ <p>View your <%= link_to "profile", user_path(@user)
%>.</p>
+
<p>You have <%= @backlog.size %> tasks in
<%= link_to "your backlog", backlog_user_path(@user) %>.
</p>
-
+
</div>
diff --git a/app/views/items/_list.html.erb b/app/views/items/_list.html.erb
index 0379bb1..a07fa3e 100644
--- a/app/views/items/_list.html.erb
+++ b/app/views/items/_list.html.erb
@@ -2,7 +2,10 @@
<colgroup>
<col class="row_id" />
<col class="description" />
- <col class="user" />
+
+ <% unless @this_user %>
+ <col class="user" />
+ <% end %>
<% unless @sprint %>
<col class="number" />
@@ -15,12 +18,15 @@
<thead>
<tr>
- <th class="title" colspan="<%= @sprint ? 6 : 7
%>">Backlog Items</th>
+ <th class="title" colspan="<%= 7 - (@sprint ? 1 : 0) -
(@this_user ? 1 : 0) %>">Backlog Items</th>
</tr>
<tr>
<th>#</th>
<th>Title</th>
- <th>Owner</th>
+
+ <% unless @this_user %>
+ <th>Owner</th>
+ <% end %>
<% unless @sprint %>
<th>Sprint</th>
@@ -49,7 +55,10 @@
product_sprint_item_path(product, sprint, item) %>
</td>
<td><%= item.user_story.title %></td>
- <td><%= link_to(item.owner.display_name, user_path(item.owner)) if
item.owner %></td>
+
+ <% unless @this_user %>
+ <td><%= link_to(item.owner.display_name, user_path(item.owner)) if
item.owner %></td>
+ <% end %>
<% unless @sprint %>
<td>
diff --git a/app/views/user_mailer/daily_updates.html.erb
b/app/views/user_mailer/daily_updates.html.erb
new file mode 100644
index 0000000..7b6d5b3
--- /dev/null
+++ b/app/views/user_mailer/daily_updates.html.erb
@@ -0,0 +1,28 @@
+Here are your daily updates:
+
+Tasks performed:
+<% if !@tasks_performed || @tasks_performed.empty? %>
+ None.
+<% else %>
+ <% @tasks_performed.each_with_index do |task, index| %>
+ <%= "#{index + 1} (#{task.hours} Hours) #{task.description}" %>
+ <% end %>
+<% end %>
+
+Open backlog items:
+<% if !@open_items || @open_items.empty? %>
+ None.
+<% else %>
+ <% @open_items.each_with_index do |item, index| %>
+ <%= "#{index + 1} #{item.user_story.title}" %>
+ <% end %>
+<% end %>
+
+Closed backlog items:
+<% if !@completed_items || @completed_items.empty? %>
+ None.
+<% else %>
+ <% @completed_items.each_with_index do |item, index| %>
+ <%= "#{index + 1} #{item.user_story.title}" %>
+ <% end %>
+<% end %>
diff --git a/app/views/users/_notifications.html.erb
b/app/views/users/_notifications.html.erb
new file mode 100644
index 0000000..06b34fb
--- /dev/null
+++ b/app/views/users/_notifications.html.erb
@@ -0,0 +1,29 @@
+<% form_for(:notifications, @this_user.notifications, :url =>
notifications_user_path(@this_user)) do |form| %>
+
+ <table class="edit">
+ <thead>
+ <tr>
+ <th class="title" colspan="2">Email
Notifications</th>
+ </tr>
+ </thead>
+
+ <tbody>
+ <tr>
+ <td class="label">Daily scrum email</td>
+ <td class="value"><%= form.check_box :daily_updates
%></td>
+ </tr>
+
+ <tr>
+ <td class="label">Task reminders</td>
+ <td class="value"><%= form.check_box :task_reminders %>
+ </tr>
+
+ <tr>
+ <td class="buttons" colspan="2">
+ <%= submit_tag "Update" %>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+<% end %>
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb
index 4fa4cf1..2c4af66 100644
--- a/app/views/users/show.html.erb
+++ b/app/views/users/show.html.erb
@@ -26,4 +26,9 @@
</tbody>
</table>
-<%= render(:partial => 'items/list') %>
+<% if @this_user.can_edit?(@user) %>
+ <%= render :partial => 'notifications' %>
+<% end %>
+
+<%= will_paginate @backlog_items %>
+<%= render :partial => 'items/list' %>
diff --git a/config/initializers/schedules.rb b/config/initializers/schedules.rb
index 9239cd9..f2bb039 100644
--- a/config/initializers/schedules.rb
+++ b/config/initializers/schedules.rb
@@ -8,9 +8,56 @@ raise "Schedule configuration file not found at
#{schedules_file_path}" unless F
SCHEDULES_CONFIG = YAML.load(File.open(schedules_file_path))
# Initialize a threads array
-threads = []
+threads = {}
-threads << Thread.new do
+threads["daily updates"] = Thread.new do
+ scheduler = Scheduler.new
+ scheduler.start
+
+ hours = SCHEDULES_CONFIG[:daily_updates][:hours]
+ minutes = SCHEDULES_CONFIG[:daily_updates][:minutes]
+
+ scheduler.schedule("#{minutes} #{hours} * * *") do
+ open_items = {}
+ completed_items = {}
+ tasks_performed = {}
+
+ BacklogItem.find(:all).each do |item|
+ owner = item.owner
+
+ if item.completed? && item.updated_at.to_date == Date.yesterday
+ completed_items[owner] ||= []
+ completed_items[owner] << item
+ elsif item.owner
+ open_items[owner] ||= []
+ open_items[owner] << item
+ end
+ end
+
+ Task.find(:all).each do |task|
+ if task.when_entered.to_date == Date.yesterday
+ tasks_performed[task.primary] ||= []
+ tasks_performed[task.primary] << task
+
+ if task.backup
+ tasks_performed[task.backup] ||= []
+ tasks_performed[task.backup] << task
+ end
+ end
+ end
+
+ User.find(:all).each do |user|
+ if user.notifications.daily_updates
+ UserMailer.deliver_daily_updates(user, open_items[user],
+ completed_items[user], tasks_performed[user])
+ end
+ end
+ end
+
+ scheduler.join
+end
+
+threads["daily reminders"] = Thread.new do
scheduler = Scheduler.new
scheduler.start
@@ -45,11 +92,11 @@ threads << Thread.new do
# Send the e-mail
user_no_activity_on_backlog_items.each do |owner, backlog_items|
- UserMailer.deliver_no_activity_recorded(owner, backlog_items)
+ UserMailer.deliver_no_activity_recorded(owner, backlog_items) if
owner.notifications.task_reminders
end
user_no_tasks_on_backlog_items.each do |owner, backlog_items|
- UserMailer.deliver_no_task_recorded(owner, backlog_items)
+ UserMailer.deliver_no_task_recorded(owner, backlog_items) if
owner.notifications.task_reminders
end
end
@@ -57,7 +104,7 @@ threads << Thread.new do
scheduler.join
end
-threads << Thread.new do
+threads["product status"] = Thread.new do
scheduler = Scheduler.new
scheduler.start
@@ -81,7 +128,7 @@ threads << Thread.new do
scheduler.join
end
-threads << Thread.new do
+threads["user verification expiration"] = Thread.new do
scheduler = Scheduler.new
scheduler.start
@@ -114,4 +161,12 @@ threads << Thread.new do
end
# Run all threads
-threads.each { |thread| thread.run }
+threads.each_pair do |key, thread|
+ puts "Starting scheduler for \"#{key}\"..."
+
+ begin
+ thread.run
+ rescue Exception => error
+ puts "Error starting thread: #{error.message}"
+ end
+end
diff --git a/config/routes.rb b/config/routes.rb
index d4d2ec6..25bac9c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -30,7 +30,7 @@ ActionController::Routing::Routes.draw do |map|
}
end
end
- map.resources :users, :member => {:backlog => :get, :roles => :get} do |user|
+ map.resources :users, :member => {:backlog => :get, :roles => :get,
:notifications => :post} do |user|
user.resources :tasks
end
diff --git a/config/schedules.yml.example b/config/schedules.yml.example
index 75741b4..88d55a7 100644
--- a/config/schedules.yml.example
+++ b/config/schedules.yml.example
@@ -1,10 +1,13 @@
---
:no_activity_or_no_task_recorded_time:
- :hours: 5
+ :hours: 3
:minutes: 0
+ :daily_updates:
+ :hours: 3
+ :minutes: 15
:sprints_products_status_time:
- :hours: 5
- :minutes: 0
+ :hours: 3
+ :minutes: 30
:user_verification_expiration:
:hours: 3
- :minutes: 0
+ :minutes: 45
diff --git a/db/migrate/020_create_notifications.rb
b/db/migrate/020_create_notifications.rb
new file mode 100644
index 0000000..11f9643
--- /dev/null
+++ b/db/migrate/020_create_notifications.rb
@@ -0,0 +1,19 @@
+class CreateNotifications < ActiveRecord::Migration
+ def self.up
+ create_table :notifications do |t|
+ t.integer :user_id
+ t.boolean :task_reminders
+ t.boolean :daily_updates
+
+ t.timestamps
+ end
+
+ User.find(:all).each do |user|
+ user .notifications = Notifications.new(:task_reminders => true, :daily_updates
=> true)
+ end
+ end
+
+ def self.down
+ drop_table :notifications
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index aec15d9..6215516 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -9,7 +9,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 19) do
+ActiveRecord::Schema.define(:version => 20) do
create_table "backlog_items", :force => true do |t|
t.integer "sprint_id",
:null => false
@@ -23,6 +23,15 @@ ActiveRecord::Schema.define(:version => 19) do
end
add_index "backlog_items", ["sprint_id",
"user_story_id"], :name =>
"index_backlog_items_on_sprint_id_and_user_story_id", :unique => true
+ add_index "backlog_items", ["user_story_id"], :name =>
"fk_backlog_items_user_story"
+
+ create_table "notifications", :force => true do |t|
+ t.integer "user_id"
+ t.boolean "task_reminders"
+ t.boolean "daily_updates"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
create_table "product_roles", :force => true do |t|
t.integer "user_id", :null => false
@@ -34,7 +43,9 @@ ActiveRecord::Schema.define(:version => 19) do
t.boolean "is_approved", :default => false
end
- add_index "product_roles", ["product_id", "user_id"],
:name => "index_product_roles_on_user_id_and_product_id", :unique => true
+ add_index "product_roles", ["user_id", "product_id"],
:name => "index_product_roles_on_user_id_and_product_id", :unique => true
+ add_index "product_roles", ["product_id"], :name =>
"fk_user_role_product"
+ add_index "product_roles", ["role_id"], :name =>
"fk_user_role_role"
create_table "products", :force => true do |t|
t.integer "project_id"
@@ -46,6 +57,7 @@ ActiveRecord::Schema.define(:version => 19) do
end
add_index "products", ["name"], :name =>
"index_products_on_name", :unique => true
+ add_index "products", ["project_id"], :name =>
"fk_products_project"
create_table "projects", :force => true do |t|
t.integer "owner_id", :null => false
@@ -57,6 +69,7 @@ ActiveRecord::Schema.define(:version => 19) do
end
add_index "projects", ["name"], :name =>
"index_projects_on_name", :unique => true
+ add_index "projects", ["owner_id"], :name =>
"fk_product_owner"
create_table "remaining_hours_estimates", :force => true do |t|
t.integer "backlog_item_id", :null =>
false
@@ -67,6 +80,9 @@ ActiveRecord::Schema.define(:version => 19) do
t.datetime "estimated_on", :null =>
false
end
+ add_index "remaining_hours_estimates", ["backlog_item_id"], :name
=> "fk_remaining_hours_item"
+ add_index "remaining_hours_estimates", ["user_id"], :name =>
"fk_remaining_hours_user"
+
create_table "roles", :force => true do |t|
t.string "name", :null =>
false
t.boolean "can_manage_backlog_items", :default => false, :null =>
false
@@ -98,6 +114,8 @@ ActiveRecord::Schema.define(:version => 19) do
t.integer "status", :default => 0, :null =>
false
end
+ add_index "sprints", ["product_id"], :name =>
"fk_sprint_product"
+
create_table "tasks", :force => true do |t|
t.integer "backlog_item_id",
:null => false
t.integer "primary_id",
:null => false
@@ -109,6 +127,10 @@ ActiveRecord::Schema.define(:version => 19) do
t.datetime "updated_at"
end
+ add_index "tasks", ["backlog_item_id"], :name =>
"fk_task_backlog_item"
+ add_index "tasks", ["primary_id"], :name =>
"fk_task_primary"
+ add_index "tasks", ["backup_id"], :name =>
"fk_task_backup"
+
create_table "user_privileges", :force => true do |t|
t.integer "user_id", :null => false
t.boolean "admin_projects", :default => false, :null => false
@@ -117,6 +139,8 @@ ActiveRecord::Schema.define(:version => 19) do
t.datetime "updated_at"
end
+ add_index "user_privileges", ["user_id"], :name =>
"fk_privilege_user"
+
create_table "user_stories", :force => true do |t|
t.integer "product_id"
t.integer "priority"
@@ -127,6 +151,8 @@ ActiveRecord::Schema.define(:version => 19) do
t.datetime "updated_at"
end
+ add_index "user_stories", ["product_id"], :name =>
"fk_user_story_product"
+
create_table "user_verifications", :force => true do |t|
t.integer "user_id", :null => false
t.string "token", :limit => 16, :null => false
diff --git a/public/stylesheets/lists.css b/public/stylesheets/lists.css
index 4db910b..c5942c9 100644
--- a/public/stylesheets/lists.css
+++ b/public/stylesheets/lists.css
@@ -28,7 +28,7 @@ col.name {
}
col.description {
-
+ width: 100%;
}
col.number {
diff --git a/test/fixtures/notifications.yml b/test/fixtures/notifications.yml
new file mode 100644
index 0000000..ac0dd71
--- /dev/null
+++ b/test/fixtures/notifications.yml
@@ -0,0 +1,6 @@
+<% User.find(:all).each do |user| %>
+ <%= "#{user.id}_notifications:" %>
+ user_id: <%= user.id %>
+ task_reminders: false
+ daily_updates: false
+ <% end %>
diff --git a/test/functional/tasks_controller_test.rb
b/test/functional/tasks_controller_test.rb
index 666fa4e..e2ed4a5 100644
--- a/test/functional/tasks_controller_test.rb
+++ b/test/functional/tasks_controller_test.rb
@@ -30,13 +30,13 @@ class TasksControllerTest < ActionController::TestCase
raise "Task must be owned by the user!" unless @task.primary_id ==
@user.id
@item = @task.backlog_item
- raise "Item cannot be closed!" if @item.closed?
+ raise "Item cannot be closed!" if @item.completed?
@sprint = @item.sprint
@product = @sprint.product
@closed_item = backlog_items(:closed_backlog_item)
- raise "Item must be closed!" unless @closed_item.closed?
+ raise "Item must be closed!" unless @closed_item.completed?
@owner = @item.owner
@nonowner = users(:jdonuts)
diff --git a/test/functional/user_items_test.rb b/test/functional/user_items_test.rb
index 628cd35..ef4354d 100644
--- a/test/functional/user_items_test.rb
+++ b/test/functional/user_items_test.rb
@@ -61,7 +61,7 @@ class UserItemsTest < ActionController::TestCase
raise "Item does not belong to sprint!" unless @unowned_item.sprint_id ==
@sprint.id
@closed_item = backlog_items(:closed_backlog_item)
- raise "item must not be active!" unless @closed_item.closed?
+ raise "item must not be active!" unless @closed_item.completed?
raise "Item does not belong to sprint!" unless @closed_item.sprint_id ==
@sprint.id
@member = users(:mcpierce)
diff --git a/test/functional/users_controller_test.rb
b/test/functional/users_controller_test.rb
index 7375369..cebc450 100644
--- a/test/functional/users_controller_test.rb
+++ b/test/functional/users_controller_test.rb
@@ -17,6 +17,7 @@
require File.dirname(__FILE__) + '/../test_helper'
class UsersControllerTest < ActionController::TestCase
+ fixtures :notifications
fixtures :user_verifications
fixtures :users
@@ -160,8 +161,11 @@ class UsersControllerTest < ActionController::TestCase
post :create, {:user => @new_user}, {:user_id => @admin.id}
assert_redirected_to user_path(assigns['this_user'])
- assert User.find_by_email(@new_user[:email]),
- "A new user should have been created."
+ result = User.find_by_email(@new_user[:email])
+
+ assert result, "A new user should have been created."
+ assert result.privileges, "No privileges were created."
+ assert result.notifications, "No notifications were created."
email = @emails.first
assert email, "No email was generated."
@@ -309,4 +313,36 @@ class UsersControllerTest < ActionController::TestCase
assert_response :success
assert assigns['product_roles'], "Failed to load the user's
roles."
end
+
+ # Ensures that notifications updates require the user be logged in.
+ def test_notifications_as_anonymous
+ post :notifications
+
+ assert_redirected_to login_path
+ end
+
+ # Ensures that a valid user's required.
+ def test_notifications_with_invalid_user
+ post :notifications, {}, {:user_id => @user.id}
+
+ assert_redirected_to users_path
+ end
+
+ # Ensures that a user cannot edit someone else's notifications.
+ def test_notifications_for_other_user
+ post :notifications, {:id => @other_user.id}, {:user_id => @user.id}
+
+ assert_redirected_to user_path(@other_user)
+ end
+
+ # Ensures that notifications are updated.
+ def test_notifications
+ post :notifications,
+ {:id => @user.id, :notifications => {:task_reminders => true}},
+ {:user_id => @user.id}
+
+ assert_redirected_to user_path(@user)
+ assert Notifications.find_by_user_id((a)user.id).task_reminders,
+ "Notification update should've been saved."
+ end
end
diff --git a/test/unit/backlog_item_test.rb b/test/unit/backlog_item_test.rb
index afe4669..c80c54a 100644
--- a/test/unit/backlog_item_test.rb
+++ b/test/unit/backlog_item_test.rb
@@ -26,7 +26,8 @@ class BacklogItemTest < ActiveSupport::TestCase
def setup
@item = BacklogItem.new(
:sprint_id => sprints(:active_sprint).id,
- :user_story_id => user_stories(:create_login).id)
+ :user_story_id => user_stories(:create_login).id,
+ :estimated_hours => 5.0)
@owned_backlog_item = backlog_items(:owned_backlog_item)
raise "Owned item must have an owner!" unless @owned_backlog_item.owner
diff --git a/test/unit/notifications_test.rb b/test/unit/notifications_test.rb
new file mode 100644
index 0000000..d515277
--- /dev/null
+++ b/test/unit/notifications_test.rb
@@ -0,0 +1,8 @@
+require 'test_helper'
+
+class NotificationsTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ def test_truth
+ assert true
+ end
+end
--
1.6.0.2