Merge pull request #530 from opf/bugfix/416_possible_watchers

pull/532/head
Hagen Schink 11 years ago
commit d0d5c5a02e
  1. 2
      app/models/watcher.rb
  2. 2
      lib/plugins/acts_as_watchable/lib/acts_as_watchable.rb
  3. 2
      spec/factories/project_factory.rb
  4. 12
      spec/factories/user_factory.rb
  5. 148
      spec/models/work_package/work_package_acts_as_watchable_spec.rb
  6. 96
      spec/models/work_package/work_package_watcher_spec.rb

@ -57,11 +57,13 @@ class Watcher < ActiveRecord::Base
protected
def validate_active_user
# TODO add informative error message
return if user.blank?
errors.add :user_id, :invalid unless user.active?
end
def validate_user_allowed_to_watch
# TODO add informative error message
return if user.blank? || watchable.blank?
errors.add :user_id, :invalid unless watchable.possible_watcher?(user)
end

@ -86,7 +86,7 @@ module Redmine
end
def possible_watcher_users
User.all.tap do |users|
User.not_builtin.tap do |users|
if respond_to?(:visible?)
users.select! {|user| possible_watcher?(user)}
else

@ -40,7 +40,7 @@ FactoryGirl.define do
end
factory :public_project do
is_public true
is_public true # Remark: is_public defaults to true
end
factory :project_with_types do

@ -29,9 +29,9 @@
FactoryGirl.define do
factory :user do
ignore do
member_in_project nil
member_in_projects nil
member_through_role nil
member_in_project nil
member_in_projects nil
member_through_role nil
end
firstname 'Bob'
lastname 'Bobbit'
@ -75,7 +75,7 @@ FactoryGirl.define do
factory :deleted_user, :class => DeletedUser do
status User::STATUSES[:builtin]
end
factory :locked_user do
firstname 'Locked'
lastname 'User'
@ -83,7 +83,7 @@ FactoryGirl.define do
sequence(:mail) {|n| "bob#{n}.bobbit@bob.com" }
password 'adminADMIN!'
password_confirmation 'adminADMIN!'
status User::STATUSES[:locked]
end
status User::STATUSES[:locked]
end
end
end

@ -0,0 +1,148 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2013 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# 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 2
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
describe WorkPackage do
let(:project) { FactoryGirl.create(:project) }
let(:work_package) { FactoryGirl.create(:work_package,
project: project) }
let(:role) { FactoryGirl.create(:role, permissions: [:view_work_packages]) }
let(:non_member_user) { FactoryGirl.create(:user) }
let(:project_member) { FactoryGirl.create(:user, member_in_project: project, member_through_role: role) }
let!(:watching_user) do
FactoryGirl.create(:user, member_in_project: project, member_through_role: role).tap {|user| Watcher.create(watchable: work_package, user: user)}
end
describe '#possible_watcher_users' do
subject { work_package.possible_watcher_users }
let!(:admin){ FactoryGirl.create(:admin) }
let!(:anonymous_user){ FactoryGirl.create(:anonymous) }
shared_examples 'it provides possible watchers' do
example 'and contains exactly those users who are allowed to view work packages' do
users_allowed_to_view_work_packages = User.all.select{ |u| u.allowed_to?(:view_work_packages, project) }
work_package.possible_watcher_users.sort.should == Array.wrap(users_allowed_to_view_work_packages).sort
end
end
shared_context 'non member role has the permission to view work packages' do
let(:non_member_role) { Role.find_by_name('Non member') }
before do
non_member_role.add_permission! :view_work_packages
end
end
shared_context 'anonymous role has the permission to view work packages' do
let!(:anonymous_role) { FactoryGirl.create :anonymous_role, permissions: [:view_work_packages] } # 'project granting candidate' for anonymous user
end
context 'when it is a public project' do
it_behaves_like 'it provides possible watchers'
it { should include(admin) }
it { should include(project_member) }
context 'and the non member role has the permission to view work packages' do
include_context 'non member role has the permission to view work packages'
it { should include(non_member_user) }
end
context 'and the anonymous role has the permission to view work packages' do
include_context 'anonymous role has the permission to view work packages'
it { should_not include(anonymous_user) }
end
end
context 'when it is a private project' do
include_context 'non member role has the permission to view work packages'
include_context 'anonymous role has the permission to view work packages'
before do
project.update_attributes is_public: false
work_package.reload
end
it_behaves_like 'it provides possible watchers'
it { should include(project_member) }
it { should include(admin) }
it { should_not include(non_member_user) }
it { should_not include(anonymous_user) }
end
end
describe '#watcher_recipients' do
subject { work_package.watcher_recipients }
it { should include(watching_user.mail) }
context 'when the permission to view work packages has been removed' do
before do
role.remove_permission! :view_work_packages
work_package.reload
end
it { should_not include(watching_user.mail) }
end
end
describe '#watched_by?' do
subject { work_package.watched_by?(watching_user) }
context 'when the permission to view work packages has been removed' do
# an existing watcher shouldn't be removed
before do
role.remove_permission! :view_work_packages
work_package.reload
end
it { should be_true }
end
end
context 'notifications' do
let(:number_of_recipients) { (work_package.recipients | work_package.watcher_recipients).length }
before :each do
Delayed::Worker.delay_jobs = false
end
it 'sends one delayed mail notification for each watcher recipient' do
UserMailer.stub_chain :issue_updated, :deliver
UserMailer.should_receive(:issue_updated).exactly(number_of_recipients).times
work_package.update_attributes :description => 'Any new description'
end
end
end

@ -1,96 +0,0 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2013 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# 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 2
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
describe WorkPackage do
describe :watcher do
let(:user) { FactoryGirl.create(:user) }
let(:project) { FactoryGirl.create(:project) }
let(:role) { FactoryGirl.create(:role,
permissions: [:view_work_packages]) }
let(:project_member) { FactoryGirl.create(:member,
project: project,
principal: user,
roles: [role]) }
let(:work_package) { FactoryGirl.create(:work_package,
project: project) }
let!(:user_allowed_to_view_work_packages) do
FactoryGirl.create(:user).tap { |user| project.add_member!(user, role) }
end
context :recipients do
let(:watcher) { Watcher.new(watchable: work_package,
user: user) }
before do
project_member
watcher.save!
role.remove_permission! :view_work_packages
work_package.reload
end
context :watcher do
subject { work_package.watched_by?(user) }
it { should be_true }
end
context :recipients do
subject { work_package.watcher_recipients }
it { should_not include(user.mail) }
end
end
context '#possible_watcher_users' do
it 'contains exactly those users who are allowed to view work packages' do
work_package.possible_watcher_users.should == [user_allowed_to_view_work_packages]
end
end
context 'notifications' do
let(:number_of_recipients) { (work_package.recipients | work_package.watcher_recipients).length }
before :each do
Delayed::Worker.delay_jobs = false
end
it 'sends one delayed mail notification for each possible watcher' do
UserMailer.stub_chain :issue_updated, :deliver
UserMailer.should_receive(:issue_updated).exactly(number_of_recipients).times
work_package.update_attributes :description => 'Any new description'
end
end
end
end
Loading…
Cancel
Save